From fbadb9202d650a76b696844f7dd6697005746a36 Mon Sep 17 00:00:00 2001 From: sam Date: Fri, 28 Nov 2008 00:48:05 +0000 Subject: [PATCH] Update to later code from my repository: o many bug fixes o add new periodic calibration api o break up 5416 periodic calibration code in preparation for 928x o move get noise floor to rf backends o 5416-specific ani (still disabled) o modularize 5210 eeprom format a la other eeprom formats o start cleaning up regdomain code o prepare for proper 1/2 and 1/4 width channel support o bring back 900MHz card support o clean up 5212 rf version handling o add 1/2 and 1/4 width channel support for 5212 parts o split 5212 rfgain handling out o improve ani debugging o add AH_USE_INIPDGAIN compile option o purge a bunch of dead 5212 state o add 1/2 and 1/4 rate modes o remove HAL_CAP_CHAN_HALFRATE and HAL_CAP_CHAN_QUARTERRATE; the same info can now be deduced from the set of supported modes --- ah.c | 71 +- ah.h | 20 +- ah_desc.h | 3 +- ah_devid.h | 4 +- ah_eeprom.h | 20 +- ah_eeprom_v1.c | 253 +++++ ah_eeprom_v1.h | 99 ++ ah_eeprom_v14.c | 6 +- ah_eeprom_v3.c | 7 +- ah_internal.h | 27 +- ah_regdomain.c | 1967 ++++++++++++++++++++--------------- ar5210/ar5210.h | 83 +- ar5210/ar5210_attach.c | 175 +--- ar5210/ar5210_misc.c | 53 +- ar5210/ar5210_reset.c | 62 +- ar5210/ar5210desc.h | 2 +- ar5211/ar5211.h | 8 +- ar5211/ar5211_attach.c | 10 +- ar5211/ar5211_interrupts.c | 6 +- ar5211/ar5211_misc.c | 60 +- ar5211/ar5211_reset.c | 60 +- ar5211/ar5211_xmit.c | 2 +- ar5212/ar2316.c | 20 +- ar5212/ar2317.c | 14 +- ar5212/ar2413.c | 20 +- ar5212/ar2425.c | 48 +- ar5212/ar5212.h | 74 +- ar5212/ar5212_ani.c | 79 +- ar5212/ar5212_attach.c | 42 +- ar5212/ar5212_interrupts.c | 6 +- ar5212/ar5212_misc.c | 101 +- ar5212/ar5212_phy.c | 12 +- ar5212/ar5212_reset.c | 466 ++------- ar5212/ar5212_rfgain.c | 333 ++++++ ar5212/ar5212phy.h | 21 +- ar5212/ar5212reg.h | 37 +- ar5212/ar5311reg.h | 1 + ar5212/ar5413.c | 20 +- ar5312/ar5312.h | 17 +- ar5312/ar5312_attach.c | 15 +- ar5312/ar5312_misc.c | 15 +- ar5312/ar5312_reset.c | 45 +- ar5416/ar2133.c | 61 +- ar5416/ar5416.h | 131 +-- ar5416/ar5416_ani.c | 888 ++++++++++++++++ ar5416/ar5416_attach.c | 27 +- ar5416/ar5416_beacon.c | 4 +- ar5416/ar5416_cal.c | 669 ++++++++++++ ar5416/ar5416_cal.h | 119 +++ ar5416/ar5416_cal_adcdc.c | 114 ++ ar5416/ar5416_cal_adcgain.c | 119 +++ ar5416/ar5416_cal_iq.c | 135 +++ ar5416/ar5416_misc.c | 8 +- ar5416/ar5416_phy.c | 4 +- ar5416/ar5416_power.c | 2 +- ar5416/ar5416_recv.c | 11 +- ar5416/ar5416_reset.c | 989 +----------------- ar5416/ar5416_xmit.c | 2 +- ar5416/ar5416desc.h | 2 +- ar5416/ar5416phy.h | 12 +- ar5416/ar5416reg.h | 6 +- ar5416/ar9160_attach.c | 17 +- version.h | 4 +- 63 files changed, 4795 insertions(+), 2913 deletions(-) create mode 100644 ah_eeprom_v1.c create mode 100644 ah_eeprom_v1.h create mode 100644 ar5212/ar5212_rfgain.c create mode 100644 ar5416/ar5416_ani.c create mode 100644 ar5416/ar5416_cal.c create mode 100644 ar5416/ar5416_cal.h create mode 100644 ar5416/ar5416_cal_adcdc.c create mode 100644 ar5416/ar5416_cal_adcgain.c create mode 100644 ar5416/ar5416_cal_iq.c diff --git a/ah.c b/ah.c index c531b78dedf1..409259dcf5ef 100644 --- a/ah.c +++ b/ah.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.c,v 1.13 2008/11/10 04:08:00 sam Exp $ + * $Id: ah.c,v 1.15 2008/11/15 22:15:44 sam Exp $ */ #include "opt_ah.h" @@ -46,6 +46,14 @@ extern struct ath_hal *ar5416Attach(uint16_t, HAL_SOFTC, extern struct ath_hal *ar9160Attach(uint16_t, HAL_SOFTC, HAL_BUS_TAG, HAL_BUS_HANDLE, HAL_STATUS*); #endif +#ifdef AH_SUPPORT_AR9280 +extern struct ath_hal *ar9280Attach(uint16_t, HAL_SOFTC, + HAL_BUS_TAG, HAL_BUS_HANDLE, HAL_STATUS*); +#endif +#ifdef AH_SUPPORT_AR9285 +extern struct ath_hal *ar9285Attach(uint16_t, HAL_SOFTC, + HAL_BUS_TAG, HAL_BUS_HANDLE, HAL_STATUS*); +#endif #include "version.h" char ath_hal_version[] = ATH_HAL_VERSION; @@ -68,6 +76,12 @@ const char* ath_hal_buildopts[] = { #ifdef AH_SUPPORT_AR9180 "AR9180", #endif +#ifdef AH_SUPPORT_AR9280 + "AR9280", +#endif +#ifdef AH_SUPPORT_AR9285 + "AR9285", +#endif #ifdef AH_SUPPORT_5111 "RF5111", #endif @@ -110,12 +124,21 @@ const char* ath_hal_buildopts[] = { #ifdef AH_PRIVATE_DIAG "PRIVATE_DIAG", #endif +#ifdef AH_SUPPORT_WRITE_EEPROM + "WRITE_EEPROM", +#endif +#ifdef AH_SUPPORT_WRITE_REGDOMAIN + "WRITE_REGDOMAIN", +#endif #ifdef AH_DEBUG_COUNTRY "DEBUG_COUNTRY", #endif #ifdef AH_NEED_DESC_SWAP "TX_DESC_SWAP", #endif +#ifdef AH_USE_INIPDGAIN + "INIPDGAIN", +#endif #ifdef AH_DISABLE_WME "DISABLE_WME", #endif @@ -169,6 +192,11 @@ ath_hal_devname(uint16_t devid) return "Atheros 5416"; case AR9160_DEVID_PCI: return "Atheros 9160"; + case AR9280_DEVID_PCI: + case AR9280_DEVID_PCIE: + return "Atheros 9280"; + case AR9285_DEVID_PCIE: + return "Atheros 9285"; } return AH_NULL; } @@ -246,6 +274,17 @@ ath_hal_attach(uint16_t devid, HAL_SOFTC sc, case AR9160_DEVID_PCI: ah = ar9160Attach(devid, sc, st, sh, error); break; +#endif +#ifdef AH_SUPPORT_AR9280 + case AR9280_DEVID_PCI: + case AR9280_DEVID_PCIE: + ah = ar9280Attach(devid, sc, st, sh, error); + break; +#endif +#ifdef AH_SUPPORT_AR9285 + case AR9285_DEVID_PCIE: + ah = ar9285Attach(devid, sc, st, sh, error); + break; #endif default: ah = AH_NULL; @@ -418,6 +457,19 @@ ath_hal_computetxtime(struct ath_hal *ah, return txTime; } +static __inline int +mapgsm(u_int freq, u_int flags) +{ + freq *= 10; + if (flags & CHANNEL_QUARTER) + freq += 5; + else if (flags & CHANNEL_HALF) + freq += 10; + else + freq += 20; + return (freq - 24220) / 5; +} + static __inline int mappsb(u_int freq, u_int flags) { @@ -434,6 +486,8 @@ ath_hal_mhz2ieee(struct ath_hal *ah, u_int freq, u_int flags) if (freq == 2484) return 14; if (freq < 2484) { + if (ath_hal_isgsmsku(ah)) + return mapgsm(freq, flags); return ((int)freq - 2407) / 5; } else return 15 + ((freq - 2512) / 20); @@ -450,6 +504,8 @@ ath_hal_mhz2ieee(struct ath_hal *ah, u_int freq, u_int flags) if (freq == 2484) return 14; if (freq < 2484) { + if (ath_hal_isgsmsku(ah)) + return mapgsm(freq, flags); return ((int)freq - 2407) / 5; } if (freq < 5000) { @@ -641,10 +697,6 @@ ath_hal_getcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, return pCap->halMcastKeySrchSupport ? HAL_OK : HAL_ENOTSUPP; case HAL_CAP_TSF_ADJUST: /* hardware has beacon tsf adjust */ return HAL_ENOTSUPP; - case HAL_CAP_CHAN_HALFRATE: - return pCap->halChanHalfRate ? HAL_OK : HAL_ENOTSUPP; - case HAL_CAP_CHAN_QUARTERRATE: - return pCap->halChanQuarterRate ? HAL_OK : HAL_ENOTSUPP; case HAL_CAP_RFSILENT: /* rfsilent support */ switch (capability) { case 0: /* facility is supported */ @@ -789,6 +841,15 @@ ath_hal_getdiagstate(struct ath_hal *ah, int request, if (argsize != sizeof(uint16_t)) return AH_FALSE; return ah->ah_resetKeyCacheEntry(ah, *(const uint16_t *)args); +#ifdef AH_SUPPORT_WRITE_EEPROM + case HAL_DIAG_EEWRITE: { + const HAL_DIAG_EEVAL *ee; + if (argsize != sizeof(HAL_DIAG_EEVAL)) + return AH_FALSE; + ee = (const HAL_DIAG_EEVAL *)args; + return ath_hal_eepromWrite(ah, ee->ee_off, ee->ee_data); + } +#endif /* AH_SUPPORT_WRITE_EEPROM */ #endif /* AH_PRIVATE_DIAG */ case HAL_DIAG_11NCOMPAT: if (argsize == 0) { diff --git a/ah.h b/ah.h index e5d47bdb47ab..0ec30ac67ad4 100644 --- a/ah.h +++ b/ah.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.h,v 1.13 2008/11/10 04:08:00 sam Exp $ + * $Id: ah.h,v 1.15 2008/11/15 03:43:50 sam Exp $ */ #ifndef _ATH_AH_H_ @@ -105,8 +105,8 @@ typedef enum { HAL_CAP_TSF_ADJUST = 20, /* hardware has beacon tsf adjust */ /* 21 was HAL_CAP_XR */ HAL_CAP_WME_TKIPMIC = 22, /* hardware can support TKIP MIC when WMM is turned on */ - HAL_CAP_CHAN_HALFRATE = 23, /* hardware can support half rate channels */ - HAL_CAP_CHAN_QUARTERRATE = 24, /* hardware can support quarter rate channels */ + /* 23 was HAL_CAP_CHAN_HALFRATE */ + /* 24 was HAL_CAP_CHAN_QUARTERRATE */ HAL_CAP_RFSILENT = 25, /* hardware has rfsilent support */ HAL_CAP_TPC_ACK = 26, /* ack txpower with per-packet tpc */ HAL_CAP_TPC_CTS = 27, /* cts txpower with per-packet tpc */ @@ -466,8 +466,10 @@ enum { #endif HAL_MODE_108G = 0x020, /* 11g+Turbo channels */ HAL_MODE_108A = 0x040, /* 11a+Turbo channels */ - HAL_MODE_11A_HALF_RATE = 0x200, /* 11A half rate channels */ - HAL_MODE_11A_QUARTER_RATE = 0x400, /* 11A quarter rate channels */ + HAL_MODE_11A_HALF_RATE = 0x200, /* 11a half width channels */ + HAL_MODE_11A_QUARTER_RATE = 0x400, /* 11a quarter width channels */ + HAL_MODE_11G_HALF_RATE = 0x800, /* 11g half width channels */ + HAL_MODE_11G_QUARTER_RATE = 0x1000, /* 11g quarter width channels */ HAL_MODE_11NG_HT20 = 0x008000, HAL_MODE_11NA_HT20 = 0x010000, HAL_MODE_11NG_HT40PLUS = 0x020000, @@ -654,7 +656,7 @@ struct ath_rx_status; struct ath_hal { uint32_t ah_magic; /* consistency check magic number */ uint32_t ah_abi; /* HAL ABI version */ -#define HAL_ABI_VERSION 0x08110600 /* YYMMDDnn */ +#define HAL_ABI_VERSION 0x08111400 /* YYMMDDnn */ uint16_t ah_devid; /* PCI device ID */ uint16_t ah_subvendorid; /* PCI subvendor ID */ HAL_SOFTC ah_sc; /* back pointer to driver/os state */ @@ -680,7 +682,11 @@ struct ath_hal { HAL_BOOL __ahdecl(*ah_phyDisable)(struct ath_hal *); HAL_BOOL __ahdecl(*ah_disable)(struct ath_hal *); void __ahdecl(*ah_setPCUConfig)(struct ath_hal *); - HAL_BOOL __ahdecl(*ah_perCalibration)(struct ath_hal*, HAL_CHANNEL *, HAL_BOOL *); + HAL_BOOL __ahdecl(*ah_perCalibration)(struct ath_hal*, HAL_CHANNEL *, + HAL_BOOL *); + HAL_BOOL __ahdecl(*ah_perCalibrationN)(struct ath_hal *, HAL_CHANNEL *, + u_int chainMask, HAL_BOOL longCal, HAL_BOOL *isCalDone); + HAL_BOOL __ahdecl(*ah_resetCalValid)(struct ath_hal *, HAL_CHANNEL *); HAL_BOOL __ahdecl(*ah_setTxPowerLimit)(struct ath_hal *, uint32_t); /* Transmit functions */ diff --git a/ah_desc.h b/ah_desc.h index 50e010ed0389..6cfad061bec2 100644 --- a/ah_desc.h +++ b/ah_desc.h @@ -167,7 +167,8 @@ enum { /* * Definitions for the software frame/packet descriptors used by - * the Atheros HAL. Drivers are expected to fillin the + * the Atheros HAL. This definition obscures hardware-specific + * details from the driver. Drivers are expected to fillin the * portions of a descriptor that are not opaque then use HAL calls * to complete the work. Status for completed frames is returned * in a device-independent format. diff --git a/ah_devid.h b/ah_devid.h index 204cf3f19125..0844c773610b 100644 --- a/ah_devid.h +++ b/ah_devid.h @@ -23,8 +23,8 @@ #define ATHEROS_VENDOR_ID 0x168c /* Atheros PCI vendor ID */ /* * NB: all Atheros-based devices should have a PCI vendor ID - * of 0x168c, but some vendors do not follow this so we - * must handle them specially. + * of 0x168c, but some vendors, in their infinite wisdom + * do not follow this so we must handle them specially. */ #define ATHEROS_3COM_VENDOR_ID 0xa727 /* 3Com 3CRPAG175 vendor ID */ #define ATHEROS_3COM2_VENDOR_ID 0x10b7 /* 3Com 3CRDAG675 vendor ID */ diff --git a/ah_eeprom.h b/ah_eeprom.h index fb57c49919c8..0adfcd144d01 100644 --- a/ah_eeprom.h +++ b/ah_eeprom.h @@ -14,11 +14,12 @@ * 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.6 2008/11/10 04:08:00 sam Exp $ + * $Id: ah_eeprom.h,v 1.11 2008/11/27 22:32:48 sam Exp $ */ #ifndef _ATH_AH_EEPROM_H_ #define _ATH_AH_EEPROM_H_ +#define AR_EEPROM_VER1 0x1000 /* Version 1.0; 5210 only */ /* * Version 3 EEPROMs are all 16K. * 3.1 adds turbo limit, antenna gain, 16 CTL's, 11g info, @@ -34,15 +35,17 @@ #define AR_EEPROM_VER3_2 0x3002 /* Version 3.2 */ #define AR_EEPROM_VER3_3 0x3003 /* Version 3.3 */ #define AR_EEPROM_VER3_4 0x3004 /* Version 3.4 */ +#define AR_EEPROM_VER4 0x4000 /* Version 4.x */ #define AR_EEPROM_VER4_0 0x4000 /* Version 4.0 */ #define AR_EEPROM_VER4_1 0x4001 /* Version 4.0 */ #define AR_EEPROM_VER4_2 0x4002 /* Version 4.0 */ #define AR_EEPROM_VER4_3 0x4003 /* Version 4.0 */ #define AR_EEPROM_VER4_6 0x4006 /* Version 4.0 */ #define AR_EEPROM_VER4_7 0x3007 /* Version 4.7 */ -#define AR_EEPROM_VER4_9 0x4009 /* EEPROM EAR futureproofing */ -#define AR_EEPROM_VER5_0 0x5000 /* Adds new 2413 cal powers and added params */ -#define AR_EEPROM_VER5_1 0x5001 /* Adds capability values */ +#define AR_EEPROM_VER4_9 0x4009 /* EEPROM EAR futureproofing */ +#define AR_EEPROM_VER5 0x5000 /* Version 5.x */ +#define AR_EEPROM_VER5_0 0x5000 /* Adds new 2413 cal powers and added params */ +#define AR_EEPROM_VER5_1 0x5001 /* Adds capability values */ #define AR_EEPROM_VER5_3 0x5003 /* Adds spur mitigation table */ #define AR_EEPROM_VER5_4 0x5004 /* @@ -50,7 +53,8 @@ * 14.2 adds txFrameToPaOn, txFrameToDataStart, ht40PowerInc * 14.3 adds bswAtten, bswMargin, swSettle, and base OpFlags for HT20/40 */ -#define AR_EEPROM_VER14_1 0xE001 /* 11n support */ +#define AR_EEPROM_VER14 0xE000 /* Version 14.x */ +#define AR_EEPROM_VER14_1 0xE001 /* Adds 11n support */ #define AR_EEPROM_VER14_2 0xE002 #define AR_EEPROM_VER14_3 0xE003 #define AR_EEPROM_VER14_7 0xE007 @@ -75,8 +79,8 @@ enum { AR_EEP_BURST, /* use ath_hal_eepromGetFlag */ AR_EEP_MAXQCU, /* uint16_t* */ AR_EEP_KCENTRIES, /* uint16_t* */ - AR_EEP_NFTHRESH_5, /* uint8_t* */ - AR_EEP_NFTHRESH_2, /* uint8_t* */ + AR_EEP_NFTHRESH_5, /* int16_t* */ + AR_EEP_NFTHRESH_2, /* int16_t* */ AR_EEP_REGDMN_0, /* uint16_t* */ AR_EEP_REGDMN_1, /* uint16_t* */ AR_EEP_OPCAP, /* uint16_t* */ @@ -122,6 +126,8 @@ typedef struct { /* XXX exposed to chip code */ #define MAX_RATE_POWER 63 +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); #endif /* _ATH_AH_EEPROM_H_ */ diff --git a/ah_eeprom_v1.c b/ah_eeprom_v1.c new file mode 100644 index 000000000000..91f895c2480f --- /dev/null +++ b/ah_eeprom_v1.c @@ -0,0 +1,253 @@ +/* + * 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. + * + * $Id: ah_eeprom_v1.c,v 1.1 2008/11/11 02:40:11 sam Exp $ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_eeprom_v1.h" + +static HAL_STATUS +v1EepromGet(struct ath_hal *ah, int param, void *val) +{ + HAL_EEPROM_v1 *ee = AH_PRIVATE(ah)->ah_eeprom; + uint32_t sum; + uint16_t eeval; + uint8_t *macaddr; + int i; + + switch (param) { + case AR_EEP_MACADDR: /* Get MAC Address */ + sum = 0; + macaddr = val; + for (i = 0; i < 3; i++) { + if (!ath_hal_eepromRead(ah, AR_EEPROM_MAC(i), &eeval)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cannot read EEPROM location %u\n", + __func__, i); + return HAL_EEREAD; + } + sum += eeval; + macaddr[2*i + 0] = eeval >> 8; + macaddr[2*i + 1] = eeval & 0xff; + } + 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: + *(uint16_t *) val = ee->ee_regDomain[0]; + return HAL_OK; + case AR_EEP_RFKILL: + HALASSERT(val == AH_NULL); + return ee->ee_rfKill ? HAL_OK : HAL_EIO; + case AR_EEP_WRITEPROTECT: + HALASSERT(val == AH_NULL); + return (ee->ee_protect & AR_EEPROM_PROTOTECT_WP_128_191) ? + HAL_OK : HAL_EIO; + default: + HALASSERT(0); + return HAL_EINVAL; + } +} + +static HAL_BOOL +v1EepromSet(struct ath_hal *ah, int param, int v) +{ + return HAL_EINVAL; +} + +static HAL_BOOL +v1EepromDiag(struct ath_hal *ah, int request, + const void *args, uint32_t argsize, void **result, uint32_t *resultsize) +{ + HAL_EEPROM_v1 *ee = AH_PRIVATE(ah)->ah_eeprom; + + switch (request) { + case HAL_DIAG_EEPROM: + *result = ee; + *resultsize = sizeof(*ee); + return AH_TRUE; + } + return AH_FALSE; +} + +static uint16_t +v1EepromGetSpurChan(struct ath_hal *ah, int ix, HAL_BOOL is2GHz) +{ + return AR_NO_SPUR; +} + +/* + * Reclaim any EEPROM-related storage. + */ +static void +v1EepromDetach(struct ath_hal *ah) +{ + HAL_EEPROM_v1 *ee = AH_PRIVATE(ah)->ah_eeprom; + + ath_hal_free(ee); + AH_PRIVATE(ah)->ah_eeprom = AH_NULL; +} + +HAL_STATUS +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; + uint32_t sum; + int i, loc; + + HALASSERT(ee == AH_NULL); + + if (!ath_hal_eepromRead(ah, AR_EEPROM_MAGIC, &eeval)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cannot read EEPROM magic number\n", __func__); + return HAL_EEREAD; + } + if (eeval != 0x5aa5) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid EEPROM magic number 0x%x\n", __func__, eeval); + return HAL_EEMAGIC; + } + + if (!ath_hal_eepromRead(ah, AR_EEPROM_PROTECT, &protect)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cannot read EEPROM protection bits; read locked?\n", + __func__); + return HAL_EEREAD; + } + 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)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: unable to read EEPROM version\n", __func__); + return HAL_EEREAD; + } + if (((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); + return HAL_EEVERSION; + } + + /* + * Read the Atheros EEPROM entries and calculate the checksum. + */ + sum = 0; + for (i = 0; i < AR_EEPROM_ATHEROS_MAX; i++) { + if (!ath_hal_eepromRead(ah, AR_EEPROM_ATHEROS(i), &athvals[i])) + return HAL_EEREAD; + sum ^= athvals[i]; + } + if (sum != 0xffff) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad EEPROM checksum 0x%x\n", + __func__, sum); + return HAL_EEBADSUM; + } + + /* + * Valid checksum, fetch the regulatory domain and save values. + */ + if (!ath_hal_eepromRead(ah, AR_EEPROM_REG_DOMAIN, &eeval)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: cannot read regdomain from EEPROM\n", __func__); + return HAL_EEREAD; + } + + ee = ath_hal_malloc(sizeof(HAL_EEPROM_v1)); + if (ee == AH_NULL) { + /* XXX message */ + return HAL_ENOMEM; + } + + ee->ee_version = version; + ee->ee_protect = protect; + ee->ee_antenna = athvals[2]; + ee->ee_biasCurrents = athvals[3]; + ee->ee_thresh62 = athvals[4] & 0xff; + ee->ee_xlnaOn = (athvals[4] >> 8) & 0xff; + ee->ee_xpaOn = athvals[5] & 0xff; + ee->ee_xpaOff = (athvals[5] >> 8) & 0xff; + ee->ee_regDomain[0] = (athvals[6] >> 8) & 0xff; + ee->ee_regDomain[1] = athvals[6] & 0xff; + ee->ee_regDomain[2] = (athvals[7] >> 8) & 0xff; + ee->ee_regDomain[3] = athvals[7] & 0xff; + ee->ee_rfKill = athvals[8] & 0x1; + ee->ee_devType = (athvals[8] >> 1) & 0x7; + + for (i = 0, loc = AR_EEPROM_ATHEROS_TP_SETTINGS; i < AR_CHANNELS_MAX; i++, loc += AR_TP_SETTINGS_SIZE) { + struct tpcMap *chan = &ee->ee_tpc[i]; + + /* Copy pcdac and gain_f values from EEPROM */ + chan->pcdac[0] = (athvals[loc] >> 10) & 0x3F; + chan->gainF[0] = (athvals[loc] >> 4) & 0x3F; + chan->pcdac[1] = ((athvals[loc] << 2) & 0x3C) + | ((athvals[loc+1] >> 14) & 0x03); + chan->gainF[1] = (athvals[loc+1] >> 8) & 0x3F; + chan->pcdac[2] = (athvals[loc+1] >> 2) & 0x3F; + chan->gainF[2] = ((athvals[loc+1] << 4) & 0x30) + | ((athvals[loc+2] >> 12) & 0x0F); + chan->pcdac[3] = (athvals[loc+2] >> 6) & 0x3F; + chan->gainF[3] = athvals[loc+2] & 0x3F; + chan->pcdac[4] = (athvals[loc+3] >> 10) & 0x3F; + chan->gainF[4] = (athvals[loc+3] >> 4) & 0x3F; + chan->pcdac[5] = ((athvals[loc+3] << 2) & 0x3C) + | ((athvals[loc+4] >> 14) & 0x03); + chan->gainF[5] = (athvals[loc+4] >> 8) & 0x3F; + chan->pcdac[6] = (athvals[loc+4] >> 2) & 0x3F; + chan->gainF[6] = ((athvals[loc+4] << 4) & 0x30) + | ((athvals[loc+5] >> 12) & 0x0F); + chan->pcdac[7] = (athvals[loc+5] >> 6) & 0x3F; + chan->gainF[7] = athvals[loc+5] & 0x3F; + chan->pcdac[8] = (athvals[loc+6] >> 10) & 0x3F; + chan->gainF[8] = (athvals[loc+6] >> 4) & 0x3F; + chan->pcdac[9] = ((athvals[loc+6] << 2) & 0x3C) + | ((athvals[loc+7] >> 14) & 0x03); + chan->gainF[9] = (athvals[loc+7] >> 8) & 0x3F; + chan->pcdac[10] = (athvals[loc+7] >> 2) & 0x3F; + chan->gainF[10] = ((athvals[loc+7] << 4) & 0x30) + | ((athvals[loc+8] >> 12) & 0x0F); + + /* Copy Regulatory Domain and Rate Information from EEPROM */ + chan->rate36 = (athvals[loc+8] >> 6) & 0x3F; + chan->rate48 = athvals[loc+8] & 0x3F; + chan->rate54 = (athvals[loc+9] >> 10) & 0x3F; + chan->regdmn[0] = (athvals[loc+9] >> 4) & 0x3F; + chan->regdmn[1] = ((athvals[loc+9] << 2) & 0x3C) + | ((athvals[loc+10] >> 14) & 0x03); + chan->regdmn[2] = (athvals[loc+10] >> 8) & 0x3F; + chan->regdmn[3] = (athvals[loc+10] >> 2) & 0x3F; + } + + AH_PRIVATE(ah)->ah_eeprom = ee; + AH_PRIVATE(ah)->ah_eeversion = version; + AH_PRIVATE(ah)->ah_eepromDetach = v1EepromDetach; + AH_PRIVATE(ah)->ah_eepromGet = v1EepromGet; + AH_PRIVATE(ah)->ah_eepromSet = v1EepromSet; + AH_PRIVATE(ah)->ah_getSpurChan = v1EepromGetSpurChan; + AH_PRIVATE(ah)->ah_eepromDiag = v1EepromDiag; + return HAL_OK; +} diff --git a/ah_eeprom_v1.h b/ah_eeprom_v1.h new file mode 100644 index 000000000000..2c235896eac3 --- /dev/null +++ b/ah_eeprom_v1.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2002-2008 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. + * + * $Id: ah_eeprom_v1.h,v 1.1 2008/11/11 02:40:11 sam Exp $ + */ +#ifndef _ATH_AH_EEPROM_V1_H_ +#define _ATH_AH_EEPROM_V1_H_ + +#include "ah_eeprom.h" + +/* + * EEPROM defines for Version 1 Crete EEPROM. + * + * The EEPROM is segmented into three sections: + * + * PCI/Cardbus default configuration settings + * Cardbus CIS tuples and vendor-specific data + * Atheros-specific data + * + * EEPROM entries are read 32-bits at a time through the PCI bus + * interface but are all 16-bit values. + * + * Access to the Atheros-specific data is controlled by protection + * bits and the data is checksum'd. The driver reads the Atheros + * data from the EEPROM at attach and caches it in its private state. + * This data includes the local regulatory domain, channel calibration + * settings, and phy-related configuration settings. + */ +#define AR_EEPROM_MAC(i) (0x1f-(i))/* MAC address word */ +#define AR_EEPROM_MAGIC 0x3d /* magic number */ +#define AR_EEPROM_PROTECT 0x3f /* Atheros segment protect register */ +#define AR_EEPROM_PROTOTECT_WP_128_191 0x80 +#define AR_EEPROM_REG_DOMAIN 0xbf /* Current regulatory domain register */ +#define AR_EEPROM_ATHEROS_BASE 0xc0 /* Base of Atheros-specific data */ +#define AR_EEPROM_ATHEROS_MAX 64 /* 64x2=128 bytes of EEPROM settings */ +#define AR_EEPROM_ATHEROS(n) (AR_EEPROM_ATHEROS_BASE+(n)) +#define AR_EEPROM_VERSION AR_EEPROM_ATHEROS(1) +#define AR_EEPROM_ATHEROS_TP_SETTINGS 0x09 /* Transmit power settings */ +#define AR_REG_DOMAINS_MAX 4 /* # of Regulatory Domains */ +#define AR_CHANNELS_MAX 5 /* # of Channel calibration groups */ +#define AR_TP_SETTINGS_SIZE 11 /* # locations/Channel group */ +#define AR_TP_SCALING_ENTRIES 11 /* # entries in transmit power dBm->pcdac */ + +/* + * NB: we store the rfsilent select+polarity data packed + * with the encoding used in later parts so values + * returned to applications are consistent. + */ +#define AR_EEPROM_RFSILENT_GPIO_SEL 0x001c +#define AR_EEPROM_RFSILENT_GPIO_SEL_S 2 +#define AR_EEPROM_RFSILENT_POLARITY 0x0002 +#define AR_EEPROM_RFSILENT_POLARITY_S 1 + +#define AR_I2DBM(x) ((uint8_t)((x * 2) + 3)) + +/* + * Transmit power and channel calibration settings. + */ +struct tpcMap { + uint8_t pcdac[AR_TP_SCALING_ENTRIES]; + uint8_t gainF[AR_TP_SCALING_ENTRIES]; + uint8_t rate36; + uint8_t rate48; + uint8_t rate54; + uint8_t regdmn[AR_REG_DOMAINS_MAX]; +}; + +/* + * Information retrieved from EEPROM. + */ +typedef struct { + uint16_t ee_version; /* Version field */ + uint16_t ee_protect; /* EEPROM protect field */ + uint16_t ee_antenna; /* Antenna Settings */ + uint16_t ee_biasCurrents; /* OB, DB */ + uint8_t ee_thresh62; /* thresh62 */ + uint8_t ee_xlnaOn; /* External LNA timing */ + uint8_t ee_xpaOff; /* Extern output stage timing */ + uint8_t ee_xpaOn; /* Extern output stage timing */ + uint8_t ee_rfKill; /* Single low bit signalling if RF Kill is implemented */ + uint8_t ee_devType; /* Type: PCI, miniPCI, CB */ + uint8_t ee_regDomain[AR_REG_DOMAINS_MAX]; + /* calibrated reg domains */ + struct tpcMap ee_tpc[AR_CHANNELS_MAX]; +} HAL_EEPROM_v1; +#endif /* _ATH_AH_EEPROM_V1_H_ */ diff --git a/ah_eeprom_v14.c b/ah_eeprom_v14.c index 67bcdedf5b8d..1941c2b0c7a9 100644 --- a/ah_eeprom_v14.c +++ b/ah_eeprom_v14.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_v14.c,v 1.3 2008/11/10 04:08:00 sam Exp $ + * $Id: ah_eeprom_v14.c,v 1.4 2008/11/10 19:04:26 sam Exp $ */ #include "opt_ah.h" @@ -37,10 +37,10 @@ v14EepromGet(struct ath_hal *ah, int param, void *val) switch (param) { case AR_EEP_NFTHRESH_5: - *(int8_t *)val = pModal[0].noiseFloorThreshCh[0]; + *(int16_t *)val = pModal[0].noiseFloorThreshCh[0]; return HAL_OK; case AR_EEP_NFTHRESH_2: - *(int8_t *)val = pModal[1].noiseFloorThreshCh[0]; + *(int16_t *)val = pModal[1].noiseFloorThreshCh[0]; return HAL_OK; case AR_EEP_MACADDR: /* Get MAC Address */ sum = 0; diff --git a/ah_eeprom_v3.c b/ah_eeprom_v3.c index 717578d91810..b2c304b7de1e 100644 --- a/ah_eeprom_v3.c +++ b/ah_eeprom_v3.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_v3.c,v 1.3 2008/11/10 04:08:00 sam Exp $ + * $Id: ah_eeprom_v3.c,v 1.4 2008/11/27 22:39:42 sam Exp $ */ #include "opt_ah.h" @@ -1765,9 +1765,8 @@ legacyEepromDetach(struct ath_hal *ah) } /* - * TODO: Need to talk to Praveen about this, these are - * not valid 2.4 channels, either we change these - * or I need to change the beanie coding to accept these + * These are not valid 2.4 channels, either we change 'em + * or we need to change the coding to accept them. */ static const uint16_t channels11b[] = { 2412, 2447, 2484 }; static const uint16_t channels11g[] = { 2312, 2412, 2484 }; diff --git a/ah_internal.h b/ah_internal.h index 78eba8d33b7d..dc21e5e63a46 100644 --- a/ah_internal.h +++ b/ah_internal.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_internal.h,v 1.17 2008/11/10 04:08:00 sam Exp $ + * $Id: ah_internal.h,v 1.21 2008/11/27 22:29:27 sam Exp $ */ #ifndef _ATH_AH_INTERAL_H_ #define _ATH_AH_INTERAL_H_ @@ -66,6 +66,9 @@ typedef struct { /* * Transmit power scale factor. + * + * NB: This is not public because we want to discourage the use of + * scaling; folks should use the tx power limit interface. */ typedef enum { HAL_TP_SCALE_MAX = 0, /* no scaling (default) */ @@ -165,7 +168,23 @@ typedef struct { /* * The ``private area'' follows immediately after the ``public area'' - * in the data structure returned by ath_hal_attach. + * in the data structure returned by ath_hal_attach. Private data are + * used by device-independent code such as the regulatory domain support. + * In general, code within the HAL should never depend on data in the + * public area. Instead any public data needed internally should be + * shadowed here. + * + * When declaring a device-specific ath_hal data structure this structure + * is assumed to at the front; e.g. + * + * struct ath_hal_5212 { + * struct ath_hal_private ah_priv; + * ... + * }; + * + * It might be better to manage the method pointers in this structure + * using an indirect pointer to a read-only data structure but this would + * disallow class-style method overriding. */ struct ath_hal_private { struct ath_hal h; /* public area */ @@ -189,6 +208,8 @@ struct ath_hal_private { HAL_CHANNEL *, uint32_t); int16_t (*ah_getNfAdjust)(struct ath_hal *, const HAL_CHANNEL_INTERNAL*); + void (*ah_getNoiseFloor)(struct ath_hal *, + int16_t nfarray[]); void *ah_eeprom; /* opaque EEPROM state */ uint16_t ah_eeversion; /* EEPROM version */ @@ -267,6 +288,8 @@ struct ath_hal_private { AH_PRIVATE(_ah)->ah_getChipPowerLimits(_ah, _chans, _nchan) #define ath_hal_getNfAdjust(_ah, _c) \ AH_PRIVATE(_ah)->ah_getNfAdjust(_ah, _c) +#define ath_hal_getNoiseFloor(_ah, _nfArray) \ + AH_PRIVATE(_ah)->ah_getNoiseFloor(_ah, _nfArray) #define ath_hal_eepromDetach(_ah) \ AH_PRIVATE(_ah)->ah_eepromDetach(_ah) diff --git a/ah_regdomain.c b/ah_regdomain.c index 2a6f2c5cb417..d021c28ed6f3 100644 --- a/ah_regdomain.c +++ b/ah_regdomain.c @@ -15,7 +15,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_regdomain.c,v 1.17 2008/11/10 04:08:00 sam Exp $ + * $Id: ah_regdomain.c,v 1.24 2008/11/27 22:29:27 sam Exp $ */ #include "opt_ah.h" @@ -37,47 +37,49 @@ /* 10MHz is half the 11A bandwidth used to determine upper edge freq of the outdoor channel */ #define HALF_MAXCHANBW 10 - -/* - * Used to set the RegDomain bitmask which chooses which frequency - * band specs are used. - */ -#define BMLEN 2 /* Use 2 64 bit uint for channel bitmask - NB: Must agree with macro below (BM) */ -#define BMZERO {(uint64_t) 0, (uint64_t) 0} /* BMLEN zeros */ - -#define BM(_fa, _fb, _fc, _fd, _fe, _ff, _fg, _fh, _fi, _fj, _fk, _fl) \ - {((((_fa >= 0) && (_fa < 64)) ? (((uint64_t) 1) << _fa) : (uint64_t) 0) | \ - (((_fb >= 0) && (_fb < 64)) ? (((uint64_t) 1) << _fb) : (uint64_t) 0) | \ - (((_fc >= 0) && (_fc < 64)) ? (((uint64_t) 1) << _fc) : (uint64_t) 0) | \ - (((_fd >= 0) && (_fd < 64)) ? (((uint64_t) 1) << _fd) : (uint64_t) 0) | \ - (((_fe >= 0) && (_fe < 64)) ? (((uint64_t) 1) << _fe) : (uint64_t) 0) | \ - (((_ff >= 0) && (_ff < 64)) ? (((uint64_t) 1) << _ff) : (uint64_t) 0) | \ - (((_fg >= 0) && (_fg < 64)) ? (((uint64_t) 1) << _fg) : (uint64_t) 0) | \ - (((_fh >= 0) && (_fh < 64)) ? (((uint64_t) 1) << _fh) : (uint64_t) 0) | \ - (((_fi >= 0) && (_fi < 64)) ? (((uint64_t) 1) << _fi) : (uint64_t) 0) | \ - (((_fj >= 0) && (_fj < 64)) ? (((uint64_t) 1) << _fj) : (uint64_t) 0) | \ - (((_fk >= 0) && (_fk < 64)) ? (((uint64_t) 1) << _fk) : (uint64_t) 0) | \ - (((_fl >= 0) && (_fl < 64)) ? (((uint64_t) 1) << _fl) : (uint64_t) 0) | \ - ((((_fa > 63) && (_fa < 128)) ? (((uint64_t) 1) << (_fa - 64)) : (uint64_t) 0) | \ - (((_fb > 63) && (_fb < 128)) ? (((uint64_t) 1) << (_fb - 64)) : (uint64_t) 0) | \ - (((_fc > 63) && (_fc < 128)) ? (((uint64_t) 1) << (_fc - 64)) : (uint64_t) 0) | \ - (((_fd > 63) && (_fd < 128)) ? (((uint64_t) 1) << (_fd - 64)) : (uint64_t) 0) | \ - (((_fe > 63) && (_fe < 128)) ? (((uint64_t) 1) << (_fe - 64)) : (uint64_t) 0) | \ - (((_ff > 63) && (_ff < 128)) ? (((uint64_t) 1) << (_ff - 64)) : (uint64_t) 0) | \ - (((_fg > 63) && (_fg < 128)) ? (((uint64_t) 1) << (_fg - 64)) : (uint64_t) 0) | \ - (((_fh > 63) && (_fh < 128)) ? (((uint64_t) 1) << (_fh - 64)) : (uint64_t) 0) | \ - (((_fi > 63) && (_fi < 128)) ? (((uint64_t) 1) << (_fi - 64)) : (uint64_t) 0) | \ - (((_fj > 63) && (_fj < 128)) ? (((uint64_t) 1) << (_fj - 64)) : (uint64_t) 0) | \ - (((_fk > 63) && (_fk < 128)) ? (((uint64_t) 1) << (_fk - 64)) : (uint64_t) 0) | \ - (((_fl > 63) && (_fl < 128)) ? (((uint64_t) 1) << (_fl - 64)) : (uint64_t) 0)))} +/* + * 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) } /* * Country/Region Codes * Numbering from ISO 3166 */ -enum CountryCode { +enum { CTRY_ALBANIA = 8, /* Albania */ CTRY_ALGERIA = 12, /* Algeria */ CTRY_ARGENTINA = 32, /* Argentina */ @@ -202,6 +204,7 @@ enum CountryCode { CTRY_SLOVENIA = 705, /* Slovenia */ CTRY_SOUTH_AFRICA = 710, /* South Africa */ CTRY_SPAIN = 724, /* Spain */ + CTRY_SR9 = 5000, /* Ubiquiti SR9 (900MHz/GSM) */ CTRY_SWEDEN = 752, /* Sweden */ CTRY_SWITZERLAND = 756, /* Switzerland */ CTRY_SYRIA = 760, /* Syria */ @@ -219,23 +222,25 @@ enum CountryCode { CTRY_UZBEKISTAN = 860, /* Uzbekistan */ CTRY_VENEZUELA = 862, /* Venezuela */ CTRY_VIET_NAM = 704, /* Viet Nam */ + CTRY_XR9 = 5001, /* Ubiquiti XR9 (900MHz/GSM) */ + CTRY_GZ901 = 5002, /* Zcomax GZ-901 (900MHz/GSM) */ CTRY_YEMEN = 887, /* Yemen */ CTRY_ZIMBABWE = 716 /* Zimbabwe */ }; -/* Mask to check whether a domain is a multidomain or a single - domain */ - +/* + * Mask to check whether a domain is a multidomain or a single domain + */ #define MULTI_DOMAIN_MASK 0xFF00 -/* Enumerated Regulatory Domain Information 8 bit values indicate that +/* + * 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 EnumRd { +enum { /* * The following regulatory domain definitions are * found in the EEPROM. Each regulatory domain @@ -253,6 +258,7 @@ enum EnumRd { 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 */ @@ -380,7 +386,9 @@ enum EnumRd { 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 */ @@ -399,6 +407,9 @@ enum EnumRd { NULL1 = 0x0198, WORLD = 0x0199, + SR9_WORLD = 0x0298, + XR9_WORLD = 0x0299, + GZ901_WORLD = 0x029a, DEBUG_REG_DMN = 0x01ff, }; @@ -414,30 +425,24 @@ enum { /* conformance test limits */ /* * 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 + * from the unitary reg domain if the reg domain pair flags value is 0 */ - enum { - NO_REQ = 0x00000000, + NO_REQ = 0x00000000, /* NB: must be zero */ DISALLOW_ADHOC_11A = 0x00000001, DISALLOW_ADHOC_11A_TURB = 0x00000002, NEED_NFC = 0x00000004, - ADHOC_PER_11D = 0x00000008, /* Start Ad-Hoc mode */ ADHOC_NO_11A = 0x00000010, - - PUBLIC_SAFETY_DOMAIN = 0x00000020, /* public safety domain */ - LIMIT_FRAME_4MS = 0x00000040, /* 4msec limit on the frame length */ - - NO_HOSTAP = 0x00000080, /* No HOSTAP mode opereation */ + LIMIT_FRAME_4MS = 0x00000020, /* 4msec limit on frame length*/ + 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 +#define NO_PSCAN 0x0ULL /* NB: must be zero */ #define PSCAN_FCC 0x0000000000000001ULL #define PSCAN_FCC_T 0x0000000000000002ULL #define PSCAN_ETSI 0x0000000000000004ULL @@ -461,8 +466,7 @@ enum { * THE following table is the mapping of regdomain pairs specified by * an 8 bit regdomain value to the individual unitary reg domains */ - -typedef struct reg_dmn_pair_mapping { +typedef struct { HAL_REG_DOMAIN regDmnEnum; /* 16 bit reg domain pair */ HAL_REG_DOMAIN regDmn5GHz; /* 5GHz reg domain */ HAL_REG_DOMAIN regDmn2GHz; /* 2GHz reg domain */ @@ -487,12 +491,13 @@ static REG_DMN_PAIR_MAPPING regDomainPairs[] = { {NULL1_ETSIB, NULL1, ETSIB, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, {NULL1_ETSIC, NULL1, ETSIC, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, - {FCC2_FCCA, FCC2, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {FCC2_FCCA, FCC2, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, {FCC2_WORLD, FCC2, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, {FCC2_ETSIC, FCC2, ETSIC, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, - {FCC3_FCCA, FCC3, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, - {FCC3_WORLD, FCC3, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, - {FCC4_FCCA, FCC4, FCCA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 }, + {FCC3_FCCA, FCC3, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {FCC3_WORLD, FCC3, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {FCC4_FCCA, FCC4, FCCA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 }, + {FCC5_FCCB, FCC5, FCCB, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, {ETSI1_WORLD, ETSI1, WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 }, {ETSI2_WORLD, ETSI2, WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 }, @@ -505,7 +510,7 @@ static REG_DMN_PAIR_MAPPING regDomainPairs[] = { {FRANCE_RES, ETSI3, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, {FCC1_WORLD, FCC1, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, - {FCC1_FCCA, FCC1, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {FCC1_FCCA, FCC1, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, {APL1_WORLD, APL1, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, {APL2_WORLD, APL2, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, {APL3_WORLD, APL3, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, @@ -515,10 +520,10 @@ static REG_DMN_PAIR_MAPPING regDomainPairs[] = { {APL8_WORLD, APL8, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, {APL9_WORLD, APL9, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, - {APL3_FCCA, APL3, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {APL3_FCCA, APL3, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, {APL1_ETSIC, APL1, ETSIC, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, {APL2_ETSIC, APL2, ETSIC, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, - {APL2_APLD, APL2, APLD, NO_REQ, NO_REQ, PSCAN_DEFER, }, + {APL2_APLD, APL2, APLD, NO_REQ, NO_REQ, PSCAN_DEFER, }, {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 }, @@ -531,19 +536,19 @@ static REG_DMN_PAIR_MAPPING regDomainPairs[] = { {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, 0 }, + {MKK3_MKKA, MKK3, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC , PSCAN_MKKA, 0 }, {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, 0 }, + {MKK3_MKKA1, MKK3, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKKA1 | PSCAN_MKKA1_G, 0 }, {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, 0 }, + {MKK3_FCCA, MKK3, FCCA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, NO_PSCAN, 0 }, /* 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, 0 }, + {MKK4_MKKA1, MKK4, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA1 | PSCAN_MKKA1_G, 0 }, {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, 0 }, + {MKK4_FCCA, MKK4, FCCA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3, 0 }, /* 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 }, @@ -565,8 +570,8 @@ static REG_DMN_PAIR_MAPPING regDomainPairs[] = { {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, 0 }, - {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, 0 }, + {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, 0 }, + {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, 0 }, /* These are super domains */ {WOR0_WORLD, WOR0_WORLD, WOR0_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, @@ -580,26 +585,13 @@ static REG_DMN_PAIR_MAPPING regDomainPairs[] = { {EU1_WORLD, EU1_WORLD, EU1_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, {WOR9_WORLD, WOR9_WORLD, WOR9_WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 }, {WORA_WORLD, WORA_WORLD, WORA_WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 }, + {SR9_WORLD, NULL1, SR9_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_SR9 }, + {XR9_WORLD, NULL1, XR9_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_XR9 }, + {GZ901_WORLD, NULL1, GZ901_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_GZ901 }, }; -/* - * The following table of vendor specific regdomain pairs and - * additional flags used to modify the flags5GHz and flags2GHz - * of the original regdomain - */ - -#define NO_INTERSECT_REQ 0xFFFFFFFF -#define NO_UNION_REQ 0 -#define MAX_MAPS 2 - -struct ccmap { - char isoName[3]; - HAL_CTRY_CODE countryCode; -}; - - /* - * The following table is the master list for all different freqeuncy + * The following tables are the master list for all different freqeuncy * bands with the complete matrix of all possible flags and settings * for each band if it is used in ANY reg domain. */ @@ -667,6 +659,7 @@ static COUNTRY_CODE_TO_ENUM_RD allCountries[] = { {CTRY_GERMANY, ETSI1_WORLD, YES, NO, YES, YES,YES, YES,YES, 7000 }, {CTRY_GREECE, ETSI1_WORLD, YES, NO, YES, YES,YES, YES,YES, 7000 }, {CTRY_GUATEMALA, FCC1_FCCA, YES, YES, YES, YES,YES, YES,YES, 7000 }, + {CTRY_GZ901, GZ901_WORLD, YES, NO, NO, NO, NO, NO, NO, 7000 }, {CTRY_HONDURAS, NULL1_WORLD, YES, NO, YES, YES,YES, YES, NO, 7000 }, {CTRY_HONG_KONG, FCC2_WORLD, YES, YES, YES, YES,YES, YES,YES, 7000 }, {CTRY_HUNGARY, ETSI1_WORLD, YES, NO, YES, YES,YES, YES,YES, 7000 }, @@ -748,6 +741,7 @@ static COUNTRY_CODE_TO_ENUM_RD allCountries[] = { {CTRY_SLOVENIA, ETSI1_WORLD, YES, NO, YES, YES,YES, YES,YES, 7000 }, {CTRY_SOUTH_AFRICA,FCC3_WORLD, YES, NO, YES, YES,YES, YES, NO, 7000 }, {CTRY_SPAIN, ETSI1_WORLD, YES, NO, YES, YES,YES, YES,YES, 7000 }, + {CTRY_SR9, SR9_WORLD, YES, NO, NO, NO, NO, NO, NO, 7000 }, {CTRY_SWEDEN, ETSI1_WORLD, YES, NO, YES, YES,YES, YES,YES, 7000 }, {CTRY_SWITZERLAND, ETSI1_WORLD, YES, NO, YES, YES,YES, YES,YES, 7000 }, {CTRY_SYRIA, NULL1_WORLD, YES, NO, YES, YES,YES, YES, NO, 7000 }, @@ -765,11 +759,35 @@ static COUNTRY_CODE_TO_ENUM_RD allCountries[] = { {CTRY_UZBEKISTAN, FCC3_FCCA, YES, YES, YES, YES,YES, YES,YES, 7000 }, {CTRY_VENEZUELA, APL2_ETSIC, YES, NO, YES, YES,YES, YES, NO, 7000 }, {CTRY_VIET_NAM, NULL1_WORLD, YES, NO, YES, YES,YES, NO, NO, 7000 }, + {CTRY_XR9, XR9_WORLD, YES, NO, NO, NO, NO, NO, NO, 7000 }, {CTRY_YEMEN, NULL1_WORLD, YES, NO, YES, YES,YES, NO, NO, 7000 }, {CTRY_ZIMBABWE, NULL1_WORLD, YES, NO, YES, YES,YES, NO, NO, 7000 } }; -typedef struct RegDmnFreqBand { +/* 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) + +/* + * 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 @@ -785,851 +803,1102 @@ typedef struct RegDmnFreqBand { uint8_t regClassId; /* Regulatory class id */ } REG_DMN_FREQ_BAND; -/* Bit masks for DFS per regdomain */ - -enum { - NO_DFS = 0x0000000000000000ULL, - DFS_FCC3 = 0x0000000000000001ULL, - DFS_ETSI = 0x0000000000000002ULL, - DFS_MKK4 = 0x0000000000000004ULL, -}; - -/* The table of frequency bands is indexed by a bitmask. The ordering - * must be consistent with the enum below. When adding a new - * frequency band, be sure to match the location in the enum with the - * comments - */ - /* * 5GHz 11A channel tags */ - -enum { - F1_4915_4925, - F1_4935_4945, - F1_4920_4980, - F1_4942_4987, - F1_4945_4985, - F1_4950_4980, - F1_5035_5040, - F1_5040_5080, - F1_5055_5055, - - F1_5120_5240, - - F1_5170_5230, - F2_5170_5230, - - F1_5180_5240, - F2_5180_5240, - F3_5180_5240, - F4_5180_5240, - F5_5180_5240, - F6_5180_5240, - - F1_5180_5320, - - F1_5240_5280, - - F1_5260_5280, - - F1_5260_5320, - F2_5260_5320, - F3_5260_5320, - F4_5260_5320, - F5_5260_5320, - F6_5260_5320, - - F1_5260_5700, - - F1_5280_5320, - - F1_5500_5620, - - F1_5500_5700, - F2_5500_5700, - F3_5500_5700, - F4_5500_5700, - - F1_5745_5805, - F2_5745_5805, - F3_5745_5805, - - F1_5745_5825, - F2_5745_5825, - F3_5745_5825, - F4_5745_5825, - F5_5745_5825, - F6_5745_5825, - - W1_4920_4980, - W1_5040_5080, - W1_5170_5230, - W1_5180_5240, - W1_5260_5320, - W1_5745_5825, - W1_5500_5700, - W2_5260_5320, - W2_5180_5240, - W2_5825_5825, -}; - static REG_DMN_FREQ_BAND regDmn5GhzFreq[] = { - { 4915, 4925, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2, 16 }, /* F1_4915_4925 */ - { 4935, 4945, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2, 16 }, /* F1_4935_4945 */ - { 4920, 4980, 23, 0, 20, 20, NO_DFS, PSCAN_MKK2, 7 }, /* F1_4920_4980 */ - { 4942, 4987, 27, 6, 5, 5, NO_DFS, PSCAN_FCC, 0 }, /* F1_4942_4987 */ - { 4945, 4985, 30, 6, 10, 5, NO_DFS, PSCAN_FCC, 0 }, /* F1_4945_4985 */ - { 4950, 4980, 33, 6, 20, 5, NO_DFS, PSCAN_FCC, 0 }, /* F1_4950_4980 */ - { 5035, 5040, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2, 12 }, /* F1_5035_5040 */ - { 5040, 5080, 23, 0, 20, 20, NO_DFS, PSCAN_MKK2, 2 }, /* F1_5040_5080 */ - { 5055, 5055, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2, 12 }, /* F1_5055_5055 */ + { 4915, 4925, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2, 16 }, +#define F1_4915_4925 0 + { 4935, 4945, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2, 16 }, +#define F1_4935_4945 AFTER(F1_4915_4925) + { 4920, 4980, 23, 0, 20, 20, NO_DFS, PSCAN_MKK2, 7 }, +#define F1_4920_4980 AFTER(F1_4935_4945) + { 4942, 4987, 27, 6, 5, 5, NO_DFS, PSCAN_FCC, 0 }, +#define F1_4942_4987 AFTER(F1_4920_4980) + { 4945, 4985, 30, 6, 10, 5, NO_DFS, PSCAN_FCC, 0 }, +#define F1_4945_4985 AFTER(F1_4942_4987) + { 4950, 4980, 33, 6, 20, 5, NO_DFS, PSCAN_FCC, 0 }, +#define F1_4950_4980 AFTER(F1_4945_4985) + { 5035, 5040, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2, 12 }, +#define F1_5035_5040 AFTER(F1_4950_4980) + { 5040, 5080, 23, 0, 20, 20, NO_DFS, PSCAN_MKK2, 2 }, +#define F1_5040_5080 AFTER(F1_5035_5040) + { 5055, 5055, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2, 12 }, +#define F1_5055_5055 AFTER(F1_5040_5080) - { 5120, 5240, 5, 6, 20, 20, NO_DFS, NO_PSCAN, 0 }, /* F1_5120_5240 */ + { 5120, 5240, 5, 6, 20, 20, NO_DFS, NO_PSCAN, 0 }, +#define F1_5120_5240 AFTER(F1_5055_5055) + { 5120, 5240, 5, 6, 10, 10, NO_DFS, NO_PSCAN, 0 }, +#define F2_5120_5240 AFTER(F1_5120_5240) + { 5120, 5240, 5, 6, 5, 5, NO_DFS, NO_PSCAN, 0 }, +#define F3_5120_5240 AFTER(F2_5120_5240) - { 5170, 5230, 23, 0, 20, 20, NO_DFS, PSCAN_MKK1 | PSCAN_MKK2, 1 }, /* F1_5170_5230 */ - { 5170, 5230, 20, 0, 20, 20, NO_DFS, PSCAN_MKK1 | PSCAN_MKK2, 1 }, /* F2_5170_5230 */ + { 5170, 5230, 23, 0, 20, 20, NO_DFS, PSCAN_MKK1 | PSCAN_MKK2, 1 }, +#define F1_5170_5230 AFTER(F3_5120_5240) + { 5170, 5230, 20, 0, 20, 20, NO_DFS, PSCAN_MKK1 | PSCAN_MKK2, 1 }, +#define F2_5170_5230 AFTER(F1_5170_5230) - { 5180, 5240, 15, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI, 0 }, /* F1_5180_5240 */ - { 5180, 5240, 17, 6, 20, 20, NO_DFS, PSCAN_FCC, 1 }, /* F2_5180_5240 */ - { 5180, 5240, 18, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI, 0 }, /* F3_5180_5240 */ - { 5180, 5240, 20, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI, 0 }, /* F4_5180_5240 */ - { 5180, 5240, 23, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI, 0 }, /* F5_5180_5240 */ - { 5180, 5240, 23, 6, 20, 20, NO_DFS, PSCAN_FCC, 0 }, /* F6_5180_5240 */ + { 5180, 5240, 15, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI, 0 }, +#define F1_5180_5240 AFTER(F2_5170_5230) + { 5180, 5240, 17, 6, 20, 20, NO_DFS, PSCAN_FCC, 1 }, +#define F2_5180_5240 AFTER(F1_5180_5240) + { 5180, 5240, 18, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI, 0 }, +#define F3_5180_5240 AFTER(F2_5180_5240) + { 5180, 5240, 20, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI, 0 }, +#define F4_5180_5240 AFTER(F3_5180_5240) + { 5180, 5240, 23, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI, 0 }, +#define F5_5180_5240 AFTER(F4_5180_5240) + { 5180, 5240, 23, 6, 20, 20, NO_DFS, PSCAN_FCC, 0 }, +#define F6_5180_5240 AFTER(F5_5180_5240) + { 5180, 5240, 17, 6, 20, 10, NO_DFS, PSCAN_FCC, 1 }, +#define F7_5180_5240 AFTER(F6_5180_5240) + { 5180, 5240, 17, 6, 20, 5, NO_DFS, PSCAN_FCC, 1 }, +#define F8_5180_5240 AFTER(F7_5180_5240) - { 5180, 5320, 20, 6, 20, 20, DFS_ETSI, PSCAN_ETSI, 0 }, /* F1_5180_5320 */ + { 5180, 5320, 20, 6, 20, 20, DFS_ETSI, PSCAN_ETSI, 0 }, +#define F1_5180_5320 AFTER(F8_5180_5240) - { 5240, 5280, 23, 0, 20, 20, DFS_FCC3, PSCAN_FCC | PSCAN_ETSI, 0 }, /* F1_5240_5280 */ + { 5240, 5280, 23, 0, 20, 20, DFS_FCC3, PSCAN_FCC | PSCAN_ETSI, 0 }, +#define F1_5240_5280 AFTER(F1_5180_5320) - { 5260, 5280, 23, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI, 0 }, /* F1_5260_5280 */ + { 5260, 5280, 23, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI, 0 }, +#define F1_5260_5280 AFTER(F1_5240_5280) - { 5260, 5320, 18, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI, 0 }, /* F1_5260_5320 */ + { 5260, 5320, 18, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI, 0 }, +#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 , 0 }, - /* F2_5260_5320 */ +#define F2_5260_5320 AFTER(F1_5260_5320) - { 5260, 5320, 20, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 2 }, /* F3_5260_5320 */ - { 5260, 5320, 23, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 2 }, /* F4_5260_5320 */ - { 5260, 5320, 23, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 0 }, /* F5_5260_5320 */ - { 5260, 5320, 30, 0, 20, 20, NO_DFS, NO_PSCAN, 0 }, /* F6_5260_5320 */ + { 5260, 5320, 20, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 2 }, +#define F3_5260_5320 AFTER(F2_5260_5320) + { 5260, 5320, 23, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 2 }, +#define F4_5260_5320 AFTER(F3_5260_5320) + { 5260, 5320, 23, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 0 }, +#define F5_5260_5320 AFTER(F4_5260_5320) + { 5260, 5320, 30, 0, 20, 20, NO_DFS, NO_PSCAN, 0 }, +#define F6_5260_5320 AFTER(F5_5260_5320) + { 5260, 5320, 23, 6, 20, 10, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 2 }, +#define F7_5260_5320 AFTER(F6_5260_5320) + { 5260, 5320, 23, 6, 20, 5, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 2 }, +#define F8_5260_5320 AFTER(F7_5260_5320) - { 5260, 5700, 5, 6, 20, 20, DFS_FCC3 | DFS_ETSI, NO_PSCAN, 0 }, /* F1_5260_5700 */ + { 5260, 5700, 5, 6, 20, 20, DFS_FCC3 | DFS_ETSI, NO_PSCAN, 0 }, +#define F1_5260_5700 AFTER(F8_5260_5320) + { 5260, 5700, 5, 6, 10, 10, DFS_FCC3 | DFS_ETSI, NO_PSCAN, 0 }, +#define F2_5260_5700 AFTER(F1_5260_5700) + { 5260, 5700, 5, 6, 5, 5, DFS_FCC3 | DFS_ETSI, NO_PSCAN, 0 }, +#define F3_5260_5700 AFTER(F2_5260_5700) - { 5280, 5320, 17, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 0 }, /* F1_5280_5320 */ + { 5280, 5320, 17, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 0 }, +#define F1_5280_5320 AFTER(F3_5260_5700) - { 5500, 5620, 30, 6, 20, 20, DFS_ETSI, PSCAN_ETSI, 0 }, /* F1_5500_5620 */ + { 5500, 5620, 30, 6, 20, 20, DFS_ETSI, PSCAN_ETSI, 0 }, +#define F1_5500_5620 AFTER(F1_5280_5320) - { 5500, 5700, 20, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 4 }, /* F1_5500_5700 */ - { 5500, 5700, 27, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI, 0 }, /* F2_5500_5700 */ - { 5500, 5700, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI, 0 }, /* F3_5500_5700 */ + { 5500, 5700, 20, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 4 }, +#define F1_5500_5700 AFTER(F1_5500_5620) + { 5500, 5700, 27, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI, 0 }, +#define F2_5500_5700 AFTER(F1_5500_5700) + { 5500, 5700, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI, 0 }, +#define F3_5500_5700 AFTER(F2_5500_5700) { 5500, 5700, 23, 0, 20, 20, DFS_FCC3 | DFS_ETSI | DFS_MKK4, PSCAN_MKK3 | PSCAN_FCC, 0 }, - /* F4_5500_5700 */ +#define F4_5500_5700 AFTER(F3_5500_5700) - { 5745, 5805, 23, 0, 20, 20, NO_DFS, NO_PSCAN, 0 }, /* F1_5745_5805 */ - { 5745, 5805, 30, 6, 20, 20, NO_DFS, NO_PSCAN, 0 }, /* F2_5745_5805 */ - { 5745, 5805, 30, 6, 20, 20, DFS_ETSI, PSCAN_ETSI, 0 }, /* F3_5745_5805 */ - { 5745, 5825, 5, 6, 20, 20, NO_DFS, NO_PSCAN, 0 }, /* F1_5745_5825 */ - { 5745, 5825, 17, 0, 20, 20, NO_DFS, NO_PSCAN, 0 }, /* F2_5745_5825 */ - { 5745, 5825, 20, 0, 20, 20, NO_DFS, NO_PSCAN, 0 }, /* F3_5745_5825 */ - { 5745, 5825, 30, 0, 20, 20, NO_DFS, NO_PSCAN, 0 }, /* F4_5745_5825 */ - { 5745, 5825, 30, 6, 20, 20, NO_DFS, NO_PSCAN, 3 }, /* F5_5745_5825 */ - { 5745, 5825, 30, 6, 20, 20, NO_DFS, NO_PSCAN, 0 }, /* F6_5745_5825 */ + { 5745, 5805, 23, 0, 20, 20, NO_DFS, NO_PSCAN, 0 }, +#define F1_5745_5805 AFTER(F4_5500_5700) + { 5745, 5805, 30, 6, 20, 20, NO_DFS, NO_PSCAN, 0 }, +#define F2_5745_5805 AFTER(F1_5745_5805) + { 5745, 5805, 30, 6, 20, 20, DFS_ETSI, PSCAN_ETSI, 0 }, +#define F3_5745_5805 AFTER(F2_5745_5805) + { 5745, 5825, 5, 6, 20, 20, NO_DFS, NO_PSCAN, 0 }, +#define F1_5745_5825 AFTER(F3_5745_5805) + { 5745, 5825, 17, 0, 20, 20, NO_DFS, NO_PSCAN, 0 }, +#define F2_5745_5825 AFTER(F1_5745_5825) + { 5745, 5825, 20, 0, 20, 20, NO_DFS, NO_PSCAN, 0 }, +#define F3_5745_5825 AFTER(F2_5745_5825) + { 5745, 5825, 30, 0, 20, 20, NO_DFS, NO_PSCAN, 0 }, +#define F4_5745_5825 AFTER(F3_5745_5825) + { 5745, 5825, 30, 6, 20, 20, NO_DFS, NO_PSCAN, 3 }, +#define F5_5745_5825 AFTER(F4_5745_5825) + { 5745, 5825, 30, 6, 20, 20, NO_DFS, NO_PSCAN, 0 }, +#define F6_5745_5825 AFTER(F5_5745_5825) + { 5745, 5825, 5, 6, 10, 10, NO_DFS, NO_PSCAN, 0 }, +#define F7_5745_5825 AFTER(F6_5745_5825) + { 5745, 5825, 5, 6, 5, 5, NO_DFS, NO_PSCAN, 0 }, +#define F8_5745_5825 AFTER(F7_5745_5825) + { 5745, 5825, 30, 6, 20, 10, NO_DFS, NO_PSCAN, 3 }, +#define F9_5745_5825 AFTER(F8_5745_5825) + { 5745, 5825, 30, 6, 20, 5, NO_DFS, NO_PSCAN, 3 }, +#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, 0 }, /* W1_4920_4980 */ - { 5040, 5080, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0 }, /* W1_5040_5080 */ - { 5170, 5230, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0 }, /* W1_5170_5230 */ - { 5180, 5240, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0 }, /* W1_5180_5240 */ - { 5260, 5320, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0 }, /* W1_5260_5320 */ - { 5745, 5825, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0 }, /* W1_5745_5825 */ - { 5500, 5700, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0 }, /* W1_5500_5700 */ - { 5260, 5320, 30, 0, 20, 20, NO_DFS, NO_PSCAN, 0 }, /* W2_5260_5320 */ - { 5180, 5240, 30, 0, 20, 20, NO_DFS, NO_PSCAN, 0 }, /* W2_5180_5240 */ - { 5825, 5825, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0 }, /* W2_5825_5825 */ + { 4920, 4980, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0 }, +#define W1_4920_4980 AFTER(F10_5745_5825) + { 5040, 5080, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0 }, +#define W1_5040_5080 AFTER(W1_4920_4980) + { 5170, 5230, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0 }, +#define W1_5170_5230 AFTER(W1_5040_5080) + { 5180, 5240, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0 }, +#define W1_5180_5240 AFTER(W1_5170_5230) + { 5260, 5320, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0 }, +#define W1_5260_5320 AFTER(W1_5180_5240) + { 5745, 5825, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0 }, +#define W1_5745_5825 AFTER(W1_5260_5320) + { 5500, 5700, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0 }, +#define W1_5500_5700 AFTER(W1_5745_5825) + { 5260, 5320, 30, 0, 20, 20, NO_DFS, NO_PSCAN, 0 }, +#define W2_5260_5320 AFTER(W1_5500_5700) + { 5180, 5240, 30, 0, 20, 20, NO_DFS, NO_PSCAN, 0 }, +#define W2_5180_5240 AFTER(W2_5260_5320) + { 5825, 5825, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0 }, +#define W2_5825_5825 AFTER(W2_5180_5240) }; /* * 5GHz Turbo (dynamic & static) tags */ - -enum { - T1_5130_5210, - T1_5250_5330, - T1_5370_5490, - T1_5530_5650, - - T1_5150_5190, - T1_5230_5310, - T1_5350_5470, - T1_5510_5670, - - T1_5200_5240, - T2_5200_5240, - T1_5210_5210, - T2_5210_5210, - - T1_5280_5280, - T2_5280_5280, - T1_5250_5250, - T1_5290_5290, - T1_5250_5290, - T2_5250_5290, - - T1_5540_5660, - T1_5760_5800, - T2_5760_5800, - - T1_5765_5805, - - WT1_5210_5250, - WT1_5290_5290, - WT1_5540_5660, - WT1_5760_5800, -}; - static REG_DMN_FREQ_BAND regDmn5GhzTurboFreq[] = { - { 5130, 5210, 5, 6, 40, 40, NO_DFS, NO_PSCAN, 0}, /* T1_5130_5210 */ - { 5250, 5330, 5, 6, 40, 40, DFS_FCC3, NO_PSCAN, 0}, /* T1_5250_5330 */ - { 5370, 5490, 5, 6, 40, 40, NO_DFS, NO_PSCAN, 0}, /* T1_5370_5490 */ - { 5530, 5650, 5, 6, 40, 40, DFS_FCC3, NO_PSCAN, 0}, /* T1_5530_5650 */ + { 5130, 5210, 5, 6, 40, 40, NO_DFS, NO_PSCAN, 0}, +#define T1_5130_5210 0 + { 5250, 5330, 5, 6, 40, 40, DFS_FCC3, NO_PSCAN, 0}, +#define T1_5250_5330 AFTER(T1_5130_5210) + { 5370, 5490, 5, 6, 40, 40, NO_DFS, NO_PSCAN, 0}, +#define T1_5370_5490 AFTER(T1_5250_5330) + { 5530, 5650, 5, 6, 40, 40, DFS_FCC3, NO_PSCAN, 0}, +#define T1_5530_5650 AFTER(T1_5370_5490) - { 5150, 5190, 5, 6, 40, 40, NO_DFS, NO_PSCAN, 0}, /* T1_5150_5190 */ - { 5230, 5310, 5, 6, 40, 40, DFS_FCC3, NO_PSCAN, 0}, /* T1_5230_5310 */ - { 5350, 5470, 5, 6, 40, 40, NO_DFS, NO_PSCAN, 0}, /* T1_5350_5470 */ - { 5510, 5670, 5, 6, 40, 40, DFS_FCC3, NO_PSCAN, 0}, /* T1_5510_5670 */ + { 5150, 5190, 5, 6, 40, 40, NO_DFS, NO_PSCAN, 0}, +#define T1_5150_5190 AFTER(T1_5530_5650) + { 5230, 5310, 5, 6, 40, 40, DFS_FCC3, NO_PSCAN, 0}, +#define T1_5230_5310 AFTER(T1_5150_5190) + { 5350, 5470, 5, 6, 40, 40, NO_DFS, NO_PSCAN, 0}, +#define T1_5350_5470 AFTER(T1_5230_5310) + { 5510, 5670, 5, 6, 40, 40, DFS_FCC3, NO_PSCAN, 0}, +#define T1_5510_5670 AFTER(T1_5350_5470) - { 5200, 5240, 17, 6, 40, 40, NO_DFS, NO_PSCAN, 0}, /* T1_5200_5240 */ - { 5200, 5240, 23, 6, 40, 40, NO_DFS, NO_PSCAN, 0}, /* T2_5200_5240 */ - { 5210, 5210, 17, 6, 40, 40, NO_DFS, NO_PSCAN, 0}, /* T1_5210_5210 */ - { 5210, 5210, 23, 0, 40, 40, NO_DFS, NO_PSCAN, 0}, /* T2_5210_5210 */ + { 5200, 5240, 17, 6, 40, 40, NO_DFS, NO_PSCAN, 0}, +#define T1_5200_5240 AFTER(T1_5510_5670) + { 5200, 5240, 23, 6, 40, 40, NO_DFS, NO_PSCAN, 0}, +#define T2_5200_5240 AFTER(T1_5200_5240) + { 5210, 5210, 17, 6, 40, 40, NO_DFS, NO_PSCAN, 0}, +#define T1_5210_5210 AFTER(T2_5200_5240) + { 5210, 5210, 23, 0, 40, 40, NO_DFS, NO_PSCAN, 0}, +#define T2_5210_5210 AFTER(T1_5210_5210) - { 5280, 5280, 23, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0}, /* T1_5280_5280 */ - { 5280, 5280, 20, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0}, /* T2_5280_5280 */ - { 5250, 5250, 17, 0, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0}, /* T1_5250_5250 */ - { 5290, 5290, 20, 0, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0}, /* T1_5290_5290 */ - { 5250, 5290, 20, 0, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0}, /* T1_5250_5290 */ - { 5250, 5290, 23, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0}, /* T2_5250_5290 */ + { 5280, 5280, 23, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0}, +#define T1_5280_5280 AFTER(T2_5210_5210) + { 5280, 5280, 20, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0}, +#define T2_5280_5280 AFTER(T1_5280_5280) + { 5250, 5250, 17, 0, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0}, +#define T1_5250_5250 AFTER(T2_5280_5280) + { 5290, 5290, 20, 0, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0}, +#define T1_5290_5290 AFTER(T1_5250_5250) + { 5250, 5290, 20, 0, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0}, +#define T1_5250_5290 AFTER(T1_5290_5290) + { 5250, 5290, 23, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0}, +#define T2_5250_5290 AFTER(T1_5250_5290) - { 5540, 5660, 20, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0}, /* T1_5540_5660 */ - { 5760, 5800, 20, 0, 40, 40, NO_DFS, NO_PSCAN, 0}, /* T1_5760_5800 */ - { 5760, 5800, 30, 6, 40, 40, NO_DFS, NO_PSCAN, 0}, /* T2_5760_5800 */ + { 5540, 5660, 20, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0}, +#define T1_5540_5660 AFTER(T2_5250_5290) + { 5760, 5800, 20, 0, 40, 40, NO_DFS, NO_PSCAN, 0}, +#define T1_5760_5800 AFTER(T1_5540_5660) + { 5760, 5800, 30, 6, 40, 40, NO_DFS, NO_PSCAN, 0}, +#define T2_5760_5800 AFTER(T1_5760_5800) - { 5765, 5805, 30, 6, 40, 40, NO_DFS, NO_PSCAN, 0}, /* T1_5765_5805 */ + { 5765, 5805, 30, 6, 40, 40, NO_DFS, NO_PSCAN, 0}, +#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, 0}, /* WT1_5210_5250 */ - { 5290, 5290, 18, 0, 40, 40, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0}, /* WT1_5290_5290 */ - { 5540, 5660, 20, 0, 40, 40, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0}, /* WT1_5540_5660 */ - { 5760, 5800, 20, 0, 40, 40, NO_DFS, PSCAN_WWR, 0}, /* WT1_5760_5800 */ + { 5210, 5250, 15, 0, 40, 40, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0}, +#define WT1_5210_5250 AFTER(T1_5765_5805) + { 5290, 5290, 18, 0, 40, 40, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0}, +#define WT1_5290_5290 AFTER(WT1_5210_5250) + { 5540, 5660, 20, 0, 40, 40, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0}, +#define WT1_5540_5660 AFTER(WT1_5290_5290) + { 5760, 5800, 20, 0, 40, 40, NO_DFS, PSCAN_WWR, 0}, +#define WT1_5760_5800 AFTER(WT1_5540_5660) }; /* * 2GHz 11b channel tags */ -enum { - F1_2312_2372, - F2_2312_2372, - - F1_2412_2472, - F2_2412_2472, - F3_2412_2472, - - F1_2412_2462, - F2_2412_2462, - - F1_2432_2442, - - F1_2457_2472, - - F1_2467_2472, - - F1_2484_2484, - F2_2484_2484, - - F1_2512_2732, - - W1_2312_2372, - W1_2412_2412, - W1_2417_2432, - W1_2437_2442, - W1_2447_2457, - W1_2462_2462, - W1_2467_2467, - W2_2467_2467, - W1_2472_2472, - W2_2472_2472, - W1_2484_2484, - W2_2484_2484, -}; - static REG_DMN_FREQ_BAND regDmn2GhzFreq[] = { - { 2312, 2372, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, /* F1_2312_2372 */ - { 2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, /* F2_2312_2372 */ + { 2312, 2372, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define F1_2312_2372 0 + { 2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define F2_2312_2372 AFTER(F1_2312_2372) - { 2412, 2472, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, /* F1_2412_2472 */ - { 2412, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA, 0}, /* F2_2412_2472 */ - { 2412, 2472, 30, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, /* F3_2412_2472 */ + { 2412, 2472, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define F1_2412_2472 AFTER(F2_2312_2372) + { 2412, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA, 0}, +#define F2_2412_2472 AFTER(F1_2412_2472) + { 2412, 2472, 30, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define F3_2412_2472 AFTER(F2_2412_2472) - { 2412, 2462, 27, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, /* F1_2412_2462 */ - { 2412, 2462, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA, 0}, /* F2_2412_2462 */ - - { 2432, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, /* F1_2432_2442 */ + { 2412, 2462, 27, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define F1_2412_2462 AFTER(F3_2412_2472) + { 2412, 2462, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA, 0}, +#define F2_2412_2462 AFTER(F1_2412_2462) - { 2457, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, /* F1_2457_2472 */ + { 2432, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define F1_2432_2442 AFTER(F2_2412_2462) - { 2467, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA2 | PSCAN_MKKA, 0}, /* F1_2467_2472 */ + { 2457, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define F1_2457_2472 AFTER(F1_2432_2442) - { 2484, 2484, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, /* F1_2484_2484 */ - { 2484, 2484, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA | PSCAN_MKKA1 | PSCAN_MKKA2, 0}, /* F2_2484_2484 */ + { 2467, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA2 | PSCAN_MKKA, 0}, +#define F1_2467_2472 AFTER(F1_2457_2472) - { 2512, 2732, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, /* F1_2512_2732 */ + { 2484, 2484, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define F1_2484_2484 AFTER(F1_2467_2472) + { 2484, 2484, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA | PSCAN_MKKA1 | PSCAN_MKKA2, 0}, +#define F2_2484_2484 AFTER(F1_2484_2484) + + { 2512, 2732, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define F1_2512_2732 AFTER(F2_2484_2484) /* - * WWR have powers opened up to 20dBm. Limits should often come from CTL/Max powers + * 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, 0}, /* W1_2312_2372 */ - { 2412, 2412, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, /* W1_2412_2412 */ - { 2417, 2432, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, /* W1_2417_2432 */ - { 2437, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, /* W1_2437_2442 */ - { 2447, 2457, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, /* W1_2447_2457 */ - { 2462, 2462, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, /* W1_2462_2462 */ - { 2467, 2467, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0}, /* W1_2467_2467 */ - { 2467, 2467, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0}, /* W2_2467_2467 */ - { 2472, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0}, /* W1_2472_2472 */ - { 2472, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0}, /* W2_2472_2472 */ - { 2484, 2484, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0}, /* W1_2484_2484 */ - { 2484, 2484, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0}, /* W2_2484_2484 */ + { 2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define W1_2312_2372 AFTER(F1_2512_2732) + { 2412, 2412, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define W1_2412_2412 AFTER(W1_2312_2372) + { 2417, 2432, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define W1_2417_2432 AFTER(W1_2412_2412) + { 2437, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define W1_2437_2442 AFTER(W1_2417_2432) + { 2447, 2457, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define W1_2447_2457 AFTER(W1_2437_2442) + { 2462, 2462, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define W1_2462_2462 AFTER(W1_2447_2457) + { 2467, 2467, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0}, +#define W1_2467_2467 AFTER(W1_2462_2462) + { 2467, 2467, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0}, +#define W2_2467_2467 AFTER(W1_2467_2467) + { 2472, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0}, +#define W1_2472_2472 AFTER(W2_2467_2467) + { 2472, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0}, +#define W2_2472_2472 AFTER(W1_2472_2472) + { 2484, 2484, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0}, +#define W1_2484_2484 AFTER(W2_2472_2472) + { 2484, 2484, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0}, +#define W2_2484_2484 AFTER(W1_2484_2484) }; /* * 2GHz 11g channel tags */ - -enum { - G1_2312_2372, - G2_2312_2372, - - G1_2412_2472, - G2_2412_2472, - G3_2412_2472, - - G1_2412_2462, - G2_2412_2462, - - G1_2432_2442, - - G1_2457_2472, - - G1_2512_2732, - - G1_2467_2472 , - - WG1_2312_2372, - WG1_2412_2412, - WG1_2417_2432, - WG1_2437_2442, - WG1_2447_2457, - WG1_2462_2462, - WG1_2467_2467, - WG2_2467_2467, - WG1_2472_2472, - WG2_2472_2472, - - S1_907_922_5, - S1_907_922_10, - S1_912_917, - - S2_907_922_5, - S2_907_922_10, - S2_912_917, -}; - static REG_DMN_FREQ_BAND regDmn2Ghz11gFreq[] = { - { 2312, 2372, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, /* G1_2312_2372 */ - { 2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, /* G2_2312_2372 */ + { 2312, 2372, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define G1_2312_2372 0 + { 2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define G2_2312_2372 AFTER(G1_2312_2372) + { 2312, 2372, 5, 6, 10, 5, NO_DFS, NO_PSCAN, 0}, +#define G3_2312_2372 AFTER(G2_2312_2372) + { 2312, 2372, 5, 6, 5, 5, NO_DFS, NO_PSCAN, 0}, +#define G4_2312_2372 AFTER(G3_2312_2372) - { 2412, 2472, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, /* G1_2412_2472 */ - { 2412, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA_G, 0}, /* G2_2412_2472 */ - { 2412, 2472, 30, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, /* G3_2412_2472 */ + { 2412, 2472, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define G1_2412_2472 AFTER(G4_2312_2372) + { 2412, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA_G, 0}, +#define G2_2412_2472 AFTER(G1_2412_2472) + { 2412, 2472, 30, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define G3_2412_2472 AFTER(G2_2412_2472) + { 2412, 2472, 5, 6, 10, 5, NO_DFS, NO_PSCAN, 0}, +#define G4_2412_2472 AFTER(G3_2412_2472) + { 2412, 2472, 5, 6, 5, 5, NO_DFS, NO_PSCAN, 0}, +#define G5_2412_2472 AFTER(G4_2412_2472) - { 2412, 2462, 27, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, /* G1_2412_2462 */ - { 2412, 2462, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA_G, 0}, /* G2_2412_2462 */ + { 2412, 2462, 27, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define G1_2412_2462 AFTER(G5_2412_2472) + { 2412, 2462, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA_G, 0}, +#define G2_2412_2462 AFTER(G1_2412_2462) + { 2412, 2462, 27, 6, 10, 5, NO_DFS, NO_PSCAN, 0}, +#define G3_2412_2462 AFTER(G2_2412_2462) + { 2412, 2462, 27, 6, 5, 5, NO_DFS, NO_PSCAN, 0}, +#define G4_2412_2462 AFTER(G3_2412_2462) - { 2432, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, /* G1_2432_2442 */ + { 2432, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define G1_2432_2442 AFTER(G4_2412_2462) - { 2457, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, /* G1_2457_2472 */ + { 2457, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define G1_2457_2472 AFTER(G1_2432_2442) - { 2512, 2732, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, /* G1_2512_2732 */ + { 2512, 2732, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define G1_2512_2732 AFTER(G1_2457_2472) + { 2512, 2732, 5, 6, 10, 5, NO_DFS, NO_PSCAN, 0}, +#define G2_2512_2732 AFTER(G1_2512_2732) + { 2512, 2732, 5, 6, 5, 5, NO_DFS, NO_PSCAN, 0}, +#define G3_2512_2732 AFTER(G2_2512_2732) - { 2467, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA2 | PSCAN_MKKA, 0 }, /* G1_2467_2472 */ + { 2467, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA2 | PSCAN_MKKA, 0 }, +#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, 0}, +#define WG1_2312_2372 AFTER(G1_2467_2472) + { 2412, 2412, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define WG1_2412_2412 AFTER(WG1_2312_2372) + { 2417, 2432, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define WG1_2417_2432 AFTER(WG1_2412_2412) + { 2437, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define WG1_2437_2442 AFTER(WG1_2417_2432) + { 2447, 2457, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define WG1_2447_2457 AFTER(WG1_2437_2442) + { 2462, 2462, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, +#define WG1_2462_2462 AFTER(WG1_2447_2457) + { 2467, 2467, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0}, +#define WG1_2467_2467 AFTER(WG1_2462_2462) + { 2467, 2467, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0}, +#define WG2_2467_2467 AFTER(WG1_2467_2467) + { 2472, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0}, +#define WG1_2472_2472 AFTER(WG2_2467_2467) + { 2472, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0}, +#define WG2_2472_2472 AFTER(WG1_2472_2472) - { 2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, /* WG1_2312_2372 */ - { 2412, 2412, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, /* WG1_2412_2412 */ - { 2417, 2432, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, /* WG1_2417_2432 */ - { 2437, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, /* WG1_2437_2442 */ - { 2447, 2457, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, /* WG1_2447_2457 */ - { 2462, 2462, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, /* WG1_2462_2462 */ - { 2467, 2467, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0}, /* WG1_2467_2467 */ - { 2467, 2467, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0}, /* WG2_2467_2467 */ - { 2472, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0}, /* WG1_2472_2472 */ - { 2472, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0}, /* WG2_2472_2472 */ + /* + * Mapping for 900MHz cards like Ubiquiti SR9 and XR9 + * and ZComax GZ-901. + */ + { 2422, 2437, 30, 0, 5, 5, NO_DFS, PSCAN_FCC, 0 }, +#define S1_907_922_5 AFTER(WG2_2472_2472) + { 2422, 2437, 30, 0, 10, 5, NO_DFS, PSCAN_FCC, 0 }, +#define S1_907_922_10 AFTER(S1_907_922_5) + { 2427, 2432, 30, 0, 20, 5, NO_DFS, PSCAN_FCC, 0 }, +#define S1_912_917 AFTER(S1_907_922_10) + { 2427, 2442, 30, 0, 5, 5, NO_DFS, PSCAN_FCC, 0 }, +#define S2_907_922_5 AFTER(S1_912_917) + { 2427, 2442, 30, 0, 10, 5, NO_DFS, PSCAN_FCC, 0 }, +#define S2_907_922_10 AFTER(S2_907_922_5) + { 2432, 2437, 30, 0, 20, 5, NO_DFS, PSCAN_FCC, 0 }, +#define S2_912_917 AFTER(S2_907_922_10) + { 2452, 2467, 30, 0, 5, 5, NO_DFS, PSCAN_FCC, 0 }, +#define S1_908_923_5 AFTER(S2_912_917) + { 2457, 2467, 30, 0, 10, 5, NO_DFS, PSCAN_FCC, 0 }, +#define S1_913_918_10 AFTER(S1_908_923_5) + { 2457, 2467, 30, 0, 20, 5, NO_DFS, PSCAN_FCC, 0 }, +#define S1_913_918 AFTER(S1_913_918_10) }; /* * 2GHz Dynamic turbo tags */ - -enum { - T1_2312_2372, - T1_2437_2437, - T2_2437_2437, - T3_2437_2437, - T1_2512_2732 -}; - static REG_DMN_FREQ_BAND regDmn2Ghz11gTurboFreq[] = { - { 2312, 2372, 5, 6, 40, 40, NO_DFS, NO_PSCAN, 0}, /* T1_2312_2372 */ - { 2437, 2437, 5, 6, 40, 40, NO_DFS, NO_PSCAN, 0}, /* T1_2437_2437 */ - { 2437, 2437, 20, 6, 40, 40, NO_DFS, NO_PSCAN, 0}, /* T2_2437_2437 */ - { 2437, 2437, 18, 6, 40, 40, NO_DFS, PSCAN_WWR, 0}, /* T3_2437_2437 */ - { 2512, 2732, 5, 6, 40, 40, NO_DFS, NO_PSCAN, 0}, /* T1_2512_2732 */ + { 2312, 2372, 5, 6, 40, 40, NO_DFS, NO_PSCAN, 0}, +#define T1_2312_2372 0 + { 2437, 2437, 5, 6, 40, 40, NO_DFS, NO_PSCAN, 0}, +#define T1_2437_2437 AFTER(T1_2312_2372) + { 2437, 2437, 20, 6, 40, 40, NO_DFS, NO_PSCAN, 0}, +#define T2_2437_2437 AFTER(T1_2437_2437) + { 2437, 2437, 18, 6, 40, 40, NO_DFS, PSCAN_WWR, 0}, +#define T3_2437_2437 AFTER(T2_2437_2437) + { 2512, 2732, 5, 6, 40, 40, NO_DFS, NO_PSCAN, 0}, +#define T1_2512_2732 AFTER(T3_2437_2437) }; typedef struct regDomain { - uint16_t regDmnEnum; /* value from EnumRd table */ + uint16_t regDmnEnum; /* value from EnumRd table */ uint8_t conformanceTestLimit; - uint64_t dfsMask; /* DFS bitmask for 5Ghz tables */ - uint64_t pscan; /* Bitmask for passive scan */ - uint32_t flags; /* Requirement flags (AdHoc disallow, noise - floor cal needed, etc) */ - uint64_t chan11a[BMLEN];/* 128 bit bitmask for channel/band - selection */ - uint64_t chan11a_turbo[BMLEN];/* 128 bit bitmask for channel/band - selection */ - uint64_t chan11a_dyn_turbo[BMLEN]; /* 128 bit bitmask for channel/band - selection */ - uint64_t chan11b[BMLEN];/* 128 bit bitmask for channel/band - selection */ - uint64_t chan11g[BMLEN];/* 128 bit bitmask for channel/band - selection */ - uint64_t chan11g_turbo[BMLEN];/* 128 bit bitmask for channel/band - selection */ + 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[] = { - {DEBUG_REG_DMN, FCC, DFS_FCC3, NO_PSCAN, NO_REQ, - BM(F1_5120_5240, F1_5260_5700, F1_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(T1_5130_5210, T1_5250_5330, T1_5370_5490, T1_5530_5650, T1_5150_5190, T1_5230_5310, T1_5350_5470, T1_5510_5670, -1, -1, -1, -1), - BM(T1_5200_5240, T1_5280_5280, T1_5540_5660, T1_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1), - BM(F1_2312_2372, F1_2412_2472, F1_2484_2484, F1_2512_2732, -1, -1, -1, -1, -1, -1, -1, -1), - BM(G1_2312_2372, G1_2412_2472, G1_2512_2732, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(T1_2312_2372, T1_2437_2437, T1_2512_2732, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, + {.regDmnEnum = DEBUG_REG_DMN, + .conformanceTestLimit = FCC, + .dfsMask = DFS_FCC3, + .chan11a = BM3(F1_5120_5240, F1_5260_5700, F1_5745_5825), + .chan11a_half = BM3(F2_5120_5240, F2_5260_5700, F7_5745_5825), + .chan11a_quarter = BM3(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), + }, - {APL1, FCC, NO_DFS, NO_PSCAN, NO_REQ, - BM(F4_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO, - BMZERO, - BMZERO}, + {.regDmnEnum = APL1, + .conformanceTestLimit = FCC, + .chan11a = BM1(F4_5745_5825), + }, - {APL2, FCC, NO_DFS, NO_PSCAN, NO_REQ, - BM(F1_5745_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO, - BMZERO, - BMZERO}, + {.regDmnEnum = APL2, + .conformanceTestLimit = FCC, + .chan11a = BM1(F1_5745_5805), + }, - {APL3, FCC, NO_DFS, NO_PSCAN, NO_REQ, - BM(F1_5280_5320, F2_5745_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO, - BMZERO, - BMZERO}, + {.regDmnEnum = APL3, + .conformanceTestLimit = FCC, + .chan11a = BM2(F1_5280_5320, F2_5745_5805), + }, - {APL4, FCC, NO_DFS, NO_PSCAN, NO_REQ, - BM(F4_5180_5240, F3_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO, - BMZERO, - BMZERO}, + {.regDmnEnum = APL4, + .conformanceTestLimit = FCC, + .chan11a = BM2(F4_5180_5240, F3_5745_5825), + }, - {APL5, FCC, NO_DFS, NO_PSCAN, NO_REQ, - BM(F2_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO, - BMZERO, - BMZERO}, + {.regDmnEnum = APL5, + .conformanceTestLimit = FCC, + .chan11a = BM1(F2_5745_5825), + }, - {APL6, ETSI, DFS_ETSI, PSCAN_FCC_T | PSCAN_FCC , NO_REQ, - BM(F4_5180_5240, F2_5260_5320, F3_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(T2_5210_5210, T1_5250_5290, T1_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO, - BMZERO}, + {.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), + }, - {APL8, ETSI, NO_DFS, NO_PSCAN, DISALLOW_ADHOC_11A|DISALLOW_ADHOC_11A_TURB, - BM(F6_5260_5320, F4_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO, - BMZERO, - BMZERO}, + {.regDmnEnum = APL8, + .conformanceTestLimit = ETSI, + .flags = DISALLOW_ADHOC_11A|DISALLOW_ADHOC_11A_TURB, + .chan11a = BM2(F6_5260_5320, F4_5745_5825), + }, - {APL9, ETSI, DFS_ETSI, PSCAN_ETSI, DISALLOW_ADHOC_11A|DISALLOW_ADHOC_11A_TURB, - BM(F1_5180_5320, F1_5500_5620, F3_5745_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO, - BMZERO, - BMZERO}, + {.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), + }, - {ETSI1, ETSI, DFS_ETSI, PSCAN_ETSI, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, - BM(W2_5180_5240, F2_5260_5320, F2_5500_5700, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO, - BMZERO, - BMZERO}, + {.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), + }, - {ETSI2, ETSI, DFS_ETSI, PSCAN_ETSI, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, - BM(F3_5180_5240, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO, - BMZERO, - BMZERO}, + {.regDmnEnum = ETSI2, + .conformanceTestLimit = ETSI, + .dfsMask = DFS_ETSI, + .pscan = PSCAN_ETSI, + .flags = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + .chan11a = BM1(F3_5180_5240), + }, - {ETSI3, ETSI, DFS_ETSI, PSCAN_ETSI, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, - BM(W2_5180_5240, F2_5260_5320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO, - BMZERO, - BMZERO}, + {.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), + }, - {ETSI4, ETSI, DFS_ETSI, PSCAN_ETSI, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, - BM(F3_5180_5240, F1_5260_5320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO, - BMZERO, - BMZERO}, + {.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), + }, - {ETSI5, ETSI, DFS_ETSI, PSCAN_ETSI, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, - BM(F1_5180_5240, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO, - BMZERO, - BMZERO}, + {.regDmnEnum = ETSI5, + .conformanceTestLimit = ETSI, + .dfsMask = DFS_ETSI, + .pscan = PSCAN_ETSI, + .flags = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + .chan11a = BM1(F1_5180_5240), + }, - {ETSI6, ETSI, DFS_ETSI, PSCAN_ETSI, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, - BM(F5_5180_5240, F1_5260_5280, F3_5500_5700, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO, - BMZERO, - BMZERO}, + {.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), + }, - {FCC1, FCC, NO_DFS, NO_PSCAN, NO_REQ, - BM(F2_5180_5240, F4_5260_5320, F5_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(T1_5210_5210, T2_5250_5290, T2_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(T1_5200_5240, T1_5280_5280, T1_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO}, + {.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), + }, - {FCC2, FCC, NO_DFS, NO_PSCAN, NO_REQ, - BM(F6_5180_5240, F5_5260_5320, F6_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(T2_5200_5240, T1_5280_5280, T1_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO}, + {.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), + }, - {FCC3, FCC, DFS_FCC3, PSCAN_FCC | PSCAN_FCC_T, NO_REQ, - BM(F2_5180_5240, F3_5260_5320, F1_5500_5700, F5_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1), - BM(T1_5210_5210, T1_5250_5250, T1_5290_5290, T2_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1), - BM(T1_5200_5240, T2_5280_5280, T1_5540_5660, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO}, + {.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), + }, - {FCC4, FCC, DFS_FCC3, PSCAN_FCC | PSCAN_FCC_T, NO_REQ, - BM(F1_4942_4987, F1_4945_4985, F1_4950_4980, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO, - BMZERO, - BMZERO}, + {.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), + }, - {MKK1, MKK, NO_DFS, PSCAN_MKK1, DISALLOW_ADHOC_11A_TURB, - BM(F1_5170_5230, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO, - BMZERO, - BMZERO}, + /* 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), + }, - {MKK2, MKK, NO_DFS, PSCAN_MKK2, DISALLOW_ADHOC_11A_TURB, - BM(F1_4915_4925, F1_4935_4945, F1_4920_4980, F1_5035_5040, F1_5055_5055, F1_5040_5080, F1_5170_5230, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO, - BMZERO, - BMZERO}, + {.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 */ - {MKK3, MKK, NO_DFS, PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB, - BM(F4_5180_5240, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO, - BMZERO, - BMZERO}, + {.regDmnEnum = MKK3, + .conformanceTestLimit = MKK, + .pscan = PSCAN_MKK3, + .flags = DISALLOW_ADHOC_11A_TURB, + .chan11a = BM1(F4_5180_5240), + }, /* UNI-1 even + UNI-2 */ - {MKK4, MKK, DFS_MKK4, PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB, - BM(F4_5180_5240, F2_5260_5320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO, - BMZERO, - BMZERO}, + {.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 */ - {MKK5, MKK, DFS_MKK4, PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB, - BM(F4_5180_5240, F2_5260_5320, F4_5500_5700, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO, - BMZERO, - BMZERO}, + {.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 */ - {MKK6, MKK, NO_DFS, PSCAN_MKK1, DISALLOW_ADHOC_11A_TURB, - BM(F2_5170_5230, F4_5180_5240, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO, - BMZERO, - BMZERO}, + {.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 */ - {MKK7, MKK, DFS_MKK4, PSCAN_MKK1 | PSCAN_MKK3 , DISALLOW_ADHOC_11A_TURB, - BM(F1_5170_5230, F4_5180_5240, F2_5260_5320, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO, - BMZERO, - BMZERO}, + {.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 */ - {MKK8, MKK, DFS_MKK4, PSCAN_MKK1 | PSCAN_MKK3 , DISALLOW_ADHOC_11A_TURB, - BM(F1_5170_5230, F4_5180_5240, F2_5260_5320, F4_5500_5700, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO, - BMZERO, - BMZERO}, + {.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 */ - {MKK9, MKK, NO_DFS, PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB, - BM(F1_4915_4925, F1_4935_4945, F1_4920_4980, F1_5035_5040, F1_5055_5055, F1_5040_5080, F4_5180_5240, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO, - BMZERO, - BMZERO}, + {.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 */ - {MKK10, MKK, DFS_MKK4, PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB, - BM(F1_4915_4925, F1_4935_4945, F1_4920_4980, F1_5035_5040, F1_5055_5055, F1_5040_5080, F4_5180_5240, F2_5260_5320, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO, - BMZERO, - BMZERO}, + {.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 */ - {APLD, NO_CTL, NO_DFS, NO_PSCAN, NO_REQ, - BMZERO, - BMZERO, - BMZERO, - BM(F2_2312_2372,F2_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(G2_2312_2372,G2_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO}, + {.regDmnEnum = APLD, + .conformanceTestLimit = NO_CTL, + .chan11b = BM2(F2_2312_2372,F2_2412_2472), + .chan11g = BM2(G2_2312_2372,G2_2412_2472), + }, - {ETSIA, NO_CTL, NO_DFS, PSCAN_ETSIA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, - BMZERO, - BMZERO, - BMZERO, - BM(F1_2457_2472,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(G1_2457_2472,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(T2_2437_2437,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, + {.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) + }, - {ETSIB, ETSI, NO_DFS, PSCAN_ETSIB, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, - BMZERO, - BMZERO, - BMZERO, - BM(F1_2432_2442,-1,-1,-1,-1,-1,-1,-1, -1, -1, -1, -1), - BM(G1_2432_2442,-1,-1,-1,-1,-1,-1,-1, -1, -1, -1, -1), - BM(T2_2437_2437,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, + {.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) + }, - {ETSIC, ETSI, NO_DFS, PSCAN_ETSIC, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, - BMZERO, - BMZERO, - BMZERO, - BM(F3_2412_2472,-1,-1,-1,-1,-1,-1,-1, -1, -1, -1, -1), - BM(G3_2412_2472,-1,-1,-1,-1,-1,-1,-1, -1, -1, -1, -1), - BM(T2_2437_2437,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, + {.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) + }, - {FCCA, FCC, NO_DFS, NO_PSCAN, NO_REQ, - BMZERO, - BMZERO, - BMZERO, - BM(F1_2412_2462,-1,-1,-1,-1,-1,-1,-1, -1, -1, -1, -1), - BM(G1_2412_2462,-1,-1,-1,-1,-1,-1,-1, -1, -1, -1, -1), - BM(T2_2437_2437,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, + {.regDmnEnum = FCCA, + .conformanceTestLimit = FCC, + .chan11b = BM1(F1_2412_2462), + .chan11g = BM1(G1_2412_2462), + .chan11g_turbo = BM1(T2_2437_2437), + }, - {MKKA, MKK, NO_DFS, PSCAN_MKKA | PSCAN_MKKA_G | PSCAN_MKKA1 | PSCAN_MKKA1_G | PSCAN_MKKA2 | PSCAN_MKKA2_G, DISALLOW_ADHOC_11A_TURB, - BMZERO, - BMZERO, - BMZERO, - BM(F2_2412_2462, F1_2467_2472, F2_2484_2484, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(G2_2412_2462, G1_2467_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(T2_2437_2437,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, + /* 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), + }, - {MKKC, MKK, NO_DFS, NO_PSCAN, NO_REQ, - BMZERO, - BMZERO, - BMZERO, - BM(F2_2412_2472,-1,-1,-1,-1,-1,-1,-1, -1, -1, -1, -1), - BM(G2_2412_2472,-1,-1,-1,-1,-1,-1,-1, -1, -1, -1, -1), - BM(T2_2437_2437,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, + {.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) + }, - {WORLD, ETSI, NO_DFS, NO_PSCAN, NO_REQ, - BMZERO, - BMZERO, - BMZERO, - BM(F2_2412_2472,-1,-1,-1,-1,-1,-1,-1, -1, -1, -1, -1), - BM(G2_2412_2472,-1,-1,-1,-1,-1,-1,-1, -1, -1, -1, -1), - BM(T2_2437_2437,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, + {.regDmnEnum = MKKC, + .conformanceTestLimit = MKK, + .chan11b = BM1(F2_2412_2472), + .chan11g = BM1(G2_2412_2472), + .chan11g_turbo = BM1(T2_2437_2437) + }, - {WOR0_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_PER_11D, - BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825, W1_5500_5700, -1, -1, -1, -1, -1, -1, -1), - BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BM(W1_2412_2412,W1_2437_2442,W1_2462_2462,W1_2472_2472,W1_2417_2432, W1_2447_2457, W1_2467_2467, W1_2484_2484, -1, -1, -1, -1), - BM(WG1_2412_2412,WG1_2437_2442,WG1_2462_2462,WG1_2472_2472,WG1_2417_2432,WG1_2447_2457,WG1_2467_2467, -1, -1, -1, -1, -1), - BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, + {.regDmnEnum = WORLD, + .conformanceTestLimit = ETSI, + .chan11b = BM1(F2_2412_2472), + .chan11g = BM1(G2_2412_2472), + .chan11g_turbo = BM1(T2_2437_2437) + }, - {WOR01_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_PER_11D, - BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825, W1_5500_5700, -1, -1, -1, -1, -1, -1, -1), - BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2417_2432, W1_2447_2457, -1, -1, -1, -1, -1, -1, -1), - BM(WG1_2412_2412, WG1_2437_2442, WG1_2462_2462, WG1_2417_2432, WG1_2447_2457, -1, -1, -1, -1, -1, -1, -1), - BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, + {.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) + }, - {WOR02_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_PER_11D, - BM(W1_5260_5320, W1_5180_5240,W1_5170_5230,W1_5745_5825,W1_5500_5700, -1, -1, -1, -1, -1, -1, -1), - BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BM(W1_2412_2412,W1_2437_2442,W1_2462_2462, W1_2472_2472,W1_2417_2432, W1_2447_2457, W1_2467_2467, -1, -1, -1, -1, -1), - BM(WG1_2412_2412,WG1_2437_2442,WG1_2462_2462, WG1_2472_2472,WG1_2417_2432, WG1_2447_2457, WG1_2467_2467, -1, -1, -1, -1, -1), - BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, + {.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)}, - {EU1_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_PER_11D, - BM(W1_5260_5320, W1_5180_5240,W1_5170_5230,W1_5745_5825,W1_5500_5700, -1, -1, -1, -1, -1, -1, -1), - BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BM(W1_2412_2412,W1_2437_2442,W1_2462_2462, W2_2472_2472,W1_2417_2432, W1_2447_2457, W2_2467_2467, -1, -1, -1, -1, -1), - BM(WG1_2412_2412,WG1_2437_2442,WG1_2462_2462, WG2_2472_2472,WG1_2417_2432, WG1_2447_2457, WG2_2467_2467, -1, -1, -1, -1, -1), - BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, + {.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)}, - {WOR1_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A, - BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825, W1_5500_5700, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BM(W1_2412_2412,W1_2437_2442,W1_2462_2462,W1_2472_2472,W1_2417_2432, W1_2447_2457, W1_2467_2467, W1_2484_2484, -1, -1, -1, -1), - BM(WG1_2412_2412,WG1_2437_2442,WG1_2462_2462,WG1_2472_2472,WG1_2417_2432,WG1_2447_2457,WG1_2467_2467, -1, -1, -1, -1, -1), - BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, + {.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)}, - {WOR2_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A, - BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825, W1_5500_5700, -1, -1, -1, -1, -1, -1, -1), - BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BM(W1_2412_2412,W1_2437_2442,W1_2462_2462,W1_2472_2472,W1_2417_2432, W1_2447_2457, W1_2467_2467, W1_2484_2484, -1, -1, -1, -1), - BM(WG1_2412_2412,WG1_2437_2442,WG1_2462_2462,WG1_2472_2472,WG1_2417_2432,WG1_2447_2457,WG1_2467_2467, -1, -1, -1, -1, -1), - BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, + {.regDmnEnum = WOR1_WORLD, + .conformanceTestLimit = NO_CTL, + .dfsMask = DFS_FCC3 | DFS_ETSI, + .pscan = PSCAN_WWR, + .flags = ADHOC_NO_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) + }, - {WOR3_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_PER_11D, - BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1), - BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BM(W1_2412_2412,W1_2437_2442,W1_2462_2462,W1_2472_2472,W1_2417_2432, W1_2447_2457, W1_2467_2467, -1, -1, -1, -1, -1), - BM(WG1_2412_2412,WG1_2437_2442,WG1_2462_2462,WG1_2472_2472,WG1_2417_2432,WG1_2447_2457,WG1_2467_2467,-1, -1, -1, -1, -1), - BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, + {.regDmnEnum = WOR2_WORLD, + .conformanceTestLimit = NO_CTL, + .dfsMask = DFS_FCC3 | DFS_ETSI, + .pscan = PSCAN_WWR, + .flags = ADHOC_NO_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)}, - {WOR4_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A, - BM(W2_5260_5320, W2_5180_5240, F2_5745_5805, W2_5825_5825, -1, -1, -1, -1, -1, -1, -1, -1), - BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BM(W1_2412_2412,W1_2437_2442,W1_2462_2462, W1_2417_2432,W1_2447_2457,-1, -1, -1, -1, -1, -1, -1), - BM(WG1_2412_2412,WG1_2437_2442,WG1_2462_2462, WG1_2417_2432,WG1_2447_2457,-1, -1, -1, -1, -1, -1, -1), - BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, + {.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)}, - {WOR5_ETSIC, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A, - BM(W1_5260_5320, W2_5180_5240, F6_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W2_2472_2472, W1_2417_2432, W1_2447_2457, W2_2467_2467, -1, -1, -1, -1, -1), - BM(WG1_2412_2412, WG1_2437_2442, WG1_2462_2462, WG2_2472_2472, WG1_2417_2432, WG1_2447_2457, WG2_2467_2467, -1, -1, -1, -1, -1), - BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, + {.regDmnEnum = WOR4_WORLD, + .conformanceTestLimit = NO_CTL, + .dfsMask = DFS_FCC3 | DFS_ETSI, + .pscan = PSCAN_WWR, + .flags = ADHOC_NO_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)}, - {WOR9_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A, - BM(W1_5260_5320, W1_5180_5240, W1_5745_5825, W1_5500_5700, -1, -1, -1, -1, -1, -1, -1, -1), - BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2417_2432, W1_2447_2457, -1, -1, -1, -1, -1, -1, -1), - BM(WG1_2412_2412, WG1_2437_2442, WG1_2462_2462, WG1_2417_2432, WG1_2447_2457, -1, -1, -1, -1, -1, -1, -1), - BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, + {.regDmnEnum = WOR5_ETSIC, + .conformanceTestLimit = NO_CTL, + .dfsMask = DFS_FCC3 | DFS_ETSI, + .pscan = PSCAN_WWR, + .flags = ADHOC_NO_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)}, - {WORA_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A, - BM(W1_5260_5320, W1_5180_5240, W1_5745_5825, W1_5500_5700, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472, W1_2417_2432, W1_2447_2457, W1_2467_2467, -1, -1, -1, -1, -1), - BM(WG1_2412_2412, WG1_2437_2442, WG1_2462_2462, WG1_2472_2472, WG1_2417_2432, WG1_2447_2457, WG1_2467_2467, -1, -1, -1, -1, -1), - BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, + {.regDmnEnum = WOR9_WORLD, + .conformanceTestLimit = NO_CTL, + .dfsMask = DFS_FCC3 | DFS_ETSI, + .pscan = PSCAN_WWR, + .flags = ADHOC_NO_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)}, - {NULL1, NO_CTL, NO_DFS, NO_PSCAN, NO_REQ, - BMZERO, - BMZERO, - BMZERO, - BMZERO, - BMZERO, - BMZERO} + {.regDmnEnum = WORA_WORLD, + .conformanceTestLimit = NO_CTL, + .dfsMask = DFS_FCC3 | DFS_ETSI, + .pscan = PSCAN_WWR, + .flags = ADHOC_NO_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 = SR9_WORLD, + .conformanceTestLimit = NO_CTL, + .pscan = PSCAN_FCC | PSCAN_FCC_T, + .chan11g = BM1(S1_912_917), + .chan11g_half = BM1(S1_907_922_10), + .chan11g_quarter = BM1(S1_907_922_5), + }, + + {.regDmnEnum = XR9_WORLD, + .conformanceTestLimit = NO_CTL, + .pscan = PSCAN_FCC | PSCAN_FCC_T, + .chan11g = BM1(S2_912_917), + .chan11g_half = BM1(S2_907_922_10), + .chan11g_quarter = BM1(S2_907_922_5), + }, + + {.regDmnEnum = GZ901_WORLD, + .conformanceTestLimit = NO_CTL, + .pscan = PSCAN_FCC | PSCAN_FCC_T, + .chan11g = BM1(S1_913_918), + .chan11g_half = BM1(S1_913_918_10), + .chan11g_quarter = BM1(S1_908_923_5), + }, + + {.regDmnEnum = NULL1, + .conformanceTestLimit = NO_CTL, + } }; struct cmode { @@ -1638,12 +1907,16 @@ struct cmode { }; static const struct cmode modes[] = { - { HAL_MODE_TURBO, CHANNEL_ST}, /* TURBO means 11a Static Turbo */ + { HAL_MODE_TURBO, CHANNEL_ST}, /* NB: 11a Static Turbo */ { HAL_MODE_11A, CHANNEL_A}, { HAL_MODE_11B, CHANNEL_B}, { HAL_MODE_11G, CHANNEL_G}, { HAL_MODE_11G_TURBO, CHANNEL_108G}, { HAL_MODE_11A_TURBO, CHANNEL_108A}, + { HAL_MODE_11A_QUARTER_RATE, CHANNEL_A | CHANNEL_QUARTER}, + { HAL_MODE_11A_HALF_RATE, CHANNEL_A | CHANNEL_HALF}, + { HAL_MODE_11G_QUARTER_RATE, CHANNEL_G | CHANNEL_QUARTER}, + { HAL_MODE_11G_HALF_RATE, CHANNEL_G | CHANNEL_HALF}, { HAL_MODE_11NG_HT20, CHANNEL_G_HT20}, { HAL_MODE_11NG_HT40PLUS, CHANNEL_G_HT40PLUS}, { HAL_MODE_11NG_HT40MINUS, CHANNEL_G_HT40MINUS}, @@ -1681,7 +1954,7 @@ getEepromRD(struct ath_hal *ah) * Test to see if the bitmask array is all zeros */ static HAL_BOOL -isChanBitMaskZero(uint64_t *bitmask) +isChanBitMaskZero(const uint64_t *bitmask) { #if BMLEN > 2 #error "add more cases" @@ -1773,9 +2046,15 @@ isCountryCodeValid(struct ath_hal *ah, HAL_CTRY_CODE cc) * capabilities and the specified country code and reg domain. */ static u_int -ath_hal_getwmodesnreg(struct ath_hal *ah, COUNTRY_CODE_TO_ENUM_RD *country, - REG_DOMAIN *rd5GHz) +ath_hal_getwmodesnreg(struct ath_hal *ah, + const COUNTRY_CODE_TO_ENUM_RD *country, const REG_DOMAIN *rd5GHz) { +#define HAL_MODE_11G_ALL \ + (HAL_MODE_11G | HAL_MODE_11G_TURBO | HAL_MODE_11G_QUARTER_RATE | \ + HAL_MODE_11G_HALF_RATE) +#define HAL_MODE_11A_ALL \ + (HAL_MODE_11A | HAL_MODE_11A_TURBO | HAL_MODE_TURBO | \ + HAL_MODE_11A_QUARTER_RATE | HAL_MODE_11A_HALF_RATE) u_int modesAvail; /* Get modes that HW is capable of */ @@ -1786,7 +2065,18 @@ ath_hal_getwmodesnreg(struct ath_hal *ah, COUNTRY_CODE_TO_ENUM_RD *country, __func__, modesAvail, country->countryCode, country->regDmnEnum); /* Check country regulations for allowed modes */ - if ((modesAvail & (HAL_MODE_11A_TURBO|HAL_MODE_TURBO)) && + if (!country->allow11g && (modesAvail & HAL_MODE_11G_ALL)) { + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "%s: disallow all 11g\n", __func__); + modesAvail &= ~HAL_MODE_11G_ALL; + } + if (isChanBitMaskZero(rd5GHz->chan11a) && + (modesAvail & HAL_MODE_11A_ALL)) { + HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + "%s: disallow all 11a\n", __func__); + modesAvail &= ~HAL_MODE_11A_ALL; + } + if ((modesAvail & (HAL_MODE_11A_TURBO | HAL_MODE_TURBO)) && !country->allow11aTurbo) { HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s: disallow 11aTurbo\n", __func__); @@ -1797,17 +2087,8 @@ ath_hal_getwmodesnreg(struct ath_hal *ah, COUNTRY_CODE_TO_ENUM_RD *country, "%s: disallow 11gTurbo\n", __func__); modesAvail &= ~HAL_MODE_11G_TURBO; } - if ((modesAvail & HAL_MODE_11G) && !country->allow11g) { - HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, - "%s: disallow 11g\n", __func__); - modesAvail &= ~HAL_MODE_11G; - } - if ((modesAvail & HAL_MODE_11A) && isChanBitMaskZero(rd5GHz->chan11a)) { - HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, - "%s: disallow 11a\n", __func__); - modesAvail &= ~HAL_MODE_11A; - } + /* Check 11n operation */ if ((modesAvail & HAL_MODE_11NG_HT20) && !country->allow11ng20) { HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s: disallow 11g HT20\n", __func__); @@ -1840,6 +2121,8 @@ ath_hal_getwmodesnreg(struct ath_hal *ah, COUNTRY_CODE_TO_ENUM_RD *country, } return modesAvail; +#undef HAL_MODE_11A_ALL +#undef HAL_MODE_11G_ALL } /* @@ -1883,6 +2166,32 @@ ath_hal_ispublicsafetysku(struct ath_hal *ah) return AH_FALSE; } +/* + * Return if device is actually operating in 900 MHz band. + */ +HAL_BOOL +ath_hal_isgsmsku(struct ath_hal *ah) +{ + uint16_t rd = getEepromRD(ah); + + switch (rd) { + case SR9_WORLD: + case XR9_WORLD: + case GZ901_WORLD: + case CTRY_SR9 | COUNTRY_ERD_FLAG: + case CTRY_XR9 | COUNTRY_ERD_FLAG: + case CTRY_GZ901 | COUNTRY_ERD_FLAG: + return AH_TRUE; + case DEBUG_REG_DMN: + case NO_ENUMRD: + return AH_PRIVATE(ah)->ah_countryCode == CTRY_SR9 + || AH_PRIVATE(ah)->ah_countryCode == CTRY_XR9 + || AH_PRIVATE(ah)->ah_countryCode == CTRY_GZ901 + ; + } + return AH_FALSE; +} + /* * Find the pointer to the country element in the country table * corresponding to the country code @@ -2089,7 +2398,6 @@ ath_hal_init_channels(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *ichans = &AH_PRIVATE(ah)->ah_channels[0]; int next, b; uint8_t ctl; - int is_quarterchan_cap, is_halfchan_cap; HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s: cc %u mode 0x%x%s%s\n", __func__, cc, modeSelect, enableOutdoor? " Enable outdoor" : " ", @@ -2152,8 +2460,6 @@ ath_hal_init_channels(struct ath_hal *ah, modesAvail = ath_hal_getwmodesnreg(ah, country, &rd5GHz); maxChan = !enableOutdoor ? country->outdoorChanStart : 7000; - is_halfchan_cap = AH_PRIVATE(ah)->ah_caps.halChanHalfRate; - is_quarterchan_cap = AH_PRIVATE(ah)->ah_caps.halChanQuarterRate; if (maxchans > N(AH_PRIVATE(ah)->ah_channels)) maxchans = N(AH_PRIVATE(ah)->ah_channels); @@ -2192,11 +2498,18 @@ ath_hal_init_channels(struct ath_hal *ah, ctl = rd->conformanceTestLimit | CTL_TURBO; break; case HAL_MODE_11A: + case HAL_MODE_11A_HALF_RATE: + case HAL_MODE_11A_QUARTER_RATE: case HAL_MODE_11NA_HT20: case HAL_MODE_11NA_HT40PLUS: case HAL_MODE_11NA_HT40MINUS: rd = &rd5GHz; - channelBM = rd->chan11a; + if (cm->mode == HAL_MODE_11A_HALF_RATE) + channelBM = rd->chan11a_half; + else if (cm->mode == HAL_MODE_11A_QUARTER_RATE) + channelBM = rd->chan11a_quarter; + else + channelBM = rd->chan11a; freqs = ®Dmn5GhzFreq[0]; ctl = rd->conformanceTestLimit; break; @@ -2207,11 +2520,18 @@ ath_hal_init_channels(struct ath_hal *ah, ctl = rd->conformanceTestLimit | CTL_11B; break; case HAL_MODE_11G: + case HAL_MODE_11G_HALF_RATE: + case HAL_MODE_11G_QUARTER_RATE: case HAL_MODE_11NG_HT20: case HAL_MODE_11NG_HT40PLUS: case HAL_MODE_11NG_HT40MINUS: rd = &rd2GHz; - channelBM = rd->chan11g; + if (cm->mode == HAL_MODE_11G_HALF_RATE) + channelBM = rd->chan11g_half; + else if (cm->mode == HAL_MODE_11G_QUARTER_RATE) + channelBM = rd->chan11g_quarter; + else + channelBM = rd->chan11g; freqs = ®Dmn2Ghz11gFreq[0]; ctl = rd->conformanceTestLimit | CTL_11G; break; @@ -2265,22 +2585,6 @@ ath_hal_init_channels(struct ath_hal *ah, __func__, c, c_lo, c_hi); continue; } - if ((fband->channelBW == CHANNEL_HALF_BW) && - !is_halfchan_cap) { - HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, - "%s: Skipping %u half rate channel\n", - __func__, c); - continue; - } - - if ((fband->channelBW == CHANNEL_QUARTER_BW) && - !is_quarterchan_cap) { - HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, - "%s: Skipping %u quarter rate channel\n", - __func__, c); - continue; - } - if (((c+fband->channelSep)/2) > (maxChan+HALF_MAXCHANBW)) { HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s: c %u > maxChan %u\n", @@ -2317,15 +2621,6 @@ ath_hal_init_channels(struct ath_hal *ah, OS_MEMZERO(&icv, sizeof(icv)); icv.channel = c; icv.channelFlags = cm->flags; - switch (fband->channelBW) { - case CHANNEL_HALF_BW: - icv.channelFlags |= CHANNEL_HALF; - break; - case CHANNEL_QUARTER_BW: - icv.channelFlags |= CHANNEL_QUARTER; - break; - } - icv.maxRegTxPower = fband->powerDfs; icv.antennaMax = fband->antennaMax; icv.regDmnFlags = rd->flags; @@ -2411,10 +2706,6 @@ ath_hal_checkchannel(struct ath_hal *ah, const HAL_CHANNEL *c) int flags = c->channelFlags & CHAN_FLAGS; int n, lim, d; - HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, - "%s: channel %u/0x%x (0x%x) requested\n", - __func__, c->channel, c->channelFlags, flags); - /* * Check current channel to avoid the lookup. */ @@ -2445,8 +2736,6 @@ ath_hal_checkchannel(struct ath_hal *ah, const HAL_CHANNEL *c) } d = flags - (cc->channelFlags & CHAN_FLAGS); } - HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s: channel %u/0x%x d %d\n", - __func__, cc->channel, cc->channelFlags, d); if (d > 0) { base = cc + 1; lim--; diff --git a/ar5210/ar5210.h b/ar5210/ar5210.h index 8f1c3b12863d..d857998e76fb 100644 --- a/ar5210/ar5210.h +++ b/ar5210/ar5210.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: ar5210.h,v 1.6 2008/11/10 04:08:02 sam Exp $ + * $Id: ar5210.h,v 1.8 2008/11/11 02:40:13 sam Exp $ */ #ifndef _ATH_AR5210_H_ #define _ATH_AR5210_H_ @@ -90,67 +90,7 @@ #define INIT_PROTO_TIME_CNTRL_TURBO ( (INIT_CARR_SENSE_EN << 26) | (INIT_EIFS_TURBO << 12) | \ (INIT_ProgIFS_TURBO) ) -/* - * EEPROM defines for Version 1 Crete EEPROM. - * - * The EEPROM is segmented into three sections: - * - * PCI/Cardbus default configuration settings - * Cardbus CIS tuples and vendor-specific data - * Atheros-specific data - * - * EEPROM entries are read 32-bits at a time through the PCI bus - * interface but are all 16-bit values. - * - * Access to the Atheros-specific data is controlled by protection - * bits and the data is checksum'd. The driver reads the Atheros - * data from the EEPROM at attach and caches it in its private state. - * This data includes the local regulatory domain, channel calibration - * settings, and phy-related configuration settings. - */ -#define AR_EEPROM_MAC(i) (0x1f-(i))/* MAC address word */ -#define AR_EEPROM_MAGIC 0x3d /* magic number */ -#define AR_EEPROM_PROTECT 0x3f /* Atheros segment protect register */ -#define AR_EEPROM_PROTOTECT_WP_128_191 0x80 -#define AR_EEPROM_REG_DOMAIN 0xbf /* Current regulatory domain register */ -#define AR_EEPROM_ATHEROS_BASE 0xc0 /* Base of Atheros-specific data */ -#define AR_EEPROM_ATHEROS_MAX 64 /* 64x2=128 bytes of EEPROM settings */ -#define AR_EEPROM_ATHEROS(n) (AR_EEPROM_ATHEROS_BASE+(n)) -#define AR_EEPROM_VERSION AR_EEPROM_ATHEROS(1) -#define AR_EEPROM_ATHEROS_TP_SETTINGS 0x09 /* Transmit power settings */ -#define AR_REG_DOMAINS_MAX 4 /* # of Regulatory Domains */ -#define AR_CHANNELS_MAX 5 /* # of Channel calibration groups */ -#define AR_TP_SETTINGS_SIZE 11 /* # locations/Channel group */ -#define AR_TP_SCALING_ENTRIES 11 /* # entries in transmit power dBm->pcdac */ - -/* - * NB: we store the rfsilent select+polarity data packed - * with the encoding used in later parts so values - * returned to applications are consistent. - */ -#define AR_EEPROM_RFSILENT_GPIO_SEL 0x001c -#define AR_EEPROM_RFSILENT_GPIO_SEL_S 2 -#define AR_EEPROM_RFSILENT_POLARITY 0x0002 -#define AR_EEPROM_RFSILENT_POLARITY_S 1 - -#define AR_I2DBM(x) ((uint8_t)((x * 2) + 3)) - -/* - * Transmit power and channel calibration settings. - */ -struct tpcMap { - uint8_t pcdac[AR_TP_SCALING_ENTRIES]; - uint8_t gainF[AR_TP_SCALING_ENTRIES]; - uint8_t rate36; - uint8_t rate48; - uint8_t rate54; - uint8_t regdmn[AR_REG_DOMAINS_MAX]; -}; - -/* NB: this is in ah_eeprom.h which isn't used for 5210 support */ -#ifndef MAX_RATE_POWER -#define MAX_RATE_POWER 60 -#endif +#define AR5210_MAX_RATE_POWER 60 #undef HAL_NUM_TX_QUEUES /* from ah.h */ #define HAL_NUM_TX_QUEUES 3 @@ -158,22 +98,6 @@ struct tpcMap { struct ath_hal_5210 { struct ath_hal_private ah_priv; /* base definitions */ - /* - * Information retrieved from EEPROM - */ - uint16_t ah_eeversion; /* EEPROM Version field */ - uint16_t ah_eeprotect; /* EEPROM protection settings */ - uint16_t ah_antenna; /* Antenna Settings */ - uint16_t ah_biasCurrents; /* OB, DB */ - uint8_t ah_thresh62; /* thresh62 */ - uint8_t ah_xlnaOn; /* External LNA timing */ - uint8_t ah_xpaOff; /* Extern output stage timing */ - uint8_t ah_xpaOn; /* Extern output stage timing */ - uint8_t ah_rfKill; /* Single low bit signalling if RF Kill is implemented */ - uint8_t ah_devType; /* Type: PCI, miniPCI, CB */ - uint8_t ah_regDomain[AR_REG_DOMAINS_MAX]; - /* calibrated reg domains */ - struct tpcMap ah_tpc[AR_CHANNELS_MAX]; uint8_t ah_macaddr[IEEE80211_ADDR_LEN]; /* * Runtime state. @@ -213,6 +137,9 @@ extern HAL_BOOL ar5210PhyDisable(struct ath_hal *); extern HAL_BOOL ar5210Disable(struct ath_hal *); extern HAL_BOOL ar5210ChipReset(struct ath_hal *, HAL_CHANNEL *); extern HAL_BOOL ar5210PerCalibration(struct ath_hal *, HAL_CHANNEL *, HAL_BOOL *); +extern HAL_BOOL ar5210PerCalibrationN(struct ath_hal *ah, HAL_CHANNEL *chan, + u_int chainMask, HAL_BOOL longCal, HAL_BOOL *isCalDone); +extern HAL_BOOL ar5210ResetCalValid(struct ath_hal *ah, HAL_CHANNEL *chan); extern int16_t ar5210GetNoiseFloor(struct ath_hal *); extern int16_t ar5210GetNfAdjust(struct ath_hal *, const HAL_CHANNEL_INTERNAL *); diff --git a/ar5210/ar5210_attach.c b/ar5210/ar5210_attach.c index 53119084a51b..37fa425e8fdf 100644 --- a/ar5210/ar5210_attach.c +++ b/ar5210/ar5210_attach.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_attach.c,v 1.7 2008/11/10 04:08:02 sam Exp $ + * $Id: ar5210_attach.c,v 1.9 2008/11/11 02:40:13 sam Exp $ */ #include "opt_ah.h" @@ -27,6 +27,8 @@ #include "ar5210/ar5210reg.h" #include "ar5210/ar5210phy.h" +#include "ah_eeprom_v1.h" + static HAL_BOOL ar5210GetChannelEdges(struct ath_hal *, uint16_t flags, uint16_t *low, uint16_t *high); static HAL_BOOL ar5210GetChipPowerLimits(struct ath_hal *ah, @@ -46,6 +48,8 @@ static const struct ath_hal_private ar5210hal = {{ .ah_disable = ar5210Disable, .ah_setPCUConfig = ar5210SetPCUConfig, .ah_perCalibration = ar5210PerCalibration, + .ah_perCalibrationN = ar5210PerCalibrationN, + .ah_resetCalValid = ar5210ResetCalValid, .ah_setTxPowerLimit = ar5210SetTxPowerLimit, .ah_getChanNoise = ath_hal_getChanNoise, @@ -93,6 +97,7 @@ static const struct ath_hal_private ar5210hal = {{ .ah_setMacAddress = ar5210SetMacAddress, .ah_getBssIdMask = ar5210GetBssIdMask, .ah_setBssIdMask = ar5210SetBssIdMask, + .ah_setRegulatoryDomain = ar5210SetRegulatoryDomain, .ah_setLedState = ar5210SetLedState, .ah_writeAssocid = ar5210WriteAssocid, .ah_gpioCfgInput = ar5210GpioCfgInput, @@ -171,10 +176,10 @@ ar5210Attach(uint16_t devid, HAL_SOFTC sc, HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HA #define N(a) (sizeof(a)/sizeof(a[0])) struct ath_hal_5210 *ahp; struct ath_hal *ah; - u_int i, loc; - uint32_t revid, pcicfg, sum; - uint16_t athvals[AR_EEPROM_ATHEROS_MAX], eeval; + uint32_t revid, pcicfg; + uint16_t eeval; HAL_STATUS ecode; + int i; HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: devid 0x%x sc %p st %p sh %p\n", __func__, devid, @@ -199,7 +204,7 @@ ar5210Attach(uint16_t devid, HAL_SOFTC sc, HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HA AH_PRIVATE(ah)->ah_devid = devid; AH_PRIVATE(ah)->ah_subvendorid = 0; /* XXX */ - AH_PRIVATE(ah)->ah_powerLimit = MAX_RATE_POWER; + AH_PRIVATE(ah)->ah_powerLimit = AR5210_MAX_RATE_POWER; AH_PRIVATE(ah)->ah_tpScale = HAL_TP_SCALE_MAX; /* no scaling */ ahp->ah_powerMode = HAL_PM_UNDEFINED; @@ -234,169 +239,40 @@ ar5210Attach(uint16_t devid, HAL_SOFTC sc, HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HA /* * Read all the settings from the EEPROM and stash - * ones we'll use later in our state block. + * ones we'll use later. */ pcicfg = OS_REG_READ(ah, AR_PCICFG); OS_REG_WRITE(ah, AR_PCICFG, pcicfg | AR_PCICFG_EEPROMSEL); - - if (!ar5210EepromRead(ah, AR_EEPROM_MAGIC, &eeval)) { - HALDEBUG(ah, HAL_DEBUG_ANY, - "%s: cannot read EEPROM magic number\n", __func__); - ecode = HAL_EEREAD; + ecode = ath_hal_v1EepromAttach(ah); + if (ecode != HAL_OK) { goto eebad; } - if (eeval != 0x5aa5) { + ecode = ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, &eeval); + if (ecode != HAL_OK) { HALDEBUG(ah, HAL_DEBUG_ANY, - "%s: invalid EEPROM magic number 0x%x\n", __func__, eeval); - ecode = HAL_EEMAGIC; - goto eebad; - } - - if (!ar5210EepromRead(ah, AR_EEPROM_PROTECT, &eeval)) { - HALDEBUG(ah, HAL_DEBUG_ANY, - "%s: cannot read EEPROM protection bits; read locked?\n", + "%s: cannot read regulatory domain from EEPROM\n", __func__); - ecode = HAL_EEREAD; goto eebad; - } - HALDEBUG(ah, HAL_DEBUG_ATTACH, "EEPROM protect 0x%x\n", eeval); - ahp->ah_eeprotect = eeval; - /* XXX check proper access before continuing */ - - if (!ar5210EepromRead(ah, AR_EEPROM_VERSION, &eeval)) { + } + AH_PRIVATE(ah)->ah_currentRD = eeval; + ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr); + if (ecode != HAL_OK) { HALDEBUG(ah, HAL_DEBUG_ANY, - "%s: unable to read EEPROM version\n", __func__); - ecode = HAL_EEREAD; + "%s: error getting mac address from EEPROM\n", __func__); goto eebad; - } - ahp->ah_eeversion = (eeval>>12) & 0xf; - if (ahp->ah_eeversion != 1) { - /* - * This driver only groks the version 1 EEPROM layout. - */ - HALDEBUG(ah, HAL_DEBUG_ANY, - "%s: unsupported EEPROM version %u (0x%x) found\n", - __func__, ahp->ah_eeversion, eeval); - ecode = HAL_EEVERSION; - goto eebad; - } + } + OS_REG_WRITE(ah, AR_PCICFG, pcicfg); /* disable EEPROM access */ - /* - * Read the Atheros EEPROM entries and calculate the checksum. - */ - sum = 0; - for (i = 0; i < AR_EEPROM_ATHEROS_MAX; i++) { - if (!ar5210EepromRead(ah, AR_EEPROM_ATHEROS(i), &athvals[i])) { - ecode = HAL_EEREAD; - goto eebad; - } - sum ^= athvals[i]; - } - if (sum != 0xffff) { - HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad EEPROM checksum 0x%x\n", - __func__, sum); - ecode = HAL_EEBADSUM; - goto eebad; - } - - /* - * Valid checksum, fetch the regulatory domain and save values. - */ - if (!ar5210EepromRead(ah, AR_EEPROM_REG_DOMAIN, &eeval)) { - HALDEBUG(ah, HAL_DEBUG_ANY, - "%s: cannot read regdomain from EEPROM\n", __func__); - ecode = HAL_EEREAD; - goto eebad; - } - - AH_PRIVATE(ah)->ah_currentRD = eeval & 0xff; - ahp->ah_antenna = athvals[2]; - ahp->ah_biasCurrents = athvals[3]; - ahp->ah_thresh62 = athvals[4] & 0xff; - ahp->ah_xlnaOn = (athvals[4] >> 8) & 0xff; - ahp->ah_xpaOn = athvals[5] & 0xff; - ahp->ah_xpaOff = (athvals[5] >> 8) & 0xff; - ahp->ah_regDomain[0] = (athvals[6] >> 8) & 0xff; - ahp->ah_regDomain[1] = athvals[6] & 0xff; - ahp->ah_regDomain[2] = (athvals[7] >> 8) & 0xff; - ahp->ah_regDomain[3] = athvals[7] & 0xff; - ahp->ah_rfKill = athvals[8] & 0x1; - ahp->ah_devType = (athvals[8] >> 1) & 0x7; AH_PRIVATE(ah)->ah_getNfAdjust = ar5210GetNfAdjust; - for (i = 0, loc = AR_EEPROM_ATHEROS_TP_SETTINGS; i < AR_CHANNELS_MAX; i++, loc += AR_TP_SETTINGS_SIZE) { - struct tpcMap *chan = &ahp->ah_tpc[i]; - - /* Copy pcdac and gain_f values from EEPROM */ - chan->pcdac[0] = (athvals[loc] >> 10) & 0x3F; - chan->gainF[0] = (athvals[loc] >> 4) & 0x3F; - chan->pcdac[1] = ((athvals[loc] << 2) & 0x3C) - | ((athvals[loc+1] >> 14) & 0x03); - chan->gainF[1] = (athvals[loc+1] >> 8) & 0x3F; - chan->pcdac[2] = (athvals[loc+1] >> 2) & 0x3F; - chan->gainF[2] = ((athvals[loc+1] << 4) & 0x30) - | ((athvals[loc+2] >> 12) & 0x0F); - chan->pcdac[3] = (athvals[loc+2] >> 6) & 0x3F; - chan->gainF[3] = athvals[loc+2] & 0x3F; - chan->pcdac[4] = (athvals[loc+3] >> 10) & 0x3F; - chan->gainF[4] = (athvals[loc+3] >> 4) & 0x3F; - chan->pcdac[5] = ((athvals[loc+3] << 2) & 0x3C) - | ((athvals[loc+4] >> 14) & 0x03); - chan->gainF[5] = (athvals[loc+4] >> 8) & 0x3F; - chan->pcdac[6] = (athvals[loc+4] >> 2) & 0x3F; - chan->gainF[6] = ((athvals[loc+4] << 4) & 0x30) - | ((athvals[loc+5] >> 12) & 0x0F); - chan->pcdac[7] = (athvals[loc+5] >> 6) & 0x3F; - chan->gainF[7] = athvals[loc+5] & 0x3F; - chan->pcdac[8] = (athvals[loc+6] >> 10) & 0x3F; - chan->gainF[8] = (athvals[loc+6] >> 4) & 0x3F; - chan->pcdac[9] = ((athvals[loc+6] << 2) & 0x3C) - | ((athvals[loc+7] >> 14) & 0x03); - chan->gainF[9] = (athvals[loc+7] >> 8) & 0x3F; - chan->pcdac[10] = (athvals[loc+7] >> 2) & 0x3F; - chan->gainF[10] = ((athvals[loc+7] << 4) & 0x30) - | ((athvals[loc+8] >> 12) & 0x0F); - - /* Copy Regulatory Domain and Rate Information from EEPROM */ - chan->rate36 = (athvals[loc+8] >> 6) & 0x3F; - chan->rate48 = athvals[loc+8] & 0x3F; - chan->rate54 = (athvals[loc+9] >> 10) & 0x3F; - chan->regdmn[0] = (athvals[loc+9] >> 4) & 0x3F; - chan->regdmn[1] = ((athvals[loc+9] << 2) & 0x3C) - | ((athvals[loc+10] >> 14) & 0x03); - chan->regdmn[2] = (athvals[loc+10] >> 8) & 0x3F; - chan->regdmn[3] = (athvals[loc+10] >> 2) & 0x3F; - } /* * Got everything we need now to setup the capabilities. */ (void) ar5210FillCapabilityInfo(ah); - sum = 0; - for (i = 0; i < 3; i++) { - if (!ar5210EepromRead(ah, AR_EEPROM_MAC(i), &eeval)) { - HALDEBUG(ah, HAL_DEBUG_ANY, - "%s: cannot read EEPROM location %u\n", __func__, i); - ecode = HAL_EEREAD; - goto bad; - } - sum += eeval; - ahp->ah_macaddr[2*i + 0] = eeval >> 8; - ahp->ah_macaddr[2*i + 1] = eeval & 0xff; - } - if (sum == 0 || sum == 0xffff*3) { - HALDEBUG(ah, HAL_DEBUG_ANY, "%s: mac address read failed: %s\n", - __func__, ath_hal_ether_sprintf(ahp->ah_macaddr)); - ecode = HAL_EEBADMAC; - goto eebad; - } - - OS_REG_WRITE(ah, AR_PCICFG, pcicfg); /* disable EEPROM access */ - HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__); return ah; - eebad: OS_REG_WRITE(ah, AR_PCICFG, pcicfg); /* disable EEPROM access */ bad: @@ -416,6 +292,7 @@ ar5210Detach(struct ath_hal *ah) HALASSERT(ah != AH_NULL); HALASSERT(ah->ah_magic == AR5210_MAGIC); + ath_hal_eepromDetach(ah); ath_hal_free(ah); } @@ -447,7 +324,7 @@ ar5210GetChipPowerLimits(struct ath_hal *ah, HAL_CHANNEL *chans, uint32_t nchans HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: no min/max power for %u/0x%x\n", __func__, chan->channel, chan->channelFlags); - chan->maxTxPower = MAX_RATE_POWER; + chan->maxTxPower = AR5210_MAX_RATE_POWER; chan->minTxPower = 0; } return AH_TRUE; @@ -477,7 +354,7 @@ ar5210FillCapabilityInfo(struct ath_hal *ah) pCap->halChanHalfRate = AH_FALSE; pCap->halChanQuarterRate = AH_FALSE; - if (AH5210(ah)->ah_rfKill) { + if (ath_hal_eepromGetFlag(ah, AR_EEP_RFKILL)) { /* * Setup initial rfsilent settings based on the EEPROM * contents. Pin 0, polarity 0 is fixed; record this diff --git a/ar5210/ar5210_misc.c b/ar5210/ar5210_misc.c index 03f118e1ad48..710c03a4999c 100644 --- a/ar5210/ar5210_misc.c +++ b/ar5210/ar5210_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: ar5210_misc.c,v 1.4 2008/11/10 04:08:02 sam Exp $ + * $Id: ar5210_misc.c,v 1.6 2008/11/27 22:29:37 sam Exp $ */ #include "opt_ah.h" @@ -27,6 +27,8 @@ #include "ar5210/ar5210reg.h" #include "ar5210/ar5210phy.h" +#include "ah_eeprom_v1.h" + #define AR_NUM_GPIO 6 /* 6 GPIO bits */ #define AR_GPIOD_MASK 0x2f /* 6-bit mask */ @@ -78,6 +80,46 @@ ar5210EepromRead(struct ath_hal *ah, u_int off, uint16_t *data) return AH_TRUE; } +#ifdef AH_SUPPORT_WRITE_EEPROM +/* + * Write 16 bits of data to the specified EEPROM offset. + */ +HAL_BOOL +ar5210EepromWrite(struct ath_hal *ah, u_int off, uint16_t data) +{ + return AH_FALSE; +} +#endif /* AH_SUPPORT_WRITE_EEPROM */ + +/* + * Attempt to change the cards operating regulatory domain to the given value + */ +HAL_BOOL +ar5210SetRegulatoryDomain(struct ath_hal *ah, + uint16_t regDomain, HAL_STATUS *status) +{ + HAL_STATUS ecode; + + if (AH_PRIVATE(ah)->ah_currentRD == regDomain) { + ecode = HAL_EINVAL; + goto bad; + } + /* + * Check if EEPROM is configured to allow this; must + * be a proper version and the protection bits must + * permit re-writing that segment of the EEPROM. + */ + if (ath_hal_eepromGetFlag(ah, AR_EEP_WRITEPROTECT)) { + ecode = HAL_EEWRITE; + goto bad; + } + ecode = HAL_EIO; /* disallow all writes */ +bad: + if (status) + *status = ecode; + return AH_FALSE; +} + /* * Return the wireless modes (a,b,g,t) supported by hardware. * @@ -302,11 +344,10 @@ ar5210GetTsf64(struct ath_hal *ah) * 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. + * 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++; } diff --git a/ar5210/ar5210_reset.c b/ar5210/ar5210_reset.c index 26a98a834f39..363c813c18ec 100644 --- a/ar5210/ar5210_reset.c +++ b/ar5210/ar5210_reset.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_reset.c,v 1.5 2008/11/10 04:08:02 sam Exp $ + * $Id: ar5210_reset.c,v 1.8 2008/11/11 17:25:16 sam Exp $ */ #include "opt_ah.h" @@ -27,6 +27,8 @@ #include "ar5210/ar5210reg.h" #include "ar5210/ar5210phy.h" +#include "ah_eeprom_v1.h" + typedef struct { uint32_t Offset; uint32_t Value; @@ -73,6 +75,7 @@ ar5210Reset(struct ath_hal *ah, HAL_OPMODE opmode, #define N(a) (sizeof (a) /sizeof (a[0])) #define FAIL(_code) do { ecode = _code; goto bad; } while (0) struct ath_hal_5210 *ahp = AH5210(ah); + const HAL_EEPROM_v1 *ee = AH_PRIVATE(ah)->ah_eeprom; HAL_CHANNEL_INTERNAL *ichan; HAL_STATUS ecode; uint32_t ledstate; @@ -214,22 +217,22 @@ ar5210Reset(struct ath_hal *ah, HAL_OPMODE opmode, OS_REG_WRITE(ah, AR_PHY(10), (OS_REG_READ(ah, AR_PHY(10)) & 0xFFFF00FF) | - (ahp->ah_xlnaOn << 8)); + (ee->ee_xlnaOn << 8)); OS_REG_WRITE(ah, AR_PHY(13), - (ahp->ah_xpaOff << 24) | (ahp->ah_xpaOff << 16) | - (ahp->ah_xpaOn << 8) | ahp->ah_xpaOn); + (ee->ee_xpaOff << 24) | (ee->ee_xpaOff << 16) | + (ee->ee_xpaOn << 8) | ee->ee_xpaOn); OS_REG_WRITE(ah, AR_PHY(17), (OS_REG_READ(ah, AR_PHY(17)) & 0xFFFFC07F) | - ((ahp->ah_antenna >> 1) & 0x3F80)); + ((ee->ee_antenna >> 1) & 0x3F80)); OS_REG_WRITE(ah, AR_PHY(18), (OS_REG_READ(ah, AR_PHY(18)) & 0xFFFC0FFF) | - ((ahp->ah_antenna << 10) & 0x3F000)); + ((ee->ee_antenna << 10) & 0x3F000)); OS_REG_WRITE(ah, AR_PHY(25), (OS_REG_READ(ah, AR_PHY(25)) & 0xFFF80FFF) | - ((ahp->ah_thresh62 << 12) & 0x7F000)); + ((ee->ee_thresh62 << 12) & 0x7F000)); OS_REG_WRITE(ah, AR_PHY(68), (OS_REG_READ(ah, AR_PHY(68)) & 0xFFFFFFFC) | - (ahp->ah_antenna & 0x3)); + (ee->ee_antenna & 0x3)); if (!ar5210SetChannel(ah, ichan)) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unable to set channel\n", @@ -443,7 +446,8 @@ enum { * changes. */ HAL_BOOL -ar5210PerCalibration(struct ath_hal *ah, HAL_CHANNEL *chan, HAL_BOOL *isIQdone) +ar5210PerCalibrationN(struct ath_hal *ah, HAL_CHANNEL *chan, u_int chainMask, + HAL_BOOL longCal, HAL_BOOL *isCalDone) { uint32_t regBeacon; uint32_t reg9858, reg985c, reg9868; @@ -559,11 +563,23 @@ ar5210PerCalibration(struct ath_hal *ah, HAL_CHANNEL *chan, HAL_BOOL *isIQdone) /* Re-enable Beacons */ OS_REG_WRITE(ah, AR_BEACON, regBeacon); - *isIQdone = AH_TRUE; + *isCalDone = AH_TRUE; return AH_TRUE; } +HAL_BOOL +ar5210PerCalibration(struct ath_hal *ah, HAL_CHANNEL *chan, HAL_BOOL *isIQdone) +{ + return ar5210PerCalibrationN(ah, chan, 0x1, AH_TRUE, isIQdone); +} + +HAL_BOOL +ar5210ResetCalValid(struct ath_hal *ah, HAL_CHANNEL *chan) +{ + return AH_TRUE; +} + /* * Writes the given reset bit mask into the reset register */ @@ -600,7 +616,7 @@ ar5210SetResetReg(struct ath_hal *ah, uint32_t resetMask, u_int delay) * Returns: the pcdac value */ static uint8_t -getPcdac(struct ath_hal *ah, struct tpcMap *pRD, uint8_t dBm) +getPcdac(struct ath_hal *ah, const struct tpcMap *pRD, uint8_t dBm) { int32_t i; int useNextEntry = AH_FALSE; @@ -643,7 +659,8 @@ getPcdac(struct ath_hal *ah, struct tpcMap *pRD, uint8_t dBm) * Find or interpolates the gainF value from the table ptr. */ static uint8_t -getGainF(struct ath_hal *ah, struct tpcMap *pRD, uint8_t pcdac, uint8_t *dBm) +getGainF(struct ath_hal *ah, const struct tpcMap *pRD, + uint8_t pcdac, uint8_t *dBm) { uint32_t interp; int low, high, i; @@ -705,7 +722,7 @@ getGainF(struct ath_hal *ah, struct tpcMap *pRD, uint8_t pcdac, uint8_t *dBm) HAL_BOOL ar5210SetTxPowerLimit(struct ath_hal *ah, uint32_t limit) { - AH_PRIVATE(ah)->ah_powerLimit = AH_MIN(limit, MAX_RATE_POWER); + AH_PRIVATE(ah)->ah_powerLimit = AH_MIN(limit, AR5210_MAX_RATE_POWER); /* XXX flush to h/w */ return AH_TRUE; } @@ -716,15 +733,15 @@ ar5210SetTxPowerLimit(struct ath_hal *ah, uint32_t limit) static HAL_BOOL setupPowerSettings(struct ath_hal *ah, HAL_CHANNEL *chan, uint8_t cp[17]) { - struct ath_hal_5210 *ahp = AH5210(ah); + const HAL_EEPROM_v1 *ee = AH_PRIVATE(ah)->ah_eeprom; uint8_t gainFRD, gainF36, gainF48, gainF54; uint8_t dBmRD, dBm36, dBm48, dBm54, dontcare; uint32_t rd, group; - struct tpcMap *pRD; + const struct tpcMap *pRD; /* Set OB/DB Values regardless of channel */ - cp[15] = (ahp->ah_biasCurrents >> 4) & 0x7; - cp[16] = ahp->ah_biasCurrents & 0x7; + cp[15] = (ee->ee_biasCurrents >> 4) & 0x7; + cp[16] = ee->ee_biasCurrents & 0x7; if (chan->channel < 5170 || chan->channel > 5320) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel %u\n", @@ -732,11 +749,12 @@ setupPowerSettings(struct ath_hal *ah, HAL_CHANNEL *chan, uint8_t cp[17]) return AH_FALSE; } - HALASSERT(ahp->ah_eeversion == 1); + HALASSERT(ee->ee_version >= AR_EEPROM_VER1 && + ee->ee_version < AR_EEPROM_VER3); /* Match regulatory domain */ for (rd = 0; rd < AR_REG_DOMAINS_MAX; rd++) - if (AH_PRIVATE(ah)->ah_currentRD == ahp->ah_regDomain[rd]) + if (AH_PRIVATE(ah)->ah_currentRD == ee->ee_regDomain[rd]) break; if (rd == AR_REG_DOMAINS_MAX) { #ifdef AH_DEBUG @@ -756,7 +774,7 @@ setupPowerSettings(struct ath_hal *ah, HAL_CHANNEL *chan, uint8_t cp[17]) /* Integer divide will set group from 0 to 4 */ group = group / 3; - pRD = &ahp->ah_tpc[group]; + pRD = &ee->ee_tpc[group]; /* Set PC DAC Values */ cp[14] = pRD->regdmn[rd]; @@ -773,7 +791,7 @@ setupPowerSettings(struct ath_hal *ah, HAL_CHANNEL *chan, uint8_t cp[17]) /* Power Scale if requested */ if (AH_PRIVATE(ah)->ah_tpScale != HAL_TP_SCALE_MAX) { static const uint16_t tpcScaleReductionTable[5] = - { 0, 3, 6, 9, MAX_RATE_POWER }; + { 0, 3, 6, 9, AR5210_MAX_RATE_POWER }; uint16_t tpScale; tpScale = tpcScaleReductionTable[AH_PRIVATE(ah)->ah_tpScale]; @@ -860,7 +878,7 @@ ar5210SetTransmitPower(struct ath_hal *ah, HAL_CHANNEL *chan) for (i = 7; i < 15; i++) cp[i] = ath_hal_reverseBits(cp[i], 6); - /* merge transmit power values into the register */ + /* merge transmit power values into the register - quite gross */ pwr_regs[0] |= ((cp[1] << 5) & 0xE0) | (cp[0] & 0x1F); pwr_regs[1] |= ((cp[3] << 7) & 0x80) | ((cp[2] << 2) & 0x7C) | ((cp[1] >> 3) & 0x03); diff --git a/ar5210/ar5210desc.h b/ar5210/ar5210desc.h index 6f105e17a612..d7d382ccfaa1 100644 --- a/ar5210/ar5210desc.h +++ b/ar5210/ar5210desc.h @@ -68,7 +68,7 @@ struct ar5210_desc { /* TX ds_ctl1 */ #define AR_BufLen 0x00000fff /* data buffer length */ #define AR_More 0x00001000 /* more desc in this frame */ -#define AR_EncryptKeyIdx 0x0007e000 /* encrypt key table index */ +#define AR_EncryptKeyIdx 0x0007e000 /* ecnrypt key table index */ #define AR_EncryptKeyIdx_S 13 #define AR_RTSDuration 0xfff80000 /* lower 13bit of duration */ diff --git a/ar5211/ar5211.h b/ar5211/ar5211.h index 5ee0646a83d6..e71d78c65311 100644 --- a/ar5211/ar5211.h +++ b/ar5211/ar5211.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: ar5211.h,v 1.7 2008/11/10 04:08:02 sam Exp $ + * $Id: ar5211.h,v 1.8 2008/11/10 22:08:47 sam Exp $ */ #ifndef _ATH_AR5211_H_ #define _ATH_AR5211_H_ @@ -155,6 +155,9 @@ extern HAL_BOOL ar5211PhyDisable(struct ath_hal *); extern HAL_BOOL ar5211Disable(struct ath_hal *); extern HAL_BOOL ar5211ChipReset(struct ath_hal *, uint16_t); extern HAL_BOOL ar5211PerCalibration(struct ath_hal *, HAL_CHANNEL *, HAL_BOOL *); +extern HAL_BOOL ar5211PerCalibrationN(struct ath_hal *ah, HAL_CHANNEL *chan, + u_int chainMask, HAL_BOOL longCal, HAL_BOOL *isCalDone); +extern HAL_BOOL ar5211ResetCalValid(struct ath_hal *ah, HAL_CHANNEL *chan); extern HAL_BOOL ar5211SetTxPowerLimit(struct ath_hal *, uint32_t limit); extern HAL_BOOL ar5211SetTransmitPower(struct ath_hal *, HAL_CHANNEL *); extern HAL_BOOL ar5211CalNoiseFloor(struct ath_hal *, HAL_CHANNEL_INTERNAL *); @@ -224,6 +227,9 @@ extern HAL_BOOL ar5211SetMacAddress(struct ath_hal *ah, const uint8_t *); extern void ar5211GetBssIdMask(struct ath_hal *, uint8_t *); extern HAL_BOOL ar5211SetBssIdMask(struct ath_hal *, const uint8_t *); extern HAL_BOOL ar5211EepromRead(struct ath_hal *, u_int off, uint16_t *data); +extern HAL_BOOL ar5211EepromWrite(struct ath_hal *, u_int off, uint16_t data); +extern HAL_BOOL ar5211SetRegulatoryDomain(struct ath_hal *, + uint16_t, HAL_STATUS *); extern u_int ar5211GetWirelessModes(struct ath_hal *); extern void ar5211EnableRfKill(struct ath_hal *); extern uint32_t ar5211GpioGet(struct ath_hal *, uint32_t gpio); diff --git a/ar5211/ar5211_attach.c b/ar5211/ar5211_attach.c index cf658ecbcf84..664b648baece 100644 --- a/ar5211/ar5211_attach.c +++ b/ar5211/ar5211_attach.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_attach.c,v 1.8 2008/11/10 04:08:02 sam Exp $ + * $Id: ar5211_attach.c,v 1.11 2008/11/27 22:29:52 sam Exp $ */ #include "opt_ah.h" @@ -49,6 +49,8 @@ static const struct ath_hal_private ar5211hal = {{ .ah_disable = ar5211Disable, .ah_setPCUConfig = ar5211SetPCUConfig, .ah_perCalibration = ar5211PerCalibration, + .ah_perCalibrationN = ar5211PerCalibrationN, + .ah_resetCalValid = ar5211ResetCalValid, .ah_setTxPowerLimit = ar5211SetTxPowerLimit, .ah_getChanNoise = ath_hal_getChanNoise, @@ -96,6 +98,7 @@ static const struct ath_hal_private ar5211hal = {{ .ah_setMacAddress = ar5211SetMacAddress, .ah_getBssIdMask = ar5211GetBssIdMask, .ah_setBssIdMask = ar5211SetBssIdMask, + .ah_setRegulatoryDomain = ar5211SetRegulatoryDomain, .ah_setLedState = ar5211SetLedState, .ah_writeAssocid = ar5211WriteAssocid, .ah_gpioCfgInput = ar5211GpioCfgInput, @@ -329,7 +332,7 @@ ar5211Attach(uint16_t devid, HAL_SOFTC sc, } AH_PRIVATE(ah)->ah_currentRD = eeval; AH_PRIVATE(ah)->ah_getNfAdjust = ar5211GetNfAdjust; - + /* * Got everything we need now to setup the capabilities. */ @@ -459,9 +462,6 @@ ar5211FillCapabilityInfo(struct ath_hal *ah) struct ath_hal_private *ahpriv = AH_PRIVATE(ah); HAL_CAPABILITIES *pCap = &ahpriv->ah_caps; - if (AH_PRIVATE(ah)->ah_currentRD == 1) - return AH_FALSE; - /* Construct wireless mode from EEPROM */ pCap->halWirelessModes = 0; if (ath_hal_eepromGetFlag(ah, AR_EEP_AMODE)) { diff --git a/ar5211/ar5211_interrupts.c b/ar5211/ar5211_interrupts.c index 3381dc5efd6c..c3203296d45e 100644 --- a/ar5211/ar5211_interrupts.c +++ b/ar5211/ar5211_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: ar5211_interrupts.c,v 1.5 2008/11/10 04:08:02 sam Exp $ + * $Id: ar5211_interrupts.c,v 1.6 2008/11/27 22:29:52 sam Exp $ */ #include "opt_ah.h" @@ -67,7 +67,9 @@ ar5211GetPendingInterrupts(struct ath_hal *ah, HAL_INT *masked) if (isr & (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR | AR_ISR_TXEOL)) *masked |= HAL_INT_TX; /* - * RXORN can hang the receive path so we force a hardware + * Receive overrun is usually non-fatal on Oahu/Spirit. + * BUT on some parts rx could fail and the chip must be reset. + * So we force a hardware reset in all cases. */ if ((isr & AR_ISR_RXORN) && AH_PRIVATE(ah)->ah_rxornIsFatal) { HALDEBUG(ah, HAL_DEBUG_ANY, diff --git a/ar5211/ar5211_misc.c b/ar5211/ar5211_misc.c index caeef5b0bff8..ee8ede9690be 100644 --- a/ar5211/ar5211_misc.c +++ b/ar5211/ar5211_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: ar5211_misc.c,v 1.6 2008/11/10 04:08:02 sam Exp $ + * $Id: ar5211_misc.c,v 1.7 2008/11/27 22:29:52 sam Exp $ */ #include "opt_ah.h" @@ -83,6 +83,55 @@ ar5211EepromRead(struct ath_hal *ah, u_int off, uint16_t *data) return AH_TRUE; } +#ifdef AH_SUPPORT_WRITE_EEPROM +/* + * Write 16 bits of data to the specified EEPROM offset. + */ +HAL_BOOL +ar5211EepromWrite(struct ath_hal *ah, u_int off, uint16_t data) +{ + return AH_FALSE; +} +#endif /* AH_SUPPORT_WRITE_EEPROM */ + +/* + * Attempt to change the cards operating regulatory domain to the given value + */ +HAL_BOOL +ar5211SetRegulatoryDomain(struct ath_hal *ah, + uint16_t regDomain, HAL_STATUS *status) +{ + HAL_STATUS ecode; + + if (AH_PRIVATE(ah)->ah_currentRD == regDomain) { + ecode = HAL_EINVAL; + goto bad; + } + /* + * Check if EEPROM is configured to allow this; must + * be a proper version and the protection bits must + * permit re-writing that segment of the EEPROM. + */ + if (ath_hal_eepromGetFlag(ah, AR_EEP_WRITEPROTECT)) { + ecode = HAL_EEWRITE; + goto bad; + } +#ifdef AH_SUPPORT_WRITE_REGDOMAIN + if (ar5211EepromWrite(ah, AR_EEPROM_REG_DOMAIN, regDomain)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: set regulatory domain to %u (0x%x)\n", + __func__, regDomain, regDomain); + AH_PRIVATE(ah)->ah_currentRD = regDomain; + return AH_TRUE; + } +#endif + ecode = HAL_EIO; +bad: + if (status) + *status = ecode; + return AH_FALSE; +} + /* * Return the wireless modes (a,b,g,t) supported by hardware. * @@ -292,11 +341,10 @@ ar5211GetTsf64(struct ath_hal *ah) * 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. + * 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++; } diff --git a/ar5211/ar5211_reset.c b/ar5211/ar5211_reset.c index 87d6fac0c291..80c7962597e9 100644 --- a/ar5211/ar5211_reset.c +++ b/ar5211/ar5211_reset.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_reset.c,v 1.6 2008/11/10 04:08:03 sam Exp $ + * $Id: ar5211_reset.c,v 1.9 2008/11/27 22:29:52 sam Exp $ */ #include "opt_ah.h" @@ -222,7 +222,7 @@ uint32_t softLedCfg, softLedState; * not accurate enough (e.g. 1 ms resolution). * 2. It would still not be accurate. * - * The most important aspect of this solution, + * The most important aspect of this workaround, * is that, after reset, the TSF is behind * other STAs TSFs. This will allow the STA to * properly resynchronize its TSF in adhoc mode. @@ -408,7 +408,7 @@ uint32_t softLedCfg, softLedState; /* * for pre-Production Oahu only. * Disable clock gating in all DMA blocks. Helps when using - * 11B and AES. This will result in higher power consumption. + * 11B and AES but results in higher power consumption. */ if (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_OAHU && AH_PRIVATE(ah)->ah_macRev < AR_SREV_OAHU_PROD) { @@ -665,7 +665,8 @@ ar5211ChipReset(struct ath_hal *ah, uint16_t channelFlags) * changes. */ HAL_BOOL -ar5211PerCalibration(struct ath_hal *ah, HAL_CHANNEL *chan, HAL_BOOL *isIQdone) +ar5211PerCalibrationN(struct ath_hal *ah, HAL_CHANNEL *chan, u_int chainMask, + HAL_BOOL longCal, HAL_BOOL *isCalDone) { struct ath_hal_5211 *ahp = AH5211(ah); HAL_CHANNEL_INTERNAL *ichan; @@ -729,31 +730,44 @@ ar5211PerCalibration(struct ath_hal *ah, HAL_CHANNEL *chan, HAL_BOOL *isIQdone) OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4, data); } } + *isCalDone = !ahp->ah_bIQCalibration; - /* Perform noise floor and set status */ - if (!ar5211IsNfGood(ah, ichan)) { - /* report up and clear internal state */ - chan->channelFlags |= CHANNEL_CW_INT; - ichan->channelFlags &= ~CHANNEL_CW_INT; - return AH_FALSE; - } - if (!ar5211CalNoiseFloor(ah, ichan)) { - /* - * Delay 5ms before retrying the noise floor - * just to make sure, as we are in an error - * condition here. - */ - OS_DELAY(5000); - if (!ar5211CalNoiseFloor(ah, ichan)) { - if (!IS_CHAN_CCK(chan)) - chan->channelFlags |= CHANNEL_CW_INT; + if (longCal) { + /* Perform noise floor and set status */ + if (!ar5211IsNfGood(ah, ichan)) { + /* report up and clear internal state */ + chan->channelFlags |= CHANNEL_CW_INT; + ichan->channelFlags &= ~CHANNEL_CW_INT; return AH_FALSE; } + if (!ar5211CalNoiseFloor(ah, ichan)) { + /* + * Delay 5ms before retrying the noise floor + * just to make sure, as we are in an error + * condition here. + */ + OS_DELAY(5000); + if (!ar5211CalNoiseFloor(ah, ichan)) { + if (!IS_CHAN_CCK(chan)) + chan->channelFlags |= CHANNEL_CW_INT; + return AH_FALSE; + } + } + ar5211RequestRfgain(ah); } + return AH_TRUE; +} - ar5211RequestRfgain(ah); - *isIQdone = !ahp->ah_bIQCalibration; +HAL_BOOL +ar5211PerCalibration(struct ath_hal *ah, HAL_CHANNEL *chan, HAL_BOOL *isIQdone) +{ + return ar5211PerCalibrationN(ah, chan, 0x1, AH_TRUE, isIQdone); +} +HAL_BOOL +ar5211ResetCalValid(struct ath_hal *ah, HAL_CHANNEL *chan) +{ + /* XXX */ return AH_TRUE; } diff --git a/ar5211/ar5211_xmit.c b/ar5211/ar5211_xmit.c index d40549a4129e..23d4a8ad309f 100644 --- a/ar5211/ar5211_xmit.c +++ b/ar5211/ar5211_xmit.c @@ -364,7 +364,7 @@ ar5211ResetTxQueue(struct ath_hal *ah, u_int q) #ifndef AH_DISABLE_WME /* - * This is a really not the right way to do it, but + * Yes, this is a hack and not the right way to do it, but * it does get the lockout bits and backoff set for the * high-pri WME queues for testing. We need to either extend * the meaning of queueInfo->mode, or create something like diff --git a/ar5212/ar2316.c b/ar5212/ar2316.c index 92798648c1d8..207e7b743554 100644 --- a/ar5212/ar2316.c +++ b/ar5212/ar2316.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: ar2316.c,v 1.8 2008/11/10 04:08:03 sam Exp $ + * $Id: ar2316.c,v 1.9 2008/11/15 22:15:46 sam Exp $ */ #include "opt_ah.h" @@ -519,8 +519,11 @@ ar2316SetPowerTable(struct ath_hal *ah, int16_t minCalPower2316_t2; uint16_t *pdadcValues = ahp->ah_pcdacTable; uint16_t gainBoundaries[4]; - uint32_t i, reg32, regoffset, tpcrg1; - int numPdGainsUsed; + uint32_t reg32, regoffset; + int i, numPdGainsUsed; +#ifndef AH_USE_INIPDGAIN + uint32_t tpcrg1; +#endif HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: chan 0x%x flag 0x%x\n", __func__, chan->channel,chan->channelFlags); @@ -542,10 +545,16 @@ ar2316SetPowerTable(struct ath_hal *ah, &minCalPower2316_t2,gainBoundaries, rfXpdGain, pdadcValues); HALASSERT(1 <= numPdGainsUsed && numPdGainsUsed <= 3); -#if 0 +#ifdef AH_USE_INIPDGAIN + /* + * Use pd_gains curve from eeprom; Atheros always uses + * the default curve from the ini file but some vendors + * (e.g. Zcomax) want to override this curve and not + * honoring their settings results in tx power 5dBm low. + */ OS_REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN, (pRawDataset->pDataPerChannel[0].numPdGains - 1)); -#endif +#else tpcrg1 = OS_REG_READ(ah, AR_PHY_TPCRG1); tpcrg1 = (tpcrg1 &~ AR_PHY_TPCRG1_NUM_PD_GAIN) | SM(numPdGainsUsed-1, AR_PHY_TPCRG1_NUM_PD_GAIN); @@ -570,6 +579,7 @@ ar2316SetPowerTable(struct ath_hal *ah, __func__, OS_REG_READ(ah, AR_PHY_TPCRG1), tpcrg1); #endif OS_REG_WRITE(ah, AR_PHY_TPCRG1, tpcrg1); +#endif /* * Note the pdadc table may not start at 0 dBm power, could be diff --git a/ar5212/ar2317.c b/ar5212/ar2317.c index 3f11d8f7c519..084fd5bc4f66 100644 --- a/ar5212/ar2317.c +++ b/ar5212/ar2317.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: ar2317.c,v 1.7 2008/11/10 04:08:03 sam Exp $ + * $Id: ar2317.c,v 1.8 2008/11/15 22:15:46 sam Exp $ */ #include "opt_ah.h" @@ -496,8 +496,11 @@ ar2317SetPowerTable(struct ath_hal *ah, int16_t minCalPower2317_t2; uint16_t *pdadcValues = ahp->ah_pcdacTable; uint16_t gainBoundaries[4]; - uint32_t i, reg32, regoffset, tpcrg1; - int numPdGainsUsed; + uint32_t reg32, regoffset; + int i, numPdGainsUsed; +#ifndef AH_USE_INIPDGAIN + uint32_t tpcrg1; +#endif HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: chan 0x%x flag 0x%x\n", __func__, chan->channel,chan->channelFlags); @@ -519,16 +522,16 @@ ar2317SetPowerTable(struct ath_hal *ah, &minCalPower2317_t2,gainBoundaries, rfXpdGain, pdadcValues); HALASSERT(1 <= numPdGainsUsed && numPdGainsUsed <= 3); +#ifdef AH_USE_INIPDGAIN /* * Use pd_gains curve from eeprom; Atheros always uses * the default curve from the ini file but some vendors * (e.g. Zcomax) want to override this curve and not * honoring their settings results in tx power 5dBm low. */ -#if 0 OS_REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN, (pRawDataset->pDataPerChannel[0].numPdGains - 1)); -#endif +#else tpcrg1 = OS_REG_READ(ah, AR_PHY_TPCRG1); tpcrg1 = (tpcrg1 &~ AR_PHY_TPCRG1_NUM_PD_GAIN) | SM(numPdGainsUsed-1, AR_PHY_TPCRG1_NUM_PD_GAIN); @@ -553,6 +556,7 @@ ar2317SetPowerTable(struct ath_hal *ah, __func__, OS_REG_READ(ah, AR_PHY_TPCRG1), tpcrg1); #endif OS_REG_WRITE(ah, AR_PHY_TPCRG1, tpcrg1); +#endif /* * Note the pdadc table may not start at 0 dBm power, could be diff --git a/ar5212/ar2413.c b/ar5212/ar2413.c index 803c77bb1883..a16f7058b6dd 100644 --- a/ar5212/ar2413.c +++ b/ar5212/ar2413.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: ar2413.c,v 1.7 2008/11/10 04:08:03 sam Exp $ + * $Id: ar2413.c,v 1.8 2008/11/15 22:15:46 sam Exp $ */ #include "opt_ah.h" @@ -513,8 +513,11 @@ ar2413SetPowerTable(struct ath_hal *ah, int16_t minCalPower2413_t2; uint16_t *pdadcValues = ahp->ah_pcdacTable; uint16_t gainBoundaries[4]; - uint32_t i, reg32, regoffset, tpcrg1; - int numPdGainsUsed; + uint32_t reg32, regoffset; + int i, numPdGainsUsed; +#ifndef AH_USE_INIPDGAIN + uint32_t tpcrg1; +#endif HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: chan 0x%x flag 0x%x\n", __func__, chan->channel,chan->channelFlags); @@ -536,10 +539,16 @@ ar2413SetPowerTable(struct ath_hal *ah, &minCalPower2413_t2,gainBoundaries, rfXpdGain, pdadcValues); HALASSERT(1 <= numPdGainsUsed && numPdGainsUsed <= 3); -#if 0 +#ifdef AH_USE_INIPDGAIN + /* + * Use pd_gains curve from eeprom; Atheros always uses + * the default curve from the ini file but some vendors + * (e.g. Zcomax) want to override this curve and not + * honoring their settings results in tx power 5dBm low. + */ OS_REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN, (pRawDataset->pDataPerChannel[0].numPdGains - 1)); -#endif +#else tpcrg1 = OS_REG_READ(ah, AR_PHY_TPCRG1); tpcrg1 = (tpcrg1 &~ AR_PHY_TPCRG1_NUM_PD_GAIN) | SM(numPdGainsUsed-1, AR_PHY_TPCRG1_NUM_PD_GAIN); @@ -564,6 +573,7 @@ ar2413SetPowerTable(struct ath_hal *ah, __func__, OS_REG_READ(ah, AR_PHY_TPCRG1), tpcrg1); #endif OS_REG_WRITE(ah, AR_PHY_TPCRG1, tpcrg1); +#endif /* * Note the pdadc table may not start at 0 dBm power, could be diff --git a/ar5212/ar2425.c b/ar5212/ar2425.c index 5bd64d5061a9..0b8ef20a4329 100644 --- a/ar5212/ar2425.c +++ b/ar5212/ar2425.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: ar2425.c,v 1.7 2008/11/10 04:08:03 sam Exp $ + * $Id: ar2425.c,v 1.8 2008/11/16 21:33:05 sam Exp $ */ #include "opt_ah.h" @@ -160,12 +160,10 @@ ar2425SetRfRegs(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan, uint16_t modesIn for (i = 0; i < N(ar5212Bank##_ix##_2425); i++) \ (_priv)->Bank##_ix##Data[i] = ar5212Bank##_ix##_2425[i][_col];\ } while (0) - - struct ath_hal_5212 *ahp = AH5212(ah); -#if 0 - uint16_t ob2GHz = 0, db2GHz = 0; -#endif + struct ath_hal_5212 *ahp = AH5212(ah); + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; struct ar2425State *priv = AR2425(ah); + uint16_t ob2GHz = 0, db2GHz = 0; int regWrites = 0; HALDEBUG(ah, HAL_DEBUG_RFPARAM, @@ -173,24 +171,24 @@ ar2425SetRfRegs(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan, uint16_t modesIn __func__, chan->channel, chan->channelFlags, modesIndex); HALASSERT(priv); -#if 0 + /* Setup rf parameters */ - switch (chan->channelFlags & CHANNEL_ALL) { - case CHANNEL_B: - ob2GHz = ahp->ah_obFor24; - db2GHz = ahp->ah_dbFor24; - break; - case CHANNEL_G: - case CHANNEL_108G: - ob2GHz = ahp->ah_obFor24g; - db2GHz = ahp->ah_dbFor24g; - break; - default: - HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n", - __func__, chan->channelFlags); - return AH_FALSE; - } -#endif + switch (chan->channelFlags & CHANNEL_ALL) { + case CHANNEL_B: + ob2GHz = ee->ee_obFor24; + db2GHz = ee->ee_dbFor24; + break; + case CHANNEL_G: + case CHANNEL_108G: + ob2GHz = ee->ee_obFor24g; + db2GHz = ee->ee_dbFor24g; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n", + __func__, chan->channelFlags); + return AH_FALSE; + } + /* Bank 1 Write */ RF_BANK_SETUP(priv, 1, 1); @@ -202,10 +200,10 @@ ar2425SetRfRegs(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan, uint16_t modesIn /* Bank 6 Write */ RF_BANK_SETUP(priv, 6, modesIndex); -#if 0 + ar5212ModifyRfBuffer(priv->Bank6Data, ob2GHz, 3, 193, 0); ar5212ModifyRfBuffer(priv->Bank6Data, db2GHz, 3, 190, 0); -#endif + /* Bank 7 Setup */ RF_BANK_SETUP(priv, 7, modesIndex); diff --git a/ar5212/ar5212.h b/ar5212/ar5212.h index d8f9aa45ef64..1236123f888c 100644 --- a/ar5212/ar5212.h +++ b/ar5212/ar5212.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: ar5212.h,v 1.9 2008/11/10 04:08:03 sam Exp $ + * $Id: ar5212.h,v 1.16 2008/11/22 07:42:00 sam Exp $ */ #ifndef _ATH_AR5212_H_ #define _ATH_AR5212_H_ @@ -267,10 +267,12 @@ struct ath_hal_5212 { uint32_t ah_txEolInterruptMask; uint32_t ah_txUrnInterruptMask; HAL_TX_QUEUE_INFO ah_txq[HAL_NUM_TX_QUEUES]; + uint32_t ah_intrTxqs; /* tx q interrupt state */ /* decomp mask array */ - uint8_t ah_decompMask[HAL_DECOMP_MASK_SIZE]; + uint8_t ah_decompMask[HAL_DECOMP_MASK_SIZE]; HAL_POWER_MODE ah_powerMode; - HAL_ANT_SETTING ah_diversityControl; /* antenna setting */ + HAL_ANT_SETTING ah_antControl; /* antenna setting */ + HAL_BOOL ah_diversity; /* fast diversity setting */ enum { IQ_CAL_INACTIVE, IQ_CAL_RUNNING, @@ -283,6 +285,8 @@ struct ath_hal_5212 { uint32_t ah_rssiThr; /* RSSI_THR settings */ HAL_BOOL ah_cwCalRequire; /* for ap51 */ HAL_BOOL ah_tpcEnabled; /* per-packet tpc enabled */ + HAL_BOOL ah_phyPowerOn; /* PHY power state */ + HAL_BOOL ah_isHb63; /* cached HB63 check */ uint32_t ah_macTPC; /* tpc register */ uint32_t ah_beaconInterval; /* XXX */ enum { @@ -301,18 +305,12 @@ struct ath_hal_5212 { u_int ah_acktimeout; /* user-specified ack timeout */ u_int ah_ctstimeout; /* user-specified cts timeout */ u_int ah_sifstime; /* user-specified sifs time */ - /* - * XXX - * 11g-specific stuff; belongs in the driver. - */ - uint8_t ah_gBeaconRate; /* fixed rate for G beacons */ /* * RF Silent handling; setup according to the EEPROM. */ uint32_t ah_gpioSelect; /* GPIO pin to use */ uint32_t ah_polarity; /* polarity to disable RF */ uint32_t ah_gpioBit; /* after init, prev value */ - HAL_BOOL ah_eepEnabled; /* EEPROM bit for capability */ /* * ANI support. */ @@ -330,30 +328,16 @@ struct ath_hal_5212 { uint16_t *ah_pcdacTable; u_int ah_pcdacTableSize; uint16_t ah_ratesArray[16]; - - /* - * Tx queue interrupt state. - */ - uint32_t ah_intrTxqs; - - HAL_BOOL ah_isHb63; /* cached HB63 check */ }; #define AH5212(_ah) ((struct ath_hal_5212 *)(_ah)) -#define IS_5112(ah) \ - ((AH_PRIVATE(ah)->ah_analog5GhzRev&0xf0) >= AR_RAD5112_SREV_MAJOR \ - && (AH_PRIVATE(ah)->ah_analog5GhzRev&0xf0) < AR_RAD2316_SREV_MAJOR ) -#define IS_RAD5112_REV1(ah) \ - ((AH_PRIVATE(ah)->ah_analog5GhzRev&0x0f) < (AR_RAD5112_SREV_2_0&0x0f)) -#define IS_RADX112_REV2(ah) \ - (IS_5112(ah) && \ - ((AH_PRIVATE(ah)->ah_analog5GhzRev == AR_RAD5112_SREV_2_0) || \ - (AH_PRIVATE(ah)->ah_analog5GhzRev == AR_RAD2112_SREV_2_0) || \ - (AH_PRIVATE(ah)->ah_analog5GhzRev == AR_RAD2112_SREV_2_1) || \ - (AH_PRIVATE(ah)->ah_analog5GhzRev == AR_RAD5112_SREV_2_1))) -#define IS_5312_2_X(ah) \ - (((AH_PRIVATE(ah)->ah_macVersion) == AR_SREV_VERSION_VENICE) && \ - (((AH_PRIVATE(ah)->ah_macRev) == 2) || ((AH_PRIVATE(ah)->ah_macRev) == 7))) +/* + * IS_XXXX macros test the MAC version + * IS_RADXXX macros test the radio/RF version (matching both 2G-only and 2/5G) + * + * Some single chip radios have equivalent radio/RF (e.g. 5112) + * for those use IS_RADXXX_ANY macros. + */ #define IS_2317(ah) \ ((AH_PRIVATE(ah)->ah_devid == AR5212_AR2317_REV1) || \ (AH_PRIVATE(ah)->ah_devid == AR5212_AR2317_REV2)) @@ -375,6 +359,29 @@ struct ath_hal_5212 { #define IS_PCIE(ah) (IS_5424(ah) || IS_2425(ah)) +#define AH_RADIO_MAJOR(ah) \ + (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) +#define AH_RADIO_MINOR(ah) \ + (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MINOR) +#define IS_RAD5111(ah) \ + (AH_RADIO_MAJOR(ah) == AR_RAD5111_SREV_MAJOR || \ + AH_RADIO_MAJOR(ah) == AR_RAD2111_SREV_MAJOR) +#define IS_RAD5112(ah) \ + (AH_RADIO_MAJOR(ah) == AR_RAD5112_SREV_MAJOR || \ + AH_RADIO_MAJOR(ah) == AR_RAD2112_SREV_MAJOR) +/* NB: does not include 5413 as Atheros' IS_5112 macro does */ +#define IS_RAD5112_ANY(ah) \ + (AR_RAD5112_SREV_MAJOR <= AH_RADIO_MAJOR(ah) && \ + AH_RADIO_MAJOR(ah) <= AR_RAD2413_SREV_MAJOR) +#define IS_RAD5112_REV1(ah) \ + (IS_RAD5112(ah) && \ + AH_RADIO_MINOR(ah) < (AR_RAD5112_SREV_2_0 & AR_RADIO_SREV_MINOR)) +#define IS_RADX112_REV2(ah) \ + (AH_PRIVATE(ah)->ah_analog5GhzRev == AR_RAD5112_SREV_2_0 || \ + AH_PRIVATE(ah)->ah_analog5GhzRev == AR_RAD2112_SREV_2_0 || \ + AH_PRIVATE(ah)->ah_analog5GhzRev == AR_RAD2112_SREV_2_1 || \ + AH_PRIVATE(ah)->ah_analog5GhzRev == AR_RAD5112_SREV_2_1) + #define ar5212RfDetach(ah) do { \ if (AH5212(ah)->ah_rfHal != AH_NULL) \ AH5212(ah)->ah_rfHal->rfDetach(ah); \ @@ -534,7 +541,11 @@ extern void ar5212SetOperatingMode(struct ath_hal *ah, int opmode); extern HAL_BOOL ar5212PhyDisable(struct ath_hal *ah); extern HAL_BOOL ar5212Disable(struct ath_hal *ah); extern HAL_BOOL ar5212ChipReset(struct ath_hal *ah, HAL_CHANNEL *); -extern HAL_BOOL ar5212PerCalibration(struct ath_hal *ah, HAL_CHANNEL *chan, HAL_BOOL *isIQdone); +extern HAL_BOOL ar5212PerCalibration(struct ath_hal *ah, HAL_CHANNEL *chan, + HAL_BOOL *isIQdone); +extern HAL_BOOL ar5212PerCalibrationN(struct ath_hal *ah, HAL_CHANNEL *chan, + u_int chainMask, HAL_BOOL longCal, HAL_BOOL *isCalDone); +extern HAL_BOOL ar5212ResetCalValid(struct ath_hal *ah, HAL_CHANNEL *chan); extern int16_t ar5212GetNoiseFloor(struct ath_hal *ah); extern void ar5212InitNfCalHistBuffer(struct ath_hal *); extern int16_t ar5212GetNfHistMid(const int16_t calData[]); @@ -546,6 +557,7 @@ extern HAL_BOOL ar5212GetChipPowerLimits(struct ath_hal *ah, HAL_CHANNEL *chans, uint32_t nchans); extern void ar5212InitializeGainValues(struct ath_hal *); extern HAL_RFGAIN ar5212GetRfgain(struct ath_hal *ah); +extern void ar5212RequestRfgain(struct ath_hal *); extern HAL_BOOL ar5212UpdateTxTrigLevel(struct ath_hal *, HAL_BOOL IncTrigLevel); diff --git a/ar5212/ar5212_ani.c b/ar5212/ar5212_ani.c index 8d9d8c0de2d4..1440f2340f87 100644 --- a/ar5212/ar5212_ani.c +++ b/ar5212/ar5212_ani.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_ani.c,v 1.5 2008/11/10 04:08:03 sam Exp $ + * $Id: ar5212_ani.c,v 1.7 2008/11/21 00:16:21 sam Exp $ */ #include "opt_ah.h" @@ -435,13 +435,17 @@ ar5212AniOfdmErrTrigger(struct ath_hal *ah) aniState = ahp->ah_curani; params = aniState->params; /* First, raise noise immunity level, up to max */ - if (aniState->noiseImmunityLevel < params->maxNoiseImmunityLevel) { + if (aniState->noiseImmunityLevel+1 < params->maxNoiseImmunityLevel) { + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: raise NI to %u\n", __func__, + aniState->noiseImmunityLevel + 1); ar5212AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, aniState->noiseImmunityLevel + 1); return; } /* then, raise spur immunity level, up to max */ - if (aniState->spurImmunityLevel < params->maxSpurImmunityLevel) { + if (aniState->spurImmunityLevel+1 < params->maxSpurImmunityLevel) { + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: raise SI to %u\n", __func__, + aniState->spurImmunityLevel + 1); ar5212AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL, aniState->spurImmunityLevel + 1); return; @@ -455,6 +459,8 @@ ar5212AniOfdmErrTrigger(struct ath_hal *ah) * weak sig detect. */ if (!aniState->ofdmWeakSigDetectOff) { + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: rssi %d OWSD off\n", __func__, rssi); ar5212AniControl(ah, HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, AH_FALSE); @@ -466,7 +472,10 @@ ar5212AniOfdmErrTrigger(struct ath_hal *ah) * If weak sig detect is already off, as last resort, * raise firstep level */ - if (aniState->firstepLevel < params->maxFirstepLevel) { + if (aniState->firstepLevel+1 < params->maxFirstepLevel) { + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: rssi %d raise ST %u\n", __func__, rssi, + aniState->firstepLevel+1); ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, aniState->firstepLevel + 1); return; @@ -476,13 +485,20 @@ ar5212AniOfdmErrTrigger(struct ath_hal *ah) * Beacon rssi in mid range, need ofdm weak signal * detect, but we can raise firststepLevel. */ - if (aniState->ofdmWeakSigDetectOff) + if (aniState->ofdmWeakSigDetectOff) { + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: rssi %d OWSD on\n", __func__, rssi); ar5212AniControl(ah, HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, AH_TRUE); - if (aniState->firstepLevel < params->maxFirstepLevel) + } + if (aniState->firstepLevel+1 < params->maxFirstepLevel) { + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: rssi %d raise ST %u\n", __func__, rssi, + aniState->firstepLevel+1); ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, aniState->firstepLevel + 1); + } return; } else { /* @@ -492,13 +508,22 @@ ar5212AniOfdmErrTrigger(struct ath_hal *ah) */ /* XXX can optimize */ if (IS_CHAN_B(chan) || IS_CHAN_G(chan)) { - if (!aniState->ofdmWeakSigDetectOff) + if (!aniState->ofdmWeakSigDetectOff) { + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: rssi %d OWSD off\n", + __func__, rssi); ar5212AniControl(ah, HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, AH_FALSE); - if (aniState->firstepLevel > 0) + } + if (aniState->firstepLevel > 0) { + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: rssi %d zero ST (was %u)\n", + __func__, rssi, + aniState->firstepLevel); ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, 0); + } return; } } @@ -521,7 +546,9 @@ ar5212AniCckErrTrigger(struct ath_hal *ah) /* first, raise noise immunity level, up to max */ aniState = ahp->ah_curani; params = aniState->params; - if (aniState->noiseImmunityLevel < params->maxNoiseImmunityLevel) { + if (aniState->noiseImmunityLevel+1 < params->maxNoiseImmunityLevel) { + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: raise NI to %u\n", __func__, + aniState->noiseImmunityLevel + 1); ar5212AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, aniState->noiseImmunityLevel + 1); return; @@ -534,9 +561,13 @@ ar5212AniCckErrTrigger(struct ath_hal *ah) * Beacon signal in mid and high range, * raise firstep level. */ - if (aniState->firstepLevel < params->maxFirstepLevel) + if (aniState->firstepLevel+1 < params->maxFirstepLevel) { + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: rssi %d raise ST %u\n", __func__, rssi, + aniState->firstepLevel+1); ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, aniState->firstepLevel + 1); + } } else { /* * Beacon rssi is low, zero firstep level to maximize @@ -544,9 +575,14 @@ ar5212AniCckErrTrigger(struct ath_hal *ah) */ /* XXX can optimize */ if (IS_CHAN_B(chan) || IS_CHAN_G(chan)) { - if (aniState->firstepLevel > 0) + if (aniState->firstepLevel > 0) { + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: rssi %d zero ST (was %u)\n", + __func__, rssi, + aniState->firstepLevel); ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, 0); + } } } } @@ -564,9 +600,6 @@ ar5212AniRestart(struct ath_hal *ah, struct ar5212AniState *aniState) * NB: these are written on reset based on the * ini so we must re-write them! */ - HALDEBUG(ah, HAL_DEBUG_ANI, - "%s: Writing ofdmbase=%u cckbase=%u\n", __func__, - params->ofdmPhyErrBase, params->cckPhyErrBase); OS_REG_WRITE(ah, AR_PHYCNT1, params->ofdmPhyErrBase); OS_REG_WRITE(ah, AR_PHYCNT2, params->cckPhyErrBase); OS_REG_WRITE(ah, AR_PHYCNTMASK1, AR_PHY_ERR_OFDM_TIMING); @@ -781,12 +814,17 @@ ar5212AniLowerImmunity(struct ath_hal *ah) * detection or lower firstep level. */ if (aniState->ofdmWeakSigDetectOff) { + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: rssi %d OWSD on\n", __func__, rssi); ar5212AniControl(ah, HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, AH_TRUE); return; } if (aniState->firstepLevel > 0) { + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: rssi %d lower ST %u\n", __func__, rssi, + aniState->firstepLevel-1); ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, aniState->firstepLevel - 1); return; @@ -796,6 +834,9 @@ ar5212AniLowerImmunity(struct ath_hal *ah) * Beacon rssi is low, reduce firstep level. */ if (aniState->firstepLevel > 0) { + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: rssi %d lower ST %u\n", __func__, rssi, + aniState->firstepLevel-1); ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, aniState->firstepLevel - 1); return; @@ -804,6 +845,8 @@ ar5212AniLowerImmunity(struct ath_hal *ah) } /* then lower spur immunity level, down to zero */ if (aniState->spurImmunityLevel > 0) { + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: lower SI %u\n", + __func__, aniState->spurImmunityLevel-1); ar5212AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL, aniState->spurImmunityLevel - 1); return; @@ -813,6 +856,8 @@ ar5212AniLowerImmunity(struct ath_hal *ah) * zero for now */ if (aniState->noiseImmunityLevel > 0) { + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: lower NI %u\n", + __func__, aniState->noiseImmunityLevel-1); ar5212AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, aniState->noiseImmunityLevel - 1); return; @@ -956,10 +1001,16 @@ ar5212AniPoll(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); ar5212AniOfdmErrTrigger(ah); ar5212AniRestart(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->cckPhyErrCount, aniState->listenTime); ar5212AniCckErrTrigger(ah); ar5212AniRestart(ah, aniState); } diff --git a/ar5212/ar5212_attach.c b/ar5212/ar5212_attach.c index 413a0023f600..a0baf5f7ba16 100644 --- a/ar5212/ar5212_attach.c +++ b/ar5212/ar5212_attach.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_attach.c,v 1.12 2008/11/10 04:08:03 sam Exp $ + * $Id: ar5212_attach.c,v 1.18 2008/11/19 22:10:42 sam Exp $ */ #include "opt_ah.h" @@ -56,6 +56,8 @@ static const struct ath_hal_private ar5212hal = {{ .ah_disable = ar5212Disable, .ah_setPCUConfig = ar5212SetPCUConfig, .ah_perCalibration = ar5212PerCalibration, + .ah_perCalibrationN = ar5212PerCalibrationN, + .ah_resetCalValid = ar5212ResetCalValid, .ah_setTxPowerLimit = ar5212SetTxPowerLimit, .ah_getChanNoise = ath_hal_getChanNoise, @@ -103,6 +105,7 @@ static const struct ath_hal_private ar5212hal = {{ .ah_setMacAddress = ar5212SetMacAddress, .ah_getBssIdMask = ar5212GetBssIdMask, .ah_setBssIdMask = ar5212SetBssIdMask, + .ah_setRegulatoryDomain = ar5212SetRegulatoryDomain, .ah_setLedState = ar5212SetLedState, .ah_writeAssocid = ar5212WriteAssocid, .ah_gpioCfgInput = ar5212GpioCfgInput, @@ -271,7 +274,8 @@ ar5212InitState(struct ath_hal_5212 *ahp, uint16_t devid, HAL_SOFTC sc, AH_PRIVATE(ah)->ah_powerLimit = MAX_RATE_POWER; AH_PRIVATE(ah)->ah_tpScale = HAL_TP_SCALE_MAX; /* no scaling */ - ahp->ah_diversityControl = HAL_ANT_VARIABLE; + ahp->ah_antControl = HAL_ANT_VARIABLE; + ahp->ah_diversity = AH_TRUE; ahp->ah_bIQCalibration = AH_FALSE; /* * Enable MIC handling. @@ -279,6 +283,7 @@ ar5212InitState(struct ath_hal_5212 *ahp, uint16_t devid, HAL_SOFTC sc, ahp->ah_staId1Defaults = AR_STA_ID1_CRPT_MIC_ENABLE; ahp->ah_rssiThr = INIT_RSSI_THR; ahp->ah_tpcEnabled = AH_FALSE; /* disabled by default */ + ahp->ah_phyPowerOn = AH_FALSE; ahp->ah_macTPC = SM(MAX_RATE_POWER, AR_TPC_ACK) | SM(MAX_RATE_POWER, AR_TPC_CTS) | SM(MAX_RATE_POWER, AR_TPC_CHIRP); @@ -289,11 +294,6 @@ ar5212InitState(struct ath_hal_5212 *ahp, uint16_t devid, HAL_SOFTC sc, ahp->ah_ctstimeout = (u_int) -1; ahp->ah_sifstime = (u_int) -1; OS_MEMCPY(&ahp->ah_bssidmask, defbssidmask, IEEE80211_ADDR_LEN); - - /* - * 11g-specific stuff - */ - ahp->ah_gBeaconRate = 0; /* adhoc beacon fixed rate */ #undef N } @@ -444,15 +444,18 @@ ar5212Attach(uint16_t devid, HAL_SOFTC sc, break; } if (IS_2413(ah)) { /* Griffin */ - AH_PRIVATE(ah)->ah_analog5GhzRev = 0x51; + AH_PRIVATE(ah)->ah_analog5GhzRev = + AR_RAD2413_SREV_MAJOR | 0x1; break; } if (IS_5413(ah)) { /* Eagle */ - AH_PRIVATE(ah)->ah_analog5GhzRev = 0x62; + AH_PRIVATE(ah)->ah_analog5GhzRev = + AR_RAD5413_SREV_MAJOR | 0x2; break; } if (IS_2425(ah) || IS_2417(ah)) {/* Swan or Nala */ - AH_PRIVATE(ah)->ah_analog5GhzRev = 0xA2; + AH_PRIVATE(ah)->ah_analog5GhzRev = + AR_RAD5424_SREV_MAJOR | 0x2; break; } } @@ -465,7 +468,7 @@ ar5212Attach(uint16_t devid, HAL_SOFTC sc, goto bad; #endif } - if (!IS_5413(ah) && IS_5112(ah) && IS_RAD5112_REV1(ah)) { + if (IS_RAD5112_REV1(ah)) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: 5112 Rev 1 is not supported by this " "driver (analog5GhzRev 0x%x)\n", __func__, @@ -565,7 +568,7 @@ ar5212Attach(uint16_t devid, HAL_SOFTC sc, #else ecode = HAL_ENOTSUPP; #endif - else if (IS_5112(ah)) + else if (IS_RAD5112(ah)) #ifdef AH_SUPPORT_5112 rfStatus = ar5112RfAttach(ah, &ecode); #else @@ -577,7 +580,7 @@ ar5212Attach(uint16_t devid, HAL_SOFTC sc, #else ecode = HAL_ENOTSUPP; #endif - else + else if (IS_RAD5111(ah)) #ifdef AH_SUPPORT_5111 rfStatus = ar5111RfAttach(ah, &ecode); #else @@ -788,7 +791,8 @@ ar5212FillCapabilityInfo(struct ath_hal *ah) } pCap->halLow2GhzChan = 2312; - if (IS_5112(ah) || IS_2413(ah) || IS_5413(ah) || IS_2425(ah)) + /* XXX 2417 too? */ + if (IS_RAD5112_ANY(ah) || IS_5413(ah) || IS_2425(ah) || IS_2417(ah)) pCap->halHigh2GhzChan = 2500; else pCap->halHigh2GhzChan = 2732; @@ -850,14 +854,8 @@ ar5212FillCapabilityInfo(struct ath_hal *ah) else pCap->halKeyCacheSize = AR_KEYTABLE_SIZE; - if (IS_5112(ah)) { - pCap->halChanHalfRate = AH_TRUE; - pCap->halChanQuarterRate = AH_TRUE; - } else { - /* XXX not needed */ - pCap->halChanHalfRate = AH_FALSE; - pCap->halChanQuarterRate = AH_FALSE; - } + pCap->halChanHalfRate = AH_TRUE; + pCap->halChanQuarterRate = 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/ar5212/ar5212_interrupts.c b/ar5212/ar5212_interrupts.c index 8383645b5f04..6e636dbe71d2 100644 --- a/ar5212/ar5212_interrupts.c +++ b/ar5212/ar5212_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: ar5212_interrupts.c,v 1.5 2008/11/10 04:08:03 sam Exp $ + * $Id: ar5212_interrupts.c,v 1.6 2008/11/27 22:30:00 sam Exp $ */ #include "opt_ah.h" @@ -96,7 +96,9 @@ ar5212GetPendingInterrupts(struct ath_hal *ah, HAL_INT *masked) } /* - * RXORN can hang the receive path so we force a hardware + * Receive overrun is usually non-fatal on Oahu/Spirit. + * BUT on some parts rx could fail and the chip must be reset. + * So we force a hardware reset in all cases. */ if ((isr & AR_ISR_RXORN) && AH_PRIVATE(ah)->ah_rxornIsFatal) { HALDEBUG(ah, HAL_DEBUG_ANY, diff --git a/ar5212/ar5212_misc.c b/ar5212/ar5212_misc.c index 5f01104bf684..f55b7f26932d 100644 --- a/ar5212/ar5212_misc.c +++ b/ar5212/ar5212_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: ar5212_misc.c,v 1.8 2008/11/10 04:08:03 sam Exp $ + * $Id: ar5212_misc.c,v 1.12 2008/11/27 22:30:00 sam Exp $ */ #include "opt_ah.h" @@ -79,12 +79,44 @@ ar5212SetBssIdMask(struct ath_hal *ah, const uint8_t *mask) return AH_TRUE; } +/* + * Attempt to change the cards operating regulatory domain to the given value + */ +HAL_BOOL +ar5212SetRegulatoryDomain(struct ath_hal *ah, + uint16_t regDomain, HAL_STATUS *status) +{ + HAL_STATUS ecode; + + if (AH_PRIVATE(ah)->ah_currentRD == regDomain) { + ecode = HAL_EINVAL; + goto bad; + } + if (ath_hal_eepromGetFlag(ah, AR_EEP_WRITEPROTECT)) { + ecode = HAL_EEWRITE; + goto bad; + } +#ifdef AH_SUPPORT_WRITE_REGDOMAIN + if (ath_hal_eepromWrite(ah, AR_EEPROM_REG_DOMAIN, regDomain)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: set regulatory domain to %u (0x%x)\n", + __func__, regDomain, regDomain); + AH_PRIVATE(ah)->ah_currentRD = regDomain; + return AH_TRUE; + } +#endif + ecode = HAL_EIO; +bad: + if (status) + *status = ecode; + return AH_FALSE; +} + /* * Return the wireless modes (a,b,g,t) supported by hardware. * * This value is what is actually supported by the hardware * and is unaffected by regulatory/country code settings. - * */ u_int ar5212GetWirelessModes(struct ath_hal *ah) @@ -95,6 +127,10 @@ ar5212GetWirelessModes(struct ath_hal *ah) mode = HAL_MODE_11A; if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO5DISABLE)) mode |= HAL_MODE_TURBO | HAL_MODE_108A; + if (AH_PRIVATE(ah)->ah_caps.halChanHalfRate) + mode |= HAL_MODE_11A_HALF_RATE; + if (AH_PRIVATE(ah)->ah_caps.halChanQuarterRate) + mode |= HAL_MODE_11A_QUARTER_RATE; } if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE)) mode |= HAL_MODE_11B; @@ -103,6 +139,10 @@ ar5212GetWirelessModes(struct ath_hal *ah) mode |= HAL_MODE_11G; if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO2DISABLE)) mode |= HAL_MODE_108G; + if (AH_PRIVATE(ah)->ah_caps.halChanHalfRate) + mode |= HAL_MODE_11G_HALF_RATE; + if (AH_PRIVATE(ah)->ah_caps.halChanQuarterRate) + mode |= HAL_MODE_11G_QUARTER_RATE; } return mode; } @@ -212,11 +252,10 @@ ar5212GetTsf64(struct ath_hal *ah) * 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. + * 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++; } @@ -382,19 +421,22 @@ ar5212SetDefAntenna(struct ath_hal *ah, u_int antenna) HAL_ANT_SETTING ar5212GetAntennaSwitch(struct ath_hal *ah) { - return AH5212(ah)->ah_diversityControl; + return AH5212(ah)->ah_antControl; } HAL_BOOL -ar5212SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings) +ar5212SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING setting) { - const HAL_CHANNEL_INTERNAL *chan = AH_PRIVATE(ah)->ah_curchan; + struct ath_hal_5212 *ahp = AH5212(ah); + const HAL_CHANNEL_INTERNAL *ichan = AH_PRIVATE(ah)->ah_curchan; - if (chan == AH_NULL) { - AH5212(ah)->ah_diversityControl = settings; + if (!ahp->ah_phyPowerOn || ichan == AH_NULL) { + /* PHY powered off, just stash settings */ + ahp->ah_antControl = setting; + ahp->ah_diversity = (setting == HAL_ANT_VARIABLE); return AH_TRUE; } - return ar5212SetAntennaSwitchInternal(ah, settings, chan); + return ar5212SetAntennaSwitchInternal(ah, setting, ichan); } HAL_BOOL @@ -632,7 +674,8 @@ ar5212SetupClock(struct ath_hal *ah, HAL_OPMODE opmode) * from A2. */ OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f); - OS_REG_WRITE(ah, AR_PHY_REFCLKPD, IS_5112(ah) ? 0x14 : 0x18); + OS_REG_WRITE(ah, AR_PHY_REFCLKPD, + IS_RAD5112_ANY(ah) || IS_5413(ah) ? 0x14 : 0x18); OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32, 1); OS_REG_WRITE(ah, AR_TSF_PARM, 61); /* 32 KHz TSF incr */ OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_SEL, 1); @@ -669,8 +712,9 @@ ar5212SetupClock(struct ath_hal *ah, HAL_OPMODE opmode) OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x0c); OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0xff); OS_REG_WRITE(ah, AR_PHY_REFCLKPD, - IS_5112(ah) || IS_2417(ah) ? 0x14 : 0x18); - OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32, IS_5112(ah) ? 39 : 31); + IS_RAD5112_ANY(ah) || IS_5413(ah) || IS_2417(ah) ? 0x14 : 0x18); + OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32, + IS_RAD5112_ANY(ah) || IS_5413(ah) ? 39 : 31); } } @@ -686,7 +730,8 @@ ar5212RestoreClock(struct ath_hal *ah, HAL_OPMODE opmode) OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_SEL, 0); OS_REG_WRITE(ah, AR_TSF_PARM, 1); /* 32 MHz TSF incr */ - OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32, IS_5112(ah) ? 39 : 31); + OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32, + IS_RAD5112_ANY(ah) || IS_5413(ah) ? 39 : 31); /* * Restore BB registers to power-on defaults @@ -696,7 +741,8 @@ ar5212RestoreClock(struct ath_hal *ah, HAL_OPMODE opmode) OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e); OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x0c); OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0xff); - OS_REG_WRITE(ah, AR_PHY_REFCLKPD, IS_5112(ah) ? 0x14 : 0x18); + OS_REG_WRITE(ah, AR_PHY_REFCLKPD, + IS_RAD5112_ANY(ah) || IS_5413(ah) ? 0x14 : 0x18); } } @@ -782,9 +828,7 @@ ar5212GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, case 0: /* hardware capability */ return HAL_OK; case 1: /* current setting */ - return (OS_REG_READ(ah, AR_PHY_CCK_DETECT) & - AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV) ? - HAL_OK : HAL_ENXIO; + return ahp->ah_diversity ? HAL_OK : HAL_ENXIO; } return HAL_EINVAL; case HAL_CAP_DIAG: @@ -892,12 +936,15 @@ ar5212SetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode); return AH_TRUE; case HAL_CAP_DIVERSITY: - v = OS_REG_READ(ah, AR_PHY_CCK_DETECT); - if (setting) - v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; - else - v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; - OS_REG_WRITE(ah, AR_PHY_CCK_DETECT, v); + if (ahp->ah_phyPowerOn) { + v = OS_REG_READ(ah, AR_PHY_CCK_DETECT); + if (setting) + v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; + else + v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; + OS_REG_WRITE(ah, AR_PHY_CCK_DETECT, v); + } + ahp->ah_diversity = (setting != 0); return AH_TRUE; case HAL_CAP_DIAG: /* hardware diagnostic support */ /* diff --git a/ar5212/ar5212_phy.c b/ar5212/ar5212_phy.c index 48469ada86ad..ae238f7541ce 100644 --- a/ar5212/ar5212_phy.c +++ b/ar5212/ar5212_phy.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_phy.c,v 1.4 2008/11/10 01:19:38 sam Exp $ + * $Id: ar5212_phy.c,v 1.5 2008/11/15 03:43:53 sam Exp $ */ #include "opt_ah.h" @@ -47,7 +47,7 @@ HAL_RATE_TABLE ar5212_11a_table = { }, }; -HAL_RATE_TABLE ar5212_11a_half_table = { +HAL_RATE_TABLE ar5212_half_table = { 8, /* number of rates */ { 0 }, { @@ -64,7 +64,7 @@ HAL_RATE_TABLE ar5212_11a_half_table = { }, }; -HAL_RATE_TABLE ar5212_11a_quarter_table = { +HAL_RATE_TABLE ar5212_quarter_table = { 8, /* number of rates */ { 0 }, { @@ -184,10 +184,12 @@ ar5212GetRateTable(struct ath_hal *ah, u_int mode) rt = &ar5212_turbog_table; break; case HAL_MODE_11A_HALF_RATE: - rt = &ar5212_11a_half_table; + case HAL_MODE_11G_HALF_RATE: + rt = &ar5212_half_table; break; case HAL_MODE_11A_QUARTER_RATE: - rt = &ar5212_11a_quarter_table; + case HAL_MODE_11G_QUARTER_RATE: + rt = &ar5212_quarter_table; break; default: HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid mode 0x%x\n", diff --git a/ar5212/ar5212_reset.c b/ar5212/ar5212_reset.c index 11bf2d2db0bb..ee87d5b1265f 100644 --- a/ar5212/ar5212_reset.c +++ b/ar5212/ar5212_reset.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_reset.c,v 1.12 2008/11/10 04:08:03 sam Exp $ + * $Id: ar5212_reset.c,v 1.20 2008/11/27 22:30:00 sam Exp $ */ #include "opt_ah.h" @@ -47,32 +47,23 @@ void ar5212SetDeltaSlope(struct ath_hal *, HAL_CHANNEL *); HAL_BOOL ar5212SetTransmitPower(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan, uint16_t *rfXpdGain); static HAL_BOOL ar5212SetRateTable(struct ath_hal *, - HAL_CHANNEL *, int16_t tpcScaleReduction, int16_t powerLimit, - HAL_BOOL commit, - int16_t *minPower, int16_t *maxPower); + HAL_CHANNEL *, int16_t tpcScaleReduction, int16_t powerLimit, + HAL_BOOL commit, int16_t *minPower, int16_t *maxPower); static void ar5212CorrectGainDelta(struct ath_hal *, int twiceOfdmCckDelta); static void ar5212GetTargetPowers(struct ath_hal *, HAL_CHANNEL *, - const TRGT_POWER_INFO *pPowerInfo, uint16_t numChannels, - TRGT_POWER_INFO *pNewPower); + const TRGT_POWER_INFO *pPowerInfo, uint16_t numChannels, + TRGT_POWER_INFO *pNewPower); static uint16_t ar5212GetMaxEdgePower(uint16_t channel, - const RD_EDGES_POWER *pRdEdgesPower); -static void ar5212RequestRfgain(struct ath_hal *); -static HAL_BOOL ar5212InvalidGainReadback(struct ath_hal *, GAIN_VALUES *); -static HAL_BOOL ar5212IsGainAdjustNeeded(struct ath_hal *, const GAIN_VALUES *); -static int32_t ar5212AdjustGain(struct ath_hal *, GAIN_VALUES *); + const RD_EDGES_POWER *pRdEdgesPower); void ar5212SetRateDurationTable(struct ath_hal *, HAL_CHANNEL *); -static uint32_t ar5212GetRfField(uint32_t *rfBuf, uint32_t numBits, - uint32_t firstBit, uint32_t column); -static void ar5212GetGainFCorrection(struct ath_hal *ah); -HAL_BOOL ar5212SetXrMode(struct ath_hal *ah, HAL_OPMODE opmode,HAL_CHANNEL *chan); -void ar5212SetIFSTiming(struct ath_hal *, HAL_CHANNEL *); +void ar5212SetIFSTiming(struct ath_hal *, HAL_CHANNEL *); /* NB: public for RF backend use */ -void ar5212GetLowerUpperValues(uint16_t value, - uint16_t *pList, uint16_t listSize, - uint16_t *pLowerValue, uint16_t *pUpperValue); -void ar5212ModifyRfBuffer(uint32_t *rfBuf, uint32_t reg32, - uint32_t numBits, uint32_t firstBit, uint32_t column); +void ar5212GetLowerUpperValues(uint16_t value, + uint16_t *pList, uint16_t listSize, + uint16_t *pLowerValue, uint16_t *pUpperValue); +void ar5212ModifyRfBuffer(uint32_t *rfBuf, uint32_t reg32, + uint32_t numBits, uint32_t firstBit, uint32_t column); static int write_common(struct ath_hal *ah, const HAL_INI_ARRAY *ia, @@ -463,8 +454,9 @@ ar5212Reset(struct ath_hal *ah, HAL_OPMODE opmode, ar5212SetRateDurationTable(ah, chan); /* Set Tx frame start to tx data start delay */ - if (IS_5112(ah) && (IS_CHAN_HALF_RATE(AH_PRIVATE(ah)->ah_curchan) || - IS_CHAN_QUARTER_RATE(AH_PRIVATE(ah)->ah_curchan))) { + if (IS_RAD5112_ANY(ah) && + (IS_CHAN_HALF_RATE(AH_PRIVATE(ah)->ah_curchan) || + IS_CHAN_QUARTER_RATE(AH_PRIVATE(ah)->ah_curchan))) { txFrm2TxDStart = (IS_CHAN_HALF_RATE(AH_PRIVATE(ah)->ah_curchan)) ? TX_FRAME_D_START_HALF_RATE: @@ -906,7 +898,7 @@ ar5212ChipReset(struct ath_hal *ah, HAL_CHANNEL *chan) if (chan != AH_NULL) { /* NB: can be null during attach */ uint32_t rfMode, phyPLL = 0, curPhyPLL, turbo; - if (IS_5413(ah)) { + if (IS_5413(ah)) { /* NB: =>'s 5424 also */ rfMode = AR_PHY_MODE_AR5112; if (IS_CHAN_HALF_RATE(chan)) rfMode |= AR_PHY_MODE_HALF; @@ -917,33 +909,26 @@ ar5212ChipReset(struct ath_hal *ah, HAL_CHANNEL *chan) phyPLL = AR_PHY_PLL_CTL_44_5112; else phyPLL = AR_PHY_PLL_CTL_40_5413; - } - else if (IS_5112(ah) || IS_2413(ah) || IS_2425(ah) || IS_2417(ah)) { - rfMode = AR_PHY_MODE_AR5112; - if (IS_CHAN_CCK(chan) || IS_CHAN_G(chan)) { - phyPLL = AR_PHY_PLL_CTL_44_5112; - } else { - if (IS_CHAN_HALF_RATE(chan)) { - phyPLL = AR_PHY_PLL_CTL_40_5112_HALF; - } else if (IS_CHAN_QUARTER_RATE(chan)) { - phyPLL = AR_PHY_PLL_CTL_40_5112_QUARTER; - } else { - phyPLL = AR_PHY_PLL_CTL_40_5112; - } - } - } else { + } else if (IS_RAD5111(ah)) { rfMode = AR_PHY_MODE_AR5111; - if (IS_CHAN_CCK(chan) || IS_CHAN_G(chan)) { + if (IS_CHAN_CCK(chan) || IS_CHAN_G(chan)) phyPLL = AR_PHY_PLL_CTL_44; - } else { - if (IS_CHAN_HALF_RATE(chan)) { - phyPLL = AR_PHY_PLL_CTL_40_HALF; - } else if (IS_CHAN_QUARTER_RATE(chan)) { - phyPLL = AR_PHY_PLL_CTL_40_QUARTER; - } else { - phyPLL = AR_PHY_PLL_CTL_40; - } - } + else + phyPLL = AR_PHY_PLL_CTL_40; + if (IS_CHAN_HALF_RATE(chan)) + phyPLL = AR_PHY_PLL_CTL_HALF; + else if (IS_CHAN_QUARTER_RATE(chan)) + phyPLL = AR_PHY_PLL_CTL_QUARTER; + } else { /* 5112, 2413, 2316, 2317 */ + rfMode = AR_PHY_MODE_AR5112; + if (IS_CHAN_CCK(chan) || IS_CHAN_G(chan)) + phyPLL = AR_PHY_PLL_CTL_44_5112; + else + phyPLL = AR_PHY_PLL_CTL_40_5112; + if (IS_CHAN_HALF_RATE(chan)) + phyPLL |= AR_PHY_PLL_CTL_HALF; + else if (IS_CHAN_QUARTER_RATE(chan)) + phyPLL |= AR_PHY_PLL_CTL_QUARTER; } if (IS_CHAN_OFDM(chan) && (IS_CHAN_CCK(chan) || IS_CHAN_G(chan))) @@ -992,7 +977,8 @@ ar5212ChipReset(struct ath_hal *ah, HAL_CHANNEL *chan) * changes. */ HAL_BOOL -ar5212PerCalibration(struct ath_hal *ah, HAL_CHANNEL *chan, HAL_BOOL *isIQdone) +ar5212PerCalibrationN(struct ath_hal *ah, HAL_CHANNEL *chan, u_int chainMask, + HAL_BOOL longCal, HAL_BOOL *isCalDone) { #define IQ_CAL_TRIES 10 struct ath_hal_5212 *ahp = AH5212(ah); @@ -1004,7 +990,7 @@ ar5212PerCalibration(struct ath_hal *ah, HAL_CHANNEL *chan, HAL_BOOL *isIQdone) HAL_BOOL isBmode = AH_FALSE; OS_MARK(ah, AH_MARK_PERCAL, chan->channel); - *isIQdone = AH_FALSE; + *isCalDone = AH_FALSE; ichan = ath_hal_checkchannel(ah, chan); if (ichan == AH_NULL) { HALDEBUG(ah, HAL_DEBUG_ANY, @@ -1015,10 +1001,9 @@ ar5212PerCalibration(struct ath_hal *ah, HAL_CHANNEL *chan, HAL_BOOL *isIQdone) SAVE_CCK(ah, ichan, ichan_isBmode); SAVE_CCK(ah, chan, isBmode); - /* XXX EAR */ - if ((ahp->ah_bIQCalibration == IQ_CAL_DONE) || - (ahp->ah_bIQCalibration == IQ_CAL_INACTIVE)) - *isIQdone = AH_TRUE; + if (ahp->ah_bIQCalibration == IQ_CAL_DONE || + ahp->ah_bIQCalibration == IQ_CAL_INACTIVE) + *isCalDone = AH_TRUE; /* IQ calibration in progress. Check to see if it has finished. */ if (ahp->ah_bIQCalibration == IQ_CAL_RUNNING && @@ -1027,7 +1012,7 @@ ar5212PerCalibration(struct ath_hal *ah, HAL_CHANNEL *chan, HAL_BOOL *isIQdone) /* IQ Calibration has finished. */ ahp->ah_bIQCalibration = IQ_CAL_INACTIVE; - *isIQdone = AH_TRUE; + *isCalDone = AH_TRUE; /* workaround for misgated IQ Cal results */ i = 0; @@ -1097,9 +1082,8 @@ ar5212PerCalibration(struct ath_hal *ah, HAL_CHANNEL *chan, HAL_BOOL *isIQdone) ichan->iCoff = iCoff; ichan->qCoff = qCoff; } - } else if (!IS_CHAN_B(chan) && - ahp->ah_bIQCalibration == IQ_CAL_DONE && - !ichan->iqCalValid) { + } else if (!IS_CHAN_B(chan) && ahp->ah_bIQCalibration == IQ_CAL_DONE && + !ichan->iqCalValid) { /* * Start IQ calibration if configured channel has changed. * Use a magic number of 15 based on default value. @@ -1113,22 +1097,21 @@ ar5212PerCalibration(struct ath_hal *ah, HAL_CHANNEL *chan, HAL_BOOL *isIQdone) } /* XXX EAR */ - /* Check noise floor results */ - ar5212GetNf(ah, ichan); - if ((ichan->channelFlags & CHANNEL_CW_INT) == 0) { - /* Perform calibration for 5Ghz channels and any OFDM on 5112 */ - if ((IS_CHAN_5GHZ(chan) || - (IS_5112(ah) && IS_CHAN_OFDM(chan))) && - !(IS_2413(ah) || IS_5413(ah) || IS_2417(ah))) - ar5212RequestRfgain(ah); + if (longCal) { + /* Check noise floor results */ + ar5212GetNf(ah, ichan); - /* XXX EAR */ - } else { - /* report up and clear internal state */ - chan->channelFlags |= CHANNEL_CW_INT; - ichan->channelFlags &= ~CHANNEL_CW_INT; + if ((ichan->channelFlags & CHANNEL_CW_INT) == 0) { + /* Perform cal for 5Ghz channels and any OFDM on 5112 */ + if (IS_CHAN_5GHZ(chan) || + (IS_RAD5112(ah) && IS_CHAN_OFDM(chan))) + ar5212RequestRfgain(ah); + } else { + /* report up and clear internal state */ + chan->channelFlags |= CHANNEL_CW_INT; + ichan->channelFlags &= ~CHANNEL_CW_INT; + } } - RESTORE_CCK(ah, ichan, ichan_isBmode); RESTORE_CCK(ah, chan, isBmode); @@ -1136,6 +1119,19 @@ ar5212PerCalibration(struct ath_hal *ah, HAL_CHANNEL *chan, HAL_BOOL *isIQdone) #undef IQ_CAL_TRIES } +HAL_BOOL +ar5212PerCalibration(struct ath_hal *ah, HAL_CHANNEL *chan, HAL_BOOL *isIQdone) +{ + return ar5212PerCalibrationN(ah, chan, 0x1, AH_TRUE, isIQdone); +} + +HAL_BOOL +ar5212ResetCalValid(struct ath_hal *ah, HAL_CHANNEL *chan) +{ + /* XXX */ + return AH_TRUE; +} + /* * Write the given reset bit mask into the reset register */ @@ -1174,6 +1170,9 @@ ar5212SetResetReg(struct ath_hal *ah, uint32_t resetMask) if (ar5212SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) (void) OS_REG_READ(ah, AR_ISR_RAC); } + + /* track PHY power state so we don't try to r/w BB registers */ + AH5212(ah)->ah_phyPowerOn = ((resetMask & AR_RC_BB) == 0); return rt; } @@ -1383,42 +1382,6 @@ ar5212SetCompRegs(struct ath_hal *ah) } } -#define MAX_ANALOG_START 319 /* XXX */ - -/* - * Find analog bits of given parameter data and return a reversed value - */ -static uint32_t -ar5212GetRfField(uint32_t *rfBuf, uint32_t numBits, uint32_t firstBit, uint32_t column) -{ - uint32_t reg32 = 0, mask, arrayEntry, lastBit; - uint32_t bitPosition, bitsShifted; - int32_t bitsLeft; - - HALASSERT(column <= 3); - HALASSERT(numBits <= 32); - HALASSERT(firstBit + numBits <= MAX_ANALOG_START); - - arrayEntry = (firstBit - 1) / 8; - bitPosition = (firstBit - 1) % 8; - bitsLeft = numBits; - bitsShifted = 0; - while (bitsLeft > 0) { - lastBit = (bitPosition + bitsLeft > 8) ? - (8) : (bitPosition + bitsLeft); - mask = (((1 << lastBit) - 1) ^ ((1 << bitPosition) - 1)) << - (column * 8); - reg32 |= (((rfBuf[arrayEntry] & mask) >> (column * 8)) >> - bitPosition) << bitsShifted; - bitsShifted += lastBit - bitPosition; - bitsLeft -= (8 - bitPosition); - bitPosition = 0; - arrayEntry++; - } - reg32 = ath_hal_reverseBits(reg32, numBits); - return reg32; -} - HAL_BOOL ar5212SetAntennaSwitchInternal(struct ath_hal *ah, HAL_ANT_SETTING settings, const HAL_CHANNEL_INTERNAL *chan) @@ -1434,6 +1397,7 @@ ar5212SetAntennaSwitchInternal(struct ath_hal *ah, HAL_ANT_SETTING settings, HAL_CHANNEL_INTERNAL ichan = *chan; HALASSERT(ah->ah_magic == AR5212_MAGIC); + HALASSERT(ahp->ah_phyPowerOn); SAVE_CCK(ah, &ichan, isBmode); switch (ichan.channelFlags & CHANNEL_ALL_NOTURBO) { @@ -1482,13 +1446,15 @@ ar5212SetAntennaSwitchInternal(struct ath_hal *ah, HAL_ANT_SETTING settings, "%s: Setting fast diversity off.\n", __func__); OS_REG_CLR_BIT(ah,AR_PHY_CCK_DETECT, AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV); + ahp->ah_diversity = AH_FALSE; } else { HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: Setting fast diversity on.\n", __func__); OS_REG_SET_BIT(ah,AR_PHY_CCK_DETECT, AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV); + ahp->ah_diversity = AH_TRUE; } - ahp->ah_diversityControl = settings; + ahp->ah_antControl = settings; OS_REG_WRITE(ah, ANT_SWITCH_TABLE1, antSwitchA); OS_REG_WRITE(ah, ANT_SWITCH_TABLE2, antSwitchB); @@ -1502,7 +1468,7 @@ HAL_BOOL ar5212IsSpurChannel(struct ath_hal *ah, HAL_CHANNEL *chan) { uint32_t clockFreq = - ((IS_5413(ah) || IS_2413(ah) || IS_5112(ah) || IS_2417(ah)) ? 40 : 32); + ((IS_5413(ah) || IS_RAD5112_ANY(ah) || IS_2417(ah)) ? 40 : 32); return ( ((chan->channel % clockFreq) != 0) && (((chan->channel % clockFreq) < 10) || (((chan->channel) % clockFreq) > 22)) ); @@ -1534,7 +1500,7 @@ ar5212SetBoardValues(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan) case CHANNEL_A: case CHANNEL_T: arrayMode = headerInfo11A; - if (!IS_5112(ah) && !IS_2413(ah) && !IS_5413(ah)) + if (!IS_RAD5112_ANY(ah) && !IS_2413(ah) && !IS_5413(ah)) OS_REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_TX_CLIP, ahp->ah_gainValues.currStep->paramVal[GP_TXCLIP]); @@ -1556,7 +1522,7 @@ ar5212SetBoardValues(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan) AR_PHY_BIS(ah, 68, 0xFFFFFC06, (ee->ee_antennaControl[0][arrayMode] << 4) | 0x1); - ar5212SetAntennaSwitchInternal(ah, ahp->ah_diversityControl, chan); + ar5212SetAntennaSwitchInternal(ah, ahp->ah_antControl, chan); /* Set the Noise Floor Thresh on ar5211 devices */ OS_REG_WRITE(ah, AR_PHY(90), @@ -2566,278 +2532,16 @@ ar5212GetLowerUpperValues(uint16_t v, uint16_t *lp, uint16_t listSize, HALASSERT(AH_FALSE); /* should not reach here */ } -static const GAIN_OPTIMIZATION_LADDER gainLadder = { - 9, /* numStepsInLadder */ - 4, /* defaultStepNum */ - { { {4, 1, 1, 1}, 6, "FG8"}, - { {4, 0, 1, 1}, 4, "FG7"}, - { {3, 1, 1, 1}, 3, "FG6"}, - { {4, 0, 0, 1}, 1, "FG5"}, - { {4, 1, 1, 0}, 0, "FG4"}, /* noJack */ - { {4, 0, 1, 0}, -2, "FG3"}, /* halfJack */ - { {3, 1, 1, 0}, -3, "FG2"}, /* clip3 */ - { {4, 0, 0, 0}, -4, "FG1"}, /* noJack */ - { {2, 1, 1, 0}, -6, "FG0"} /* clip2 */ - } -}; - -const static GAIN_OPTIMIZATION_LADDER gainLadder5112 = { - 8, /* numStepsInLadder */ - 1, /* defaultStepNum */ - { { {3, 0,0,0, 0,0,0}, 6, "FG7"}, /* most fixed gain */ - { {2, 0,0,0, 0,0,0}, 0, "FG6"}, - { {1, 0,0,0, 0,0,0}, -3, "FG5"}, - { {0, 0,0,0, 0,0,0}, -6, "FG4"}, - { {0, 1,1,0, 0,0,0}, -8, "FG3"}, - { {0, 1,1,0, 1,1,0}, -10, "FG2"}, - { {0, 1,0,1, 1,1,0}, -13, "FG1"}, - { {0, 1,0,1, 1,0,1}, -16, "FG0"}, /* least fixed gain */ - } -}; - -/* - * Initialize the gain structure to good values - */ -void -ar5212InitializeGainValues(struct ath_hal *ah) -{ - struct ath_hal_5212 *ahp = AH5212(ah); - GAIN_VALUES *gv = &ahp->ah_gainValues; - - /* initialize gain optimization values */ - if (IS_5112(ah)) { - gv->currStepNum = gainLadder5112.defaultStepNum; - gv->currStep = - &gainLadder5112.optStep[gainLadder5112.defaultStepNum]; - gv->active = AH_TRUE; - gv->loTrig = 20; - gv->hiTrig = 85; - } else { - gv->currStepNum = gainLadder.defaultStepNum; - gv->currStep = &gainLadder.optStep[gainLadder.defaultStepNum]; - gv->active = AH_TRUE; - gv->loTrig = 20; - gv->hiTrig = 35; - } -} - -static HAL_BOOL -ar5212InvalidGainReadback(struct ath_hal *ah, GAIN_VALUES *gv) -{ - uint32_t gStep, g, mixOvr; - uint32_t L1, L2, L3, L4; - - if (IS_5112(ah)) { - mixOvr = ar5212GetRfField(ar5212GetRfBank(ah, 7), 1, 36, 0); - L1 = 0; - L2 = 107; - L3 = 0; - L4 = 107; - if (mixOvr == 1) { - L2 = 83; - L4 = 83; - gv->hiTrig = 55; - } - } else { - gStep = ar5212GetRfField(ar5212GetRfBank(ah, 7), 6, 37, 0); - - L1 = 0; - L2 = (gStep == 0x3f) ? 50 : gStep + 4; - L3 = (gStep != 0x3f) ? 0x40 : L1; - L4 = L3 + 50; - - gv->loTrig = L1 + (gStep == 0x3f ? DYN_ADJ_LO_MARGIN : 0); - /* never adjust if != 0x3f */ - gv->hiTrig = L4 - (gStep == 0x3f ? DYN_ADJ_UP_MARGIN : -5); - } - g = gv->currGain; - - return !((g >= L1 && g<= L2) || (g >= L3 && g <= L4)); -} - -/* - * Enable the probe gain check on the next packet - */ -static void -ar5212RequestRfgain(struct ath_hal *ah) -{ - struct ath_hal_5212 *ahp = AH5212(ah); - uint32_t probePowerIndex; - - /* Enable the gain readback probe */ - probePowerIndex = ahp->ah_ofdmTxPower + ahp->ah_txPowerIndexOffset; - OS_REG_WRITE(ah, AR_PHY_PAPD_PROBE, - SM(probePowerIndex, AR_PHY_PAPD_PROBE_POWERTX) - | AR_PHY_PAPD_PROBE_NEXT_TX); - - ahp->ah_rfgainState = HAL_RFGAIN_READ_REQUESTED; -} - -/* - * Exported call to check for a recent gain reading and return - * the current state of the thermal calibration gain engine. - */ -HAL_RFGAIN -ar5212GetRfgain(struct ath_hal *ah) -{ - struct ath_hal_5212 *ahp = AH5212(ah); - GAIN_VALUES *gv = &ahp->ah_gainValues; - uint32_t rddata, probeType; - - if (!gv->active) - return HAL_RFGAIN_INACTIVE; - - if (ahp->ah_rfgainState == HAL_RFGAIN_READ_REQUESTED) { - /* Caller had asked to setup a new reading. Check it. */ - rddata = OS_REG_READ(ah, AR_PHY_PAPD_PROBE); - - if ((rddata & AR_PHY_PAPD_PROBE_NEXT_TX) == 0) { - /* bit got cleared, we have a new reading. */ - gv->currGain = rddata >> AR_PHY_PAPD_PROBE_GAINF_S; - probeType = MS(rddata, AR_PHY_PAPD_PROBE_TYPE); - if (probeType == AR_PHY_PAPD_PROBE_TYPE_CCK) { - const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; - - HALASSERT(IS_5112(ah)); - HALASSERT(ah->ah_magic == AR5212_MAGIC); - if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_2) - gv->currGain += ee->ee_cckOfdmGainDelta; - else - gv->currGain += PHY_PROBE_CCK_CORRECTION; - } - if (IS_5112(ah)) { - ar5212GetGainFCorrection(ah); - if (gv->currGain >= gv->gainFCorrection) - gv->currGain -= gv->gainFCorrection; - else - gv->currGain = 0; - } - /* inactive by default */ - ahp->ah_rfgainState = HAL_RFGAIN_INACTIVE; - - if (!ar5212InvalidGainReadback(ah, gv) && - ar5212IsGainAdjustNeeded(ah, gv) && - ar5212AdjustGain(ah, gv) > 0) { - /* - * Change needed. Copy ladder info - * into eeprom info. - */ - ahp->ah_rfgainState = HAL_RFGAIN_NEED_CHANGE; - /* for ap51 */ - ahp->ah_cwCalRequire = AH_TRUE; - /* Request IQ recalibration for temperature chang */ - ahp->ah_bIQCalibration = IQ_CAL_INACTIVE; - } - } - } - return ahp->ah_rfgainState; -} - -/* - * Check to see if our readback gain level sits within the linear - * region of our current variable attenuation window - */ -static HAL_BOOL -ar5212IsGainAdjustNeeded(struct ath_hal *ah, const GAIN_VALUES *gv) -{ - return (gv->currGain <= gv->loTrig || gv->currGain >= gv->hiTrig); -} - -/* - * Move the rabbit ears in the correct direction. - */ -static int32_t -ar5212AdjustGain(struct ath_hal *ah, GAIN_VALUES *gv) -{ - const GAIN_OPTIMIZATION_LADDER *gl; - - if (IS_5112(ah)) - gl = &gainLadder5112; - else - gl = &gainLadder; - gv->currStep = &gl->optStep[gv->currStepNum]; - if (gv->currGain >= gv->hiTrig) { - if (gv->currStepNum == 0) { - HALDEBUG(ah, HAL_DEBUG_ANY, "%s: Max gain limit.\n", - __func__); - return -1; - } - HALDEBUG(ah, HAL_DEBUG_RFPARAM, - "%s: Adding gain: currG=%d [%s] --> ", - __func__, gv->currGain, gv->currStep->stepName); - gv->targetGain = gv->currGain; - while (gv->targetGain >= gv->hiTrig && gv->currStepNum > 0) { - gv->targetGain -= 2 * (gl->optStep[--(gv->currStepNum)].stepGain - - gv->currStep->stepGain); - gv->currStep = &gl->optStep[gv->currStepNum]; - } - HALDEBUG(ah, HAL_DEBUG_RFPARAM, "targG=%d [%s]\n", - gv->targetGain, gv->currStep->stepName); - return 1; - } - if (gv->currGain <= gv->loTrig) { - if (gv->currStepNum == gl->numStepsInLadder-1) { - HALDEBUG(ah, HAL_DEBUG_RFPARAM, - "%s: Min gain limit.\n", __func__); - return -2; - } - HALDEBUG(ah, HAL_DEBUG_RFPARAM, - "%s: Deducting gain: currG=%d [%s] --> ", - __func__, gv->currGain, gv->currStep->stepName); - gv->targetGain = gv->currGain; - while (gv->targetGain <= gv->loTrig && - gv->currStepNum < (gl->numStepsInLadder - 1)) { - gv->targetGain -= 2 * - (gl->optStep[++(gv->currStepNum)].stepGain - gv->currStep->stepGain); - gv->currStep = &gl->optStep[gv->currStepNum]; - } - HALDEBUG(ah, HAL_DEBUG_RFPARAM, "targG=%d [%s]\n", - gv->targetGain, gv->currStep->stepName); - return 2; - } - return 0; /* caller didn't call needAdjGain first */ -} - -/* - * Read rf register to determine if gainF needs correction - */ -static void -ar5212GetGainFCorrection(struct ath_hal *ah) -{ - struct ath_hal_5212 *ahp = AH5212(ah); - GAIN_VALUES *gv = &ahp->ah_gainValues; - - HALASSERT(IS_RADX112_REV2(ah)); - - gv->gainFCorrection = 0; - if (ar5212GetRfField(ar5212GetRfBank(ah, 7), 1, 36, 0) == 1) { - uint32_t mixGain = gv->currStep->paramVal[0]; - uint32_t gainStep = - ar5212GetRfField(ar5212GetRfBank(ah, 7), 4, 32, 0); - switch (mixGain) { - case 0 : - gv->gainFCorrection = 0; - break; - case 1 : - gv->gainFCorrection = gainStep; - break; - case 2 : - gv->gainFCorrection = 2 * gainStep - 5; - break; - case 3 : - gv->gainFCorrection = 2 * gainStep; - break; - } - } -} - /* * Perform analog "swizzling" of parameters into their location + * + * NB: used by RF backends */ void ar5212ModifyRfBuffer(uint32_t *rfBuf, uint32_t reg32, uint32_t numBits, uint32_t firstBit, uint32_t column) { +#define MAX_ANALOG_START 319 /* XXX */ uint32_t tmp32, mask, arrayEntry, lastBit; int32_t bitPosition, bitsLeft; @@ -2862,6 +2566,7 @@ ar5212ModifyRfBuffer(uint32_t *rfBuf, uint32_t reg32, uint32_t numBits, bitPosition = 0; arrayEntry++; } +#undef MAX_ANALOG_START } /* @@ -2881,6 +2586,7 @@ ar5212SetRateDurationTable(struct ath_hal *ah, HAL_CHANNEL *chan) const HAL_RATE_TABLE *rt; int i; + /* NB: band doesn't matter for 1/2 and 1/4 rate */ if (IS_CHAN_HALF_RATE(chan)) { rt = ar5212GetRateTable(ah, HAL_MODE_11A_HALF_RATE); } else if (IS_CHAN_QUARTER_RATE(chan)) { @@ -2931,6 +2637,8 @@ ar5212SetIFSTiming(struct ath_hal *ah, HAL_CHANNEL *chan) { uint32_t txLat, rxLat, usec, slot, refClock, eifs, init_usec; + HALASSERT(IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(chan)); + refClock = OS_REG_READ(ah, AR_USEC) & AR_USEC_USEC32; if (IS_CHAN_HALF_RATE(chan)) { slot = IFS_SLOT_HALF_RATE; @@ -2953,7 +2661,5 @@ ar5212SetIFSTiming(struct ath_hal *ah, HAL_CHANNEL *chan) OS_REG_WRITE(ah, AR_D_GBL_IFS_EIFS, eifs); OS_REG_RMW_FIELD(ah, AR_D_GBL_IFS_MISC, AR_D_GBL_IFS_MISC_USEC_DURATION, init_usec); - return; } - #endif /* AH_SUPPORT_AR5212 */ diff --git a/ar5212/ar5212_rfgain.c b/ar5212/ar5212_rfgain.c new file mode 100644 index 000000000000..088cd26d4bdf --- /dev/null +++ b/ar5212/ar5212_rfgain.c @@ -0,0 +1,333 @@ +/* + * Copyright (c) 2002-2008 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. + * + * $Id: ar5212_rfgain.c,v 1.2 2008/11/19 21:23:01 sam Exp $ + */ +#include "opt_ah.h" + +#ifdef AH_SUPPORT_AR5212 + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ar5212/ar5212.h" +#include "ar5212/ar5212reg.h" +#include "ar5212/ar5212phy.h" + +#include "ah_eeprom_v3.h" + +static const GAIN_OPTIMIZATION_LADDER gainLadder = { + 9, /* numStepsInLadder */ + 4, /* defaultStepNum */ + { { {4, 1, 1, 1}, 6, "FG8"}, + { {4, 0, 1, 1}, 4, "FG7"}, + { {3, 1, 1, 1}, 3, "FG6"}, + { {4, 0, 0, 1}, 1, "FG5"}, + { {4, 1, 1, 0}, 0, "FG4"}, /* noJack */ + { {4, 0, 1, 0}, -2, "FG3"}, /* halfJack */ + { {3, 1, 1, 0}, -3, "FG2"}, /* clip3 */ + { {4, 0, 0, 0}, -4, "FG1"}, /* noJack */ + { {2, 1, 1, 0}, -6, "FG0"} /* clip2 */ + } +}; + +static const GAIN_OPTIMIZATION_LADDER gainLadder5112 = { + 8, /* numStepsInLadder */ + 1, /* defaultStepNum */ + { { {3, 0,0,0, 0,0,0}, 6, "FG7"}, /* most fixed gain */ + { {2, 0,0,0, 0,0,0}, 0, "FG6"}, + { {1, 0,0,0, 0,0,0}, -3, "FG5"}, + { {0, 0,0,0, 0,0,0}, -6, "FG4"}, + { {0, 1,1,0, 0,0,0}, -8, "FG3"}, + { {0, 1,1,0, 1,1,0}, -10, "FG2"}, + { {0, 1,0,1, 1,1,0}, -13, "FG1"}, + { {0, 1,0,1, 1,0,1}, -16, "FG0"}, /* least fixed gain */ + } +}; + +/* + * Initialize the gain structure to good values + */ +void +ar5212InitializeGainValues(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + GAIN_VALUES *gv = &ahp->ah_gainValues; + + /* initialize gain optimization values */ + if (IS_RAD5112_ANY(ah)) { + gv->currStepNum = gainLadder5112.defaultStepNum; + gv->currStep = + &gainLadder5112.optStep[gainLadder5112.defaultStepNum]; + gv->active = AH_TRUE; + gv->loTrig = 20; + gv->hiTrig = 85; + } else { + gv->currStepNum = gainLadder.defaultStepNum; + gv->currStep = &gainLadder.optStep[gainLadder.defaultStepNum]; + gv->active = AH_TRUE; + gv->loTrig = 20; + gv->hiTrig = 35; + } +} + +#define MAX_ANALOG_START 319 /* XXX */ + +/* + * Find analog bits of given parameter data and return a reversed value + */ +static uint32_t +ar5212GetRfField(uint32_t *rfBuf, uint32_t numBits, uint32_t firstBit, uint32_t column) +{ + uint32_t reg32 = 0, mask, arrayEntry, lastBit; + uint32_t bitPosition, bitsShifted; + int32_t bitsLeft; + + HALASSERT(column <= 3); + HALASSERT(numBits <= 32); + HALASSERT(firstBit + numBits <= MAX_ANALOG_START); + + arrayEntry = (firstBit - 1) / 8; + bitPosition = (firstBit - 1) % 8; + bitsLeft = numBits; + bitsShifted = 0; + while (bitsLeft > 0) { + lastBit = (bitPosition + bitsLeft > 8) ? + (8) : (bitPosition + bitsLeft); + mask = (((1 << lastBit) - 1) ^ ((1 << bitPosition) - 1)) << + (column * 8); + reg32 |= (((rfBuf[arrayEntry] & mask) >> (column * 8)) >> + bitPosition) << bitsShifted; + bitsShifted += lastBit - bitPosition; + bitsLeft -= (8 - bitPosition); + bitPosition = 0; + arrayEntry++; + } + reg32 = ath_hal_reverseBits(reg32, numBits); + return reg32; +} + +static HAL_BOOL +ar5212InvalidGainReadback(struct ath_hal *ah, GAIN_VALUES *gv) +{ + uint32_t gStep, g, mixOvr; + uint32_t L1, L2, L3, L4; + + if (IS_RAD5112_ANY(ah)) { + mixOvr = ar5212GetRfField(ar5212GetRfBank(ah, 7), 1, 36, 0); + L1 = 0; + L2 = 107; + L3 = 0; + L4 = 107; + if (mixOvr == 1) { + L2 = 83; + L4 = 83; + gv->hiTrig = 55; + } + } else { + gStep = ar5212GetRfField(ar5212GetRfBank(ah, 7), 6, 37, 0); + + L1 = 0; + L2 = (gStep == 0x3f) ? 50 : gStep + 4; + L3 = (gStep != 0x3f) ? 0x40 : L1; + L4 = L3 + 50; + + gv->loTrig = L1 + (gStep == 0x3f ? DYN_ADJ_LO_MARGIN : 0); + /* never adjust if != 0x3f */ + gv->hiTrig = L4 - (gStep == 0x3f ? DYN_ADJ_UP_MARGIN : -5); + } + g = gv->currGain; + + return !((g >= L1 && g<= L2) || (g >= L3 && g <= L4)); +} + +/* + * Enable the probe gain check on the next packet + */ +void +ar5212RequestRfgain(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + uint32_t probePowerIndex; + + /* Enable the gain readback probe */ + probePowerIndex = ahp->ah_ofdmTxPower + ahp->ah_txPowerIndexOffset; + OS_REG_WRITE(ah, AR_PHY_PAPD_PROBE, + SM(probePowerIndex, AR_PHY_PAPD_PROBE_POWERTX) + | AR_PHY_PAPD_PROBE_NEXT_TX); + + ahp->ah_rfgainState = HAL_RFGAIN_READ_REQUESTED; +} + +/* + * Check to see if our readback gain level sits within the linear + * region of our current variable attenuation window + */ +static HAL_BOOL +ar5212IsGainAdjustNeeded(struct ath_hal *ah, const GAIN_VALUES *gv) +{ + return (gv->currGain <= gv->loTrig || gv->currGain >= gv->hiTrig); +} + +/* + * Move the rabbit ears in the correct direction. + */ +static int32_t +ar5212AdjustGain(struct ath_hal *ah, GAIN_VALUES *gv) +{ + const GAIN_OPTIMIZATION_LADDER *gl; + + if (IS_RAD5112_ANY(ah)) + gl = &gainLadder5112; + else + gl = &gainLadder; + gv->currStep = &gl->optStep[gv->currStepNum]; + if (gv->currGain >= gv->hiTrig) { + if (gv->currStepNum == 0) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: Max gain limit.\n", + __func__); + return -1; + } + HALDEBUG(ah, HAL_DEBUG_RFPARAM, + "%s: Adding gain: currG=%d [%s] --> ", + __func__, gv->currGain, gv->currStep->stepName); + gv->targetGain = gv->currGain; + while (gv->targetGain >= gv->hiTrig && gv->currStepNum > 0) { + gv->targetGain -= 2 * (gl->optStep[--(gv->currStepNum)].stepGain - + gv->currStep->stepGain); + gv->currStep = &gl->optStep[gv->currStepNum]; + } + HALDEBUG(ah, HAL_DEBUG_RFPARAM, "targG=%d [%s]\n", + gv->targetGain, gv->currStep->stepName); + return 1; + } + if (gv->currGain <= gv->loTrig) { + if (gv->currStepNum == gl->numStepsInLadder-1) { + HALDEBUG(ah, HAL_DEBUG_RFPARAM, + "%s: Min gain limit.\n", __func__); + return -2; + } + HALDEBUG(ah, HAL_DEBUG_RFPARAM, + "%s: Deducting gain: currG=%d [%s] --> ", + __func__, gv->currGain, gv->currStep->stepName); + gv->targetGain = gv->currGain; + while (gv->targetGain <= gv->loTrig && + gv->currStepNum < (gl->numStepsInLadder - 1)) { + gv->targetGain -= 2 * + (gl->optStep[++(gv->currStepNum)].stepGain - gv->currStep->stepGain); + gv->currStep = &gl->optStep[gv->currStepNum]; + } + HALDEBUG(ah, HAL_DEBUG_RFPARAM, "targG=%d [%s]\n", + gv->targetGain, gv->currStep->stepName); + return 2; + } + return 0; /* caller didn't call needAdjGain first */ +} + +/* + * Read rf register to determine if gainF needs correction + */ +static void +ar5212GetGainFCorrection(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + GAIN_VALUES *gv = &ahp->ah_gainValues; + + HALASSERT(IS_RADX112_REV2(ah)); + + gv->gainFCorrection = 0; + if (ar5212GetRfField(ar5212GetRfBank(ah, 7), 1, 36, 0) == 1) { + uint32_t mixGain = gv->currStep->paramVal[0]; + uint32_t gainStep = + ar5212GetRfField(ar5212GetRfBank(ah, 7), 4, 32, 0); + switch (mixGain) { + case 0 : + gv->gainFCorrection = 0; + break; + case 1 : + gv->gainFCorrection = gainStep; + break; + case 2 : + gv->gainFCorrection = 2 * gainStep - 5; + break; + case 3 : + gv->gainFCorrection = 2 * gainStep; + break; + } + } +} + +/* + * Exported call to check for a recent gain reading and return + * the current state of the thermal calibration gain engine. + */ +HAL_RFGAIN +ar5212GetRfgain(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + GAIN_VALUES *gv = &ahp->ah_gainValues; + uint32_t rddata, probeType; + + if (!gv->active) + return HAL_RFGAIN_INACTIVE; + + if (ahp->ah_rfgainState == HAL_RFGAIN_READ_REQUESTED) { + /* Caller had asked to setup a new reading. Check it. */ + rddata = OS_REG_READ(ah, AR_PHY_PAPD_PROBE); + + if ((rddata & AR_PHY_PAPD_PROBE_NEXT_TX) == 0) { + /* bit got cleared, we have a new reading. */ + gv->currGain = rddata >> AR_PHY_PAPD_PROBE_GAINF_S; + probeType = MS(rddata, AR_PHY_PAPD_PROBE_TYPE); + if (probeType == AR_PHY_PAPD_PROBE_TYPE_CCK) { + const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; + + HALASSERT(IS_RAD5112_ANY(ah)); + HALASSERT(ah->ah_magic == AR5212_MAGIC); + if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_2) + gv->currGain += ee->ee_cckOfdmGainDelta; + else + gv->currGain += PHY_PROBE_CCK_CORRECTION; + } + if (IS_RADX112_REV2(ah)) { + ar5212GetGainFCorrection(ah); + if (gv->currGain >= gv->gainFCorrection) + gv->currGain -= gv->gainFCorrection; + else + gv->currGain = 0; + } + /* inactive by default */ + ahp->ah_rfgainState = HAL_RFGAIN_INACTIVE; + + if (!ar5212InvalidGainReadback(ah, gv) && + ar5212IsGainAdjustNeeded(ah, gv) && + ar5212AdjustGain(ah, gv) > 0) { + /* + * Change needed. Copy ladder info + * into eeprom info. + */ + ahp->ah_rfgainState = HAL_RFGAIN_NEED_CHANGE; + /* for ap51 */ + ahp->ah_cwCalRequire = AH_TRUE; + /* Request IQ recalibration for temperature chang */ + ahp->ah_bIQCalibration = IQ_CAL_INACTIVE; + } + } + } + return ahp->ah_rfgainState; +} +#endif /* AH_SUPPORT_AR5212 */ diff --git a/ar5212/ar5212phy.h b/ar5212/ar5212phy.h index fd76fd1965d1..e040ec79b63a 100644 --- a/ar5212/ar5212phy.h +++ b/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.5 2008/11/04 01:08:40 sam Exp $ + * $Id: ar5212phy.h,v 1.7 2008/11/19 21:23:01 sam Exp $ */ #ifndef _DEV_ATH_AR5212PHY_H_ #define _DEV_ATH_AR5212PHY_H_ @@ -113,6 +113,7 @@ #define AR_PHY_AGC_CONTROL_CAL 0x00000001 /* do internal calibration */ #define AR_PHY_AGC_CONTROL_NF 0x00000002 /* do noise-floor calculation */ #define AR_PHY_AGC_CONTROL_ENABLE_NF 0x00008000 /* Enable noise floor calibration to happen */ +#define AR_PHY_AGC_CONTROL_FLTR_CAL 0x00010000 /* Allow Filter calibration */ #define AR_PHY_AGC_CONTROL_NO_UPDATE_NF 0x00020000 /* Don't update noise floor automatically */ #define AR_PHY_SFCORR_LOW 0x986C @@ -136,16 +137,14 @@ #define AR_PHY_SLEEP_CTR_LIMIT 0x9874 #define AR_PHY_SLEEP_SCAL 0x9878 -#define AR_PHY_PLL_CTL 0x987c /* PLL control register */ -#define AR_PHY_PLL_CTL_40 0xaa /* 40 MHz */ -#define AR_PHY_PLL_CTL_44 0xab /* 44 MHz for 11b, 11g */ -#define AR_PHY_PLL_CTL_40_HALF 0x1aa /* 40 MHz for 11a, turbos (Half)*/ -#define AR_PHY_PLL_CTL_40_QUARTER 0x2aa /* 40 MHz for 11a, turbos (Quarter)*/ -#define AR_PHY_PLL_CTL_44_5112 0xeb /* 44 MHz for 11b, 11g */ -#define AR_PHY_PLL_CTL_40_5112 0xea /* 40 MHz for 11a, turbos */ -#define AR_PHY_PLL_CTL_40_5112_HALF 0x1ea /* 40 MHz for 11a, turbos (Half)*/ -#define AR_PHY_PLL_CTL_40_5112_QUARTER 0x2ea /* 40 MHz for 11a, turbos (Quarter)*/ -#define AR_PHY_PLL_CTL_40_5413 0x04 /* 40 MHz for 11a, turbos with 5413 */ +#define AR_PHY_PLL_CTL 0x987c /* PLL control register */ +#define AR_PHY_PLL_CTL_40 0xaa /* 40 MHz */ +#define AR_PHY_PLL_CTL_44 0xab /* 44 MHz for 11b, 11g */ +#define AR_PHY_PLL_CTL_44_5112 0xeb /* 44 MHz for 11b, 11g */ +#define AR_PHY_PLL_CTL_40_5112 0xea /* 40 MHz for 11a, turbos */ +#define AR_PHY_PLL_CTL_40_5413 0x04 /* 40 MHz for 11a, turbos with 5413 */ +#define AR_PHY_PLL_CTL_HALF 0x100 /* Half clock for 1/2 chan width */ +#define AR_PHY_PLL_CTL_QUARTER 0x200 /* Quarter clock for 1/4 chan width */ #define AR_PHY_BIN_MASK_1 0x9900 #define AR_PHY_BIN_MASK_2 0x9904 diff --git a/ar5212/ar5212reg.h b/ar5212/ar5212reg.h index 9d5754c255a9..681c6e33bbbe 100644 --- a/ar5212/ar5212reg.h +++ b/ar5212/ar5212reg.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: ar5212reg.h,v 1.4 2008/10/12 17:07:17 sam Exp $ + * $Id: ar5212reg.h,v 1.5 2008/11/16 06:45:43 sam Exp $ */ #ifndef _DEV_ATH_AR5212REG_H_ #define _DEV_ATH_AR5212REG_H_ @@ -762,9 +762,9 @@ #define AR_SREV_CRETE_MS 5 /* FCS metal spin */ #define AR_SREV_CRETE_MS23 7 /* 2.3 metal spin (6 skipped) */ #define AR_SREV_CRETE_23 8 /* 2.3 full tape out */ -#define AR_SREV_GRIFFIN_LITE 8 -#define AR_SREV_HAINAN 9 -#define AR_SREV_CONDOR 11 +#define AR_SREV_GRIFFIN_LITE 8 +#define AR_SREV_HAINAN 9 +#define AR_SREV_CONDOR 11 #define AR_SREV_VERSION 0x000000F0 /* Mask for Chip version */ #define AR_SREV_VERSION_CRETE 0 #define AR_SREV_VERSION_MAUI_1 1 @@ -773,38 +773,39 @@ #define AR_SREV_VERSION_OAHU 4 #define AR_SREV_VERSION_VENICE 5 #define AR_SREV_VERSION_GRIFFIN 7 -#define AR_SREV_VERSION_CONDOR 9 -#define AR_SREV_VERSION_EAGLE 10 +#define AR_SREV_VERSION_CONDOR 9 +#define AR_SREV_VERSION_EAGLE 10 #define AR_SREV_VERSION_COBRA 11 #define AR_SREV_2413 AR_SREV_VERSION_GRIFFIN -#define AR_SREV_5413 AR_SREV_VERSION_EAGLE +#define AR_SREV_5413 AR_SREV_VERSION_EAGLE #define AR_SREV_2415 AR_SREV_VERSION_COBRA -#define AR_SREV_5424 AR_SREV_VERSION_CONDOR -#define AR_SREV_2425 14 /* SWAN */ -#define AR_SREV_2417 15 /* Nala */ +#define AR_SREV_5424 AR_SREV_VERSION_CONDOR +#define AR_SREV_2425 14 /* SWAN */ +#define AR_SREV_2417 15 /* Nala */ #define AR_SREV_OAHU_ES 0 /* Engineering Sample */ #define AR_SREV_OAHU_PROD 2 /* Production */ -#define AR_PHYREV_HAINAN 0x43 -#define AR_ANALOG5REV_HAINAN 0x46 +#define AR_PHYREV_HAINAN 0x43 +#define AR_ANALOG5REV_HAINAN 0x46 -#define AR_RADIO_SREV_MAJOR 0xF0 +#define AR_RADIO_SREV_MAJOR 0xF0 +#define AR_RADIO_SREV_MINOR 0x0F #define AR_RAD5111_SREV_MAJOR 0x10 /* All current supported ar5211 5 GHz radios are rev 0x10 */ #define AR_RAD5111_SREV_PROD 0x15 /* Current production level radios */ #define AR_RAD2111_SREV_MAJOR 0x20 /* All current supported ar5211 2 GHz radios are rev 0x10 */ #define AR_RAD5112_SREV_MAJOR 0x30 /* 5112 Major Rev */ +#define AR_RAD5112_SREV_2_0 0x35 /* AR5112 Revision 2.0 */ +#define AR_RAD5112_SREV_2_1 0x36 /* AR5112 Revision 2.1 */ #define AR_RAD2112_SREV_MAJOR 0x40 /* 2112 Major Rev */ +#define AR_RAD2112_SREV_2_0 0x45 /* AR2112 Revision 2.0 */ +#define AR_RAD2112_SREV_2_1 0x46 /* AR2112 Revision 2.1 */ #define AR_RAD2413_SREV_MAJOR 0x50 /* 2413 Major Rev */ #define AR_RAD5413_SREV_MAJOR 0x60 /* 5413 Major Rev */ -#define AR_RAD5424_SREV_MAJOR 0xa0 /* Mostly same as 5413 Major Rev */ #define AR_RAD2316_SREV_MAJOR 0x70 /* 2316 Major Rev */ #define AR_RAD2317_SREV_MAJOR 0x80 /* 2317 Major Rev */ -#define AR_RAD5112_SREV_2_0 0x35 /* AR5112 Revision 2.0 */ -#define AR_RAD2112_SREV_2_0 0x45 /* AR2112 Revision 2.0 */ -#define AR_RAD5112_SREV_2_1 0x36 /* AR5112 Revision 2.1 */ -#define AR_RAD2112_SREV_2_1 0x46 /* AR2112 Revision 2.1 */ +#define AR_RAD5424_SREV_MAJOR 0xa0 /* Mostly same as 5413 Major Rev */ #define AR_PCIE_PMC_ENA_L1 0x01 /* enable PCIe core enter L1 when d2_sleep_en is asserted */ diff --git a/ar5212/ar5311reg.h b/ar5212/ar5311reg.h index ebf9b64ca774..efb85686369d 100644 --- a/ar5212/ar5311reg.h +++ b/ar5212/ar5311reg.h @@ -45,5 +45,6 @@ * is controlled */ #define AR5311_D_MISC_SEQ_NUM_CONTROL 0x01000000 /* seq num local or global */ +#define AR5311_DIAG_USE_ECO 0x00000400 /* "super secret" enable ECO */ #endif /* _DEV_ATH_AR5311REG_H_ */ diff --git a/ar5212/ar5413.c b/ar5212/ar5413.c index ee876597cf19..6b15a6c3340d 100644 --- a/ar5212/ar5413.c +++ b/ar5212/ar5413.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: ar5413.c,v 1.7 2008/11/10 04:08:03 sam Exp $ + * $Id: ar5413.c,v 1.8 2008/11/15 22:15:46 sam Exp $ */ #include "opt_ah.h" @@ -549,8 +549,11 @@ ar5413SetPowerTable(struct ath_hal *ah, int16_t minCalPower5413_t2; uint16_t *pdadcValues = ahp->ah_pcdacTable; uint16_t gainBoundaries[4]; - uint32_t i, reg32, regoffset, tpcrg1; - int numPdGainsUsed; + uint32_t reg32, regoffset; + int i, numPdGainsUsed; +#ifndef AH_USE_INIPDGAIN + uint32_t tpcrg1; +#endif HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: chan 0x%x flag 0x%x\n", __func__, chan->channel,chan->channelFlags); @@ -572,10 +575,16 @@ ar5413SetPowerTable(struct ath_hal *ah, &minCalPower5413_t2,gainBoundaries, rfXpdGain, pdadcValues); HALASSERT(1 <= numPdGainsUsed && numPdGainsUsed <= 3); -#if 0 +#ifdef AH_USE_INIPDGAIN + /* + * Use pd_gains curve from eeprom; Atheros always uses + * the default curve from the ini file but some vendors + * (e.g. Zcomax) want to override this curve and not + * honoring their settings results in tx power 5dBm low. + */ OS_REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN, (pRawDataset->pDataPerChannel[0].numPdGains - 1)); -#endif +#else tpcrg1 = OS_REG_READ(ah, AR_PHY_TPCRG1); tpcrg1 = (tpcrg1 &~ AR_PHY_TPCRG1_NUM_PD_GAIN) | SM(numPdGainsUsed-1, AR_PHY_TPCRG1_NUM_PD_GAIN); @@ -600,6 +609,7 @@ ar5413SetPowerTable(struct ath_hal *ah, __func__, OS_REG_READ(ah, AR_PHY_TPCRG1), tpcrg1); #endif OS_REG_WRITE(ah, AR_PHY_TPCRG1, tpcrg1); +#endif /* * Note the pdadc table may not start at 0 dBm power, could be diff --git a/ar5312/ar5312.h b/ar5312/ar5312.h index 08edf2f490f7..4714ea15d00f 100644 --- a/ar5312/ar5312.h +++ b/ar5312/ar5312.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: ar5312.h,v 1.4 2008/11/10 04:08:04 sam Exp $ + * $Id: ar5312.h,v 1.5 2008/11/22 07:37:40 sam Exp $ */ #ifndef _ATH_AR5312_H_ #define _ATH_AR5312_H_ @@ -30,15 +30,13 @@ (((const struct ar531x_config *)((_ah)->ah_st))->radio) #define IS_5312_2_X(ah) \ - (((AH_PRIVATE(ah)->ah_macVersion) == AR_SREV_VERSION_VENICE) && \ - (((AH_PRIVATE(ah)->ah_macRev) == 2) || ((AH_PRIVATE(ah)->ah_macRev) == 7))) - + (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_VENICE && \ + (AH_PRIVATE(ah)->ah_macRev == 2 || AH_PRIVATE(ah)->ah_macRev == 7)) #define IS_5315(ah) \ - ((AH_PRIVATE(ah)->ah_devid == AR5212_AR2315_REV6) || \ - (AH_PRIVATE(ah)->ah_devid == AR5212_AR2315_REV7) || \ - (AH_PRIVATE(ah)->ah_devid == AR5212_AR2317_REV1) || \ - (AH_PRIVATE(ah)->ah_devid == AR5212_AR2317_REV2)) - + (AH_PRIVATE(ah)->ah_devid == AR5212_AR2315_REV6 || \ + AH_PRIVATE(ah)->ah_devid == AR5212_AR2315_REV7 || \ + AH_PRIVATE(ah)->ah_devid == AR5212_AR2317_REV1 || \ + AH_PRIVATE(ah)->ah_devid == AR5212_AR2317_REV2) extern struct ath_hal * ar5312Attach(uint16_t devid, HAL_SOFTC sc, HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status); @@ -76,5 +74,6 @@ extern HAL_BOOL ar5312GetPowerStatus(struct ath_hal *ah); /* BSP functions */ extern HAL_BOOL ar5312EepromRead(struct ath_hal *, u_int off, uint16_t *data); +extern HAL_BOOL ar5312EepromWrite(struct ath_hal *, u_int off, uint16_t data); #endif /* _ATH_AR3212_H_ */ diff --git a/ar5312/ar5312_attach.c b/ar5312/ar5312_attach.c index 52d2132655c9..e919924721c2 100644 --- a/ar5312/ar5312_attach.c +++ b/ar5312/ar5312_attach.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_attach.c,v 1.6 2008/11/10 04:08:04 sam Exp $ + * $Id: ar5312_attach.c,v 1.8 2008/11/27 22:30:03 sam Exp $ */ #include "opt_ah.h" @@ -39,13 +39,6 @@ #define AH_5212_COMMON #include "ar5212/ar5212.ini" -/* - * These are not valid 2.4 channels, either we change these - * or we need to change the coding to accept these - */ -static const uint16_t channels11b[] = { 2412, 2447, 2484 }; -static const uint16_t channels11g[] = { 2312, 2412, 2484 }; - static HAL_BOOL ar5312GetMacAddr(struct ath_hal *ah); static void @@ -217,7 +210,7 @@ ar5312Attach(uint16_t devid, HAL_SOFTC sc, goto bad; } #endif - if (IS_5112(ah) && !IS_RADX112_REV2(ah)) { + if (IS_RAD5112(ah) && !IS_RADX112_REV2(ah)) { #ifdef AH_DEBUG ath_hal_printf(ah, "%s: 5112 Rev 1 is not supported by this " "driver (analog5GhzRev 0x%x)\n", __func__, @@ -293,13 +286,13 @@ ar5312Attach(uint16_t devid, HAL_SOFTC sc, #else ecode = HAL_ENOTSUPP; #endif - else if (IS_5112(ah)) + else if (IS_RAD5112_ANY(ah)) #ifdef AH_SUPPORT_5112 rfStatus = ar5112RfAttach(ah, &ecode); #else ecode = HAL_ENOTSUPP; #endif - else + else if (IS_RAD5111(ah)) #ifdef AH_SUPPORT_5111 rfStatus = ar5111RfAttach(ah, &ecode); #else diff --git a/ar5312/ar5312_misc.c b/ar5312/ar5312_misc.c index 12e173b84dc2..79283186c5d3 100644 --- a/ar5312/ar5312_misc.c +++ b/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.3 2008/11/10 04:08:04 sam Exp $ + * $Id: ar5312_misc.c,v 1.4 2008/11/22 07:40:15 sam Exp $ */ #include "opt_ah.h" @@ -108,7 +108,8 @@ ar5312SetupClock(struct ath_hal *ah, HAL_OPMODE opmode) OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0c); OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x03); OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0x05); - OS_REG_WRITE(ah, AR_PHY_REFCLKPD, (IS_5112(ah) || IS_2413(ah)) ? 0x14 : 0x18); + OS_REG_WRITE(ah, AR_PHY_REFCLKPD, + IS_RAD5112_ANY(ah) ? 0x14 : 0x18); OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32, 1); OS_REG_WRITE(ah, AR_TSF_PARM, 61); /* 32 KHz TSF incr */ @@ -116,7 +117,7 @@ ar5312SetupClock(struct ath_hal *ah, HAL_OPMODE opmode) } else { OS_REG_WRITE(ah, AR_TSF_PARM, 1); /* 32 MHz TSF incr */ OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32, - (IS_5112(ah) || IS_2413(ah)) ? 39 : 31); + IS_RAD5112_ANY(ah) ? 39 : 31); OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f); OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT, 0x7f); @@ -128,7 +129,8 @@ ar5312SetupClock(struct ath_hal *ah, HAL_OPMODE opmode) OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e); OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x0c); OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0xff); - OS_REG_WRITE(ah, AR_PHY_REFCLKPD, (IS_5112(ah) || IS_2413(ah)) ? 0x14 : 0x18); + OS_REG_WRITE(ah, AR_PHY_REFCLKPD, + IS_RAD5112_ANY(ah) ? 0x14 : 0x18); } } } @@ -143,7 +145,7 @@ ar5312RestoreClock(struct ath_hal *ah, HAL_OPMODE opmode) /* # Set sleep clock rate back to 32 MHz. */ OS_REG_WRITE(ah, AR_TSF_PARM, 1); /* 32 MHz TSF incr */ OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32, - (IS_5112(ah) || IS_2413(ah)) ? 39 : 31); + IS_RAD5112_ANY(ah) ? 39 : 31); /* * Restore BB registers to power-on defaults @@ -157,7 +159,8 @@ ar5312RestoreClock(struct ath_hal *ah, HAL_OPMODE opmode) OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e); OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x0c); OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0xff); - OS_REG_WRITE(ah, AR_PHY_REFCLKPD, (IS_5112(ah) || IS_2413(ah)) ? 0x14 : 0x18); + OS_REG_WRITE(ah, AR_PHY_REFCLKPD, + IS_RAD5112_ANY(ah) ? 0x14 : 0x18); } } } diff --git a/ar5312/ar5312_reset.c b/ar5312/ar5312_reset.c index 84904318e095..6c0bb0a8a1e6 100644 --- a/ar5312/ar5312_reset.c +++ b/ar5312/ar5312_reset.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_reset.c,v 1.9 2008/11/10 04:08:04 sam Exp $ + * $Id: ar5312_reset.c,v 1.10 2008/11/22 07:41:37 sam Exp $ */ #include "opt_ah.h" @@ -173,7 +173,7 @@ ar5312Reset(struct ath_hal *ah, HAL_OPMODE opmode, * -channel change requested - so it's not the initial reset. * -it's not a change to the current channel - often called when switching modes * on a channel - * -the modes of the previous and requested channel are the same + * -the modes of the previous and requested channel are the same - some ugly code for XR */ if (bChannelChange && (AH_PRIVATE(ah)->ah_curchan != AH_NULL) && @@ -406,8 +406,9 @@ ar5312Reset(struct ath_hal *ah, HAL_OPMODE opmode, ar5212SetRateDurationTable(ah, chan); /* Set Tx frame start to tx data start delay */ - if (IS_5112(ah) && (IS_CHAN_HALF_RATE(AH_PRIVATE(ah)->ah_curchan) || - IS_CHAN_QUARTER_RATE(AH_PRIVATE(ah)->ah_curchan))) { + if (IS_RAD5112_ANY(ah) && + (IS_CHAN_HALF_RATE(AH_PRIVATE(ah)->ah_curchan) || + IS_CHAN_QUARTER_RATE(AH_PRIVATE(ah)->ah_curchan))) { txFrm2TxDStart = (IS_CHAN_HALF_RATE(AH_PRIVATE(ah)->ah_curchan)) ? TX_FRAME_D_START_HALF_RATE: @@ -679,7 +680,7 @@ ar5312ChipReset(struct ath_hal *ah, HAL_CHANNEL *chan) if (chan != AH_NULL) { /* NB: can be null during attach */ uint32_t rfMode, phyPLL = 0, curPhyPLL, turbo; - if (IS_5112(ah) || IS_2413(ah)) { + if (IS_RAD5112_ANY(ah)) { rfMode = AR_PHY_MODE_AR5112; if (!IS_5315(ah)) { if (IS_CHAN_CCK(chan) || IS_CHAN_G(chan)) { @@ -694,31 +695,25 @@ ar5312ChipReset(struct ath_hal *ah, HAL_CHANNEL *chan) } } } else { - if (IS_CHAN_CCK(chan) || IS_CHAN_G(chan)) { + if (IS_CHAN_CCK(chan) || IS_CHAN_G(chan)) phyPLL = AR_PHY_PLL_CTL_44_5112; - } else { - if (IS_CHAN_HALF_RATE(chan)) { - phyPLL = AR_PHY_PLL_CTL_40_5112_HALF; - } else if (IS_CHAN_QUARTER_RATE(chan)) { - phyPLL = AR_PHY_PLL_CTL_40_5112_QUARTER; - } else { - phyPLL = AR_PHY_PLL_CTL_40_5112; - } - } + else + phyPLL = AR_PHY_PLL_CTL_40_5112; + if (IS_CHAN_HALF_RATE(chan)) + phyPLL |= AR_PHY_PLL_CTL_HALF; + else if (IS_CHAN_QUARTER_RATE(chan)) + phyPLL |= AR_PHY_PLL_CTL_QUARTER; } } else { rfMode = AR_PHY_MODE_AR5111; - if (IS_CHAN_CCK(chan) || IS_CHAN_G(chan)) { + if (IS_CHAN_CCK(chan) || IS_CHAN_G(chan)) phyPLL = AR_PHY_PLL_CTL_44; - } else { - if (IS_CHAN_HALF_RATE(chan)) { - phyPLL = AR_PHY_PLL_CTL_40_HALF; - } else if (IS_CHAN_QUARTER_RATE(chan)) { - phyPLL = AR_PHY_PLL_CTL_40_QUARTER; - } else { - phyPLL = AR_PHY_PLL_CTL_40; - } - } + else + phyPLL = AR_PHY_PLL_CTL_40; + if (IS_CHAN_HALF_RATE(chan)) + phyPLL = AR_PHY_PLL_CTL_HALF; + else if (IS_CHAN_QUARTER_RATE(chan)) + phyPLL = AR_PHY_PLL_CTL_QUARTER; } if (IS_CHAN_OFDM(chan) && (IS_CHAN_CCK(chan) || IS_CHAN_G(chan))) diff --git a/ar5416/ar2133.c b/ar5416/ar2133.c index 9fb95dfbcddc..d9666931479e 100644 --- a/ar5416/ar2133.c +++ b/ar5416/ar2133.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: ar2133.c,v 1.10 2008/11/10 04:08:04 sam Exp $ + * $Id: ar2133.c,v 1.13 2008/11/11 00:11:30 sam Exp $ */ #include "opt_ah.h" @@ -330,6 +330,64 @@ ar2133GetChannelMaxMinPower(struct ath_hal *ah, HAL_CHANNEL *chan, int16_t *maxP #endif } +static void +ar2133GetNoiseFloor(struct ath_hal *ah, int16_t nfarray[]) +{ + struct ath_hal_5416 *ahp = AH5416(ah); + int16_t nf; + + switch (ahp->ah_rx_chainmask) { + case 0x7: + nf = MS(OS_REG_READ(ah, AR_PHY_CH2_CCA), AR_PHY_CH2_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + HALDEBUG(ah, HAL_DEBUG_NFCAL, + "NF calibrated [ctl] [chain 2] is %d\n", nf); + nfarray[4] = nf; + + nf = MS(OS_REG_READ(ah, AR_PHY_CH2_EXT_CCA), AR_PHY_CH2_EXT_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + HALDEBUG(ah, HAL_DEBUG_NFCAL, + "NF calibrated [ext] [chain 2] is %d\n", nf); + nfarray[5] = nf; + /* fall thru... */ + case 0x3: + case 0x5: + nf = MS(OS_REG_READ(ah, AR_PHY_CH1_CCA), AR_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[2] = nf; + + + nf = MS(OS_REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR_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[3] = nf; + /* fall thru... */ + case 0x1: + nf = MS(OS_REG_READ(ah, AR_PHY_CCA), AR_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_EXT_CCA), AR_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[1] = nf; + + break; + } +} + /* * Adjust NF based on statistical values for 5GHz frequencies. * Stubbed:Not used by Fowl @@ -404,6 +462,7 @@ ar2133RfAttach(struct ath_hal *ah, HAL_STATUS *status) * direct call instead of thunking. */ AH_PRIVATE(ah)->ah_getNfAdjust = priv->base.getNfAdjust; + AH_PRIVATE(ah)->ah_getNoiseFloor = ar2133GetNoiseFloor; return AH_TRUE; } diff --git a/ar5416/ar5416.h b/ar5416/ar5416.h index db7a821971c0..34e76b958cdf 100644 --- a/ar5416/ar5416.h +++ b/ar5416/ar5416.h @@ -14,19 +14,20 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Id: ar5416.h,v 1.16 2008/11/10 04:08:04 sam Exp $ + * $Id: ar5416.h,v 1.19 2008/11/11 21:38:13 sam Exp $ */ #ifndef _ATH_AR5416_H_ #define _ATH_AR5416_H_ #include "ar5212/ar5212.h" +#include "ar5416_cal.h" #define AR5416_MAGIC 0x20065416 enum { - HAL_RESET_POWER_ON, - HAL_RESET_WARM, - HAL_RESET_COLD, + HAL_RESET_POWER_ON, + HAL_RESET_WARM, + HAL_RESET_COLD, }; typedef struct { @@ -40,71 +41,10 @@ typedef struct { #define AR5416_MAX_RATE_POWER 63 #define AR5416_KEYTABLE_SIZE 128 -#define AR5416_NUM_NF_READINGS 6 /* (3 chains * (ctl + ext) */ #define AR5416_CCA_MAX_GOOD_VALUE -85 #define AR5416_CCA_MAX_HIGH_VALUE -62 #define AR5416_CCA_MIN_BAD_VALUE -140 -#define INIT_CAL(_perCal) do { \ - (_perCal)->calState = CAL_WAITING; \ - (_perCal)->calNext = AH_NULL; \ -} while (0) - -#define INSERT_CAL(_ahp, _perCal) do { \ - if ((_ahp)->ah_cal_last == AH_NULL) { \ - (_ahp)->ah_cal_list = (_ahp)->ah_cal_last = (_perCal); \ - ((_ahp)->ah_cal_last)->calNext = (_perCal); \ - } else { \ - ((_ahp)->ah_cal_last)->calNext = (_perCal); \ - (_ahp)->ah_cal_last = (_perCal); \ - (_perCal)->calNext = (_ahp)->ah_cal_list; \ - } \ -} while (0) - -typedef enum cal_types { - ADC_DC_INIT_CAL = 0x1, - ADC_GAIN_CAL = 0x2, - ADC_DC_CAL = 0x4, - IQ_MISMATCH_CAL = 0x8 -} HAL_CAL_TYPE; - -/* Calibrate state */ -typedef enum cal_state { - CAL_INACTIVE, - CAL_WAITING, - CAL_RUNNING, - CAL_DONE -} HAL_CAL_STATE; - -typedef union { - uint32_t u; - int32_t s; -} HAL_CAL_SAMPLE; - -#define MIN_CAL_SAMPLES 1 -#define MAX_CAL_SAMPLES 64 -#define INIT_LOG_COUNT 5 -#define PER_MIN_LOG_COUNT 2 -#define PER_MAX_LOG_COUNT 10 - -/* Per Calibration data structure */ -typedef struct per_cal_data { - const char *calName; /* for diagnostics */ - HAL_CAL_TYPE calType; /* Type of calibration */ - uint32_t calNumSamples; /* # SW samples to collect */ - uint32_t calCountMax; /* # HW samples to collect */ - void (*calCollect)(struct ath_hal *); /* Accumulator function */ - /* Post-processing function */ - void (*calPostProc)(struct ath_hal *, uint8_t); -} HAL_PERCAL_DATA; - -/* List structure for calibration data */ -typedef struct cal_list { - struct cal_list *calNext; - HAL_CAL_STATE calState; - const HAL_PERCAL_DATA *calData; -} HAL_CAL_LIST; - struct ath_hal_5416 { struct ath_hal_5212 ah_5212; @@ -119,7 +59,6 @@ struct ath_hal_5416 { HAL_INI_ARRAY ah_ini_addac; u_int ah_globaltxtimeout; /* global tx timeout */ - int ah_clksel; int ah_hangs; /* h/w hangs state */ uint8_t ah_keytype[AR5416_KEYTABLE_SIZE]; /* @@ -130,43 +69,11 @@ struct ath_hal_5416 { uint32_t ah_extBusy; uint32_t ah_rx_chainmask; uint32_t ah_tx_chainmask; - /* - * Periodic calibration state. - */ - HAL_CAL_TYPE ah_suppCals; - HAL_CAL_LIST ah_iqCalData; - HAL_CAL_LIST ah_adcGainCalData; - HAL_CAL_LIST ah_adcDcCalInitData; - HAL_CAL_LIST ah_adcDcCalData; - HAL_CAL_LIST *ah_cal_list; - HAL_CAL_LIST *ah_cal_last; - HAL_CAL_LIST *ah_cal_curr; -#define AR5416_MAX_CHAINS 3 /* XXX dup's eeprom def */ - HAL_CAL_SAMPLE ah_caldata[4][AR5416_MAX_CHAINS]; - int ah_calSamples; - /* - * Noise floor cal histogram support. - * XXX be nice to re-use space in ar5212 - */ - struct ar5212NfCalHist ah_nfCalHist[AR5416_NUM_NF_READINGS]; + + struct ar5416PerCal ah_cal; /* periodic calibration state */ }; #define AH5416(_ah) ((struct ath_hal_5416 *)(_ah)) -/* IQ Cal aliases */ -#define ah_totalPowerMeasI(i) ah_caldata[0][i].u -#define ah_totalPowerMeasQ(i) ah_caldata[1][i].u -#define ah_totalIqCorrMeas(i) ah_caldata[2][i].s -/* Adc Gain Cal aliases */ -#define ah_totalAdcIOddPhase(i) ah_caldata[0][i].u -#define ah_totalAdcIEvenPhase(i) ah_caldata[1][i].u -#define ah_totalAdcQOddPhase(i) ah_caldata[2][i].u -#define ah_totalAdcQEvenPhase(i) ah_caldata[3][i].u -/* Adc DC Offset Cal aliases */ -#define ah_totalAdcDcOffsetIOddPhase(i) ah_caldata[0][i].s -#define ah_totalAdcDcOffsetIEvenPhase(i) ah_caldata[1][i].s -#define ah_totalAdcDcOffsetQOddPhase(i) ah_caldata[2][i].s -#define ah_totalAdcDcOffsetQEvenPhase(i) ah_caldata[3][i].s - #define IS_5416_PCI(ah) ((AH_PRIVATE(ah)->ah_macVersion) == AR_SREV_VERSION_OWL_PCI) #define IS_5416_PCIE(ah) ((AH_PRIVATE(ah)->ah_macVersion) == AR_SREV_VERSION_OWL_PCIE) #undef IS_PCIE @@ -187,8 +94,17 @@ extern HAL_BOOL ar5416FillCapabilityInfo(struct ath_hal *ah); #define IS_5GHZ_FAST_CLOCK_EN(_ah, _c) \ (IS_CHAN_5GHZ(_c) && ath_hal_eepromGetFlag(ah, AR_EEP_FSTCLK_5G)) -extern HAL_BOOL ar5416AniAttach(struct ath_hal *ah); -extern void ar5416AniDetach(struct ath_hal *ah); +extern void ar5416AniAttach(struct ath_hal *, const struct ar5212AniParams *, + const struct ar5212AniParams *, HAL_BOOL ena); +extern void ar5416AniDetach(struct ath_hal *); +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 *, + HAL_CHANNEL *); +extern void ar5416AniReset(struct ath_hal *, HAL_CHANNEL_INTERNAL *, + HAL_OPMODE, int); extern void ar5416SetBeaconTimers(struct ath_hal *, const HAL_BEACON_TIMERS *); extern void ar5416BeaconInit(struct ath_hal *ah, @@ -250,17 +166,6 @@ extern HAL_RFGAIN ar5416GetRfgain(struct ath_hal *ah); extern HAL_BOOL ar5416Disable(struct ath_hal *ah); extern HAL_BOOL ar5416ChipReset(struct ath_hal *ah, HAL_CHANNEL *); extern HAL_BOOL ar5416SetResetReg(struct ath_hal *, uint32_t type); -extern HAL_BOOL ar5416PerCalibration(struct ath_hal *, HAL_CHANNEL *, - HAL_BOOL *isIQdone); -extern void ar5416ResetCalValid(struct ath_hal *ah, HAL_CHANNEL *chan, - HAL_BOOL *isIQdone); -extern void ar5416IQCalCollect(struct ath_hal *ah); -extern void ar5416IQCalibration(struct ath_hal *ah, uint8_t numChains); -extern void ar5416AdcGainCalCollect(struct ath_hal *ah); -extern void ar5416AdcGainCalibration(struct ath_hal *ah, uint8_t numChains); -extern void ar5416AdcDcCalCollect(struct ath_hal *ah); -extern void ar5416AdcDcCalibration(struct ath_hal *ah, uint8_t numChains); -extern void ar5416InitNfHistBuff(struct ar5212NfCalHist *h); extern HAL_BOOL ar5416SetTxPowerLimit(struct ath_hal *ah, uint32_t limit); extern HAL_BOOL ar5416GetChipPowerLimits(struct ath_hal *ah, HAL_CHANNEL *chans, uint32_t nchans); diff --git a/ar5416/ar5416_ani.c b/ar5416/ar5416_ani.c new file mode 100644 index 000000000000..fbcab4d72039 --- /dev/null +++ b/ar5416/ar5416_ani.c @@ -0,0 +1,888 @@ +/* + * Copyright (c) 2002-2008 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. + * + * $Id: ar5416_ani.c,v 1.1 2008/11/11 20:46:06 sam Exp $ + */ +#include "opt_ah.h" + +#ifdef AH_SUPPORT_AR5416 +/* + * XXX this is virtually the same code as for 5212; we reuse + * storage in the 5212 state block; need to refactor. + */ +#include "ah.h" +#include "ah_internal.h" +#include "ah_desc.h" + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" + +/* + * Anti noise immunity support. We track phy errors and react + * to excessive errors by adjusting the noise immunity parameters. + */ + +#define HAL_EP_RND(x, mul) \ + ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul)) +#define BEACON_RSSI(ahp) \ + HAL_EP_RND(ahp->ah_stats.ast_nodestats.ns_avgbrssi, \ + HAL_RSSI_EP_MULTIPLIER) + +/* + * ANI processing tunes radio parameters according to PHY errors + * and related information. This is done for for noise and spur + * immunity in all operating modes if the device indicates it's + * capable at attach time. In addition, when there is a reference + * rssi value (e.g. beacon frames from an ap in station mode) + * further tuning is done. + * + * ANI_ENA indicates whether any ANI processing should be done; + * this is specified at attach time. + * + * ANI_ENA_RSSI indicates whether rssi-based processing should + * done, this is enabled based on operating mode and is meaningful + * only if ANI_ENA is true. + * + * ANI parameters are typically controlled only by the hal. The + * AniControl interface however permits manual tuning through the + * diagnostic api. + */ +#define ANI_ENA(ah) \ + (AH5212(ah)->ah_procPhyErr & HAL_ANI_ENA) +#define ANI_ENA_RSSI(ah) \ + (AH5212(ah)->ah_procPhyErr & HAL_RSSI_ANI_ENA) + +#define ah_mibStats ah_stats.ast_mibstats + +static void +enableAniMIBCounters(struct ath_hal *ah, const struct ar5212AniParams *params) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: Enable mib counters: " + "OfdmPhyErrBase 0x%x cckPhyErrBase 0x%x\n", + __func__, params->ofdmPhyErrBase, params->cckPhyErrBase); + + OS_REG_WRITE(ah, AR_FILTOFDM, 0); + OS_REG_WRITE(ah, AR_FILTCCK, 0); + + OS_REG_WRITE(ah, AR_PHYCNT1, params->ofdmPhyErrBase); + OS_REG_WRITE(ah, AR_PHYCNT2, params->cckPhyErrBase); + OS_REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); + OS_REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); + + ar5212UpdateMibCounters(ah, &ahp->ah_mibStats); /* save+clear counters*/ + ar5212EnableMibCounters(ah); /* enable everything */ +} + +static void +disableAniMIBCounters(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + HALDEBUG(ah, HAL_DEBUG_ANI, "Disable MIB counters\n"); + + ar5212UpdateMibCounters(ah, &ahp->ah_mibStats); /* save stats */ + ar5212DisableMibCounters(ah); /* disable everything */ + + OS_REG_WRITE(ah, AR_PHY_ERR_MASK_1, 0); + OS_REG_WRITE(ah, AR_PHY_ERR_MASK_2, 0); +} + +/* + * This routine returns the index into the aniState array that + * corresponds to the channel in *chan. If no match is found and the + * array is still not fully utilized, a new entry is created for the + * channel. We assume the attach function has already initialized the + * ah_ani values and only the channel field needs to be set. + */ +static int +ar5416GetAniChannelIndex(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan) +{ +#define N(a) (sizeof(a) / sizeof(a[0])) + struct ath_hal_5212 *ahp = AH5212(ah); + int i; + + for (i = 0; i < N(ahp->ah_ani); i++) { + struct ar5212AniState *asp = &ahp->ah_ani[i]; + if (asp->c.channel == chan->channel) + return i; + if (asp->c.channel == 0) { + asp->c.channel = chan->channel; + asp->c.channelFlags = chan->channelFlags; + asp->c.privFlags = chan->privFlags; + asp->isSetup = AH_FALSE; + if (IS_CHAN_2GHZ(chan)) + asp->params = &ahp->ah_aniParams24; + else + asp->params = &ahp->ah_aniParams5; + return i; + } + } + /* XXX statistic */ + HALDEBUG(ah, HAL_DEBUG_ANY, + "No more channel states left. Using channel 0\n"); + return 0; /* XXX gotta return something valid */ +#undef N +} + +static void +setPhyErrBase(struct ath_hal *ah, struct ar5212AniParams *params) +{ + if (params->ofdmTrigHigh >= AR_PHY_COUNTMAX) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "OFDM Trigger %d is too high for hw counters, using max\n", + params->ofdmTrigHigh); + params->ofdmPhyErrBase = 0; + } else + params->ofdmPhyErrBase = AR_PHY_COUNTMAX - params->ofdmTrigHigh; + if (params->cckTrigHigh >= AR_PHY_COUNTMAX) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "CCK Trigger %d is too high for hw counters, using max\n", + params->cckTrigHigh); + params->cckPhyErrBase = 0; + } else + params->cckPhyErrBase = AR_PHY_COUNTMAX - params->cckTrigHigh; +} + +/* + * Setup ANI handling. Sets all thresholds and reset the + * channel statistics. Note that ar5416AniReset should be + * called by ar5416Reset before anything else happens and + * that's where we force initial settings. + */ +void +ar5416AniAttach(struct ath_hal *ah, const struct ar5212AniParams *params24, + const struct ar5212AniParams *params5, HAL_BOOL enable) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + + if (params24 != AH_NULL) { + OS_MEMCPY(&ahp->ah_aniParams24, params24, sizeof(*params24)); + setPhyErrBase(ah, &ahp->ah_aniParams24); + } + if (params5 != AH_NULL) { + OS_MEMCPY(&ahp->ah_aniParams5, params5, sizeof(*params5)); + setPhyErrBase(ah, &ahp->ah_aniParams5); + } + + OS_MEMZERO(ahp->ah_ani, sizeof(ahp->ah_ani)); + /* Enable MIB Counters */ + enableAniMIBCounters(ah, &ahp->ah_aniParams24 /*XXX*/); + + if (enable) { /* Enable ani now */ + HALASSERT(params24 != AH_NULL && params5 != AH_NULL); + ahp->ah_procPhyErr |= HAL_ANI_ENA; + } else { + ahp->ah_procPhyErr &= ~HAL_ANI_ENA; + } +} + +/* + * Cleanup any ANI state setup. + */ +void +ar5416AniDetach(struct ath_hal *ah) +{ + HALDEBUG(ah, HAL_DEBUG_ANI, "Detaching Ani\n"); + disableAniMIBCounters(ah); +} + +/* + * Control Adaptive Noise Immunity Parameters + */ +HAL_BOOL +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; + + OS_MARK(ah, AH_MARK_ANI_CONTROL, cmd); + + switch (cmd) { + case HAL_ANI_NOISE_IMMUNITY_LEVEL: { + u_int level = param; + + if (level >= params->maxNoiseImmunityLevel) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: level out of range (%u > %u)\n", + __func__, level, params->maxNoiseImmunityLevel); + return AH_FALSE; + } + + OS_REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, + AR_PHY_DESIRED_SZ_TOT_DES, params->totalSizeDesired[level]); + OS_REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1, + AR_PHY_AGC_CTL1_COARSE_LOW, params->coarseLow[level]); + OS_REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1, + AR_PHY_AGC_CTL1_COARSE_HIGH, params->coarseHigh[level]); + OS_REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, + AR_PHY_FIND_SIG_FIRPWR, params->firpwr[level]); + + if (level > aniState->noiseImmunityLevel) + ahp->ah_stats.ast_ani_niup++; + else if (level < aniState->noiseImmunityLevel) + ahp->ah_stats.ast_ani_nidown++; + aniState->noiseImmunityLevel = level; + break; + } + case HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION: { + static const TABLE m1ThreshLow = { 127, 50 }; + static const TABLE m2ThreshLow = { 127, 40 }; + static const TABLE m1Thresh = { 127, 0x4d }; + static const TABLE m2Thresh = { 127, 0x40 }; + static const TABLE m2CountThr = { 31, 16 }; + static const TABLE m2CountThrLow = { 63, 48 }; + u_int on = param ? 1 : 0; + + 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, + AR_PHY_SFCORR_LOW_M2_THRESH_LOW, m2ThreshLow[on]); + OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR, + AR_PHY_SFCORR_M1_THRESH, m1Thresh[on]); + OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR, + AR_PHY_SFCORR_M2_THRESH, m2Thresh[on]); + OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR, + AR_PHY_SFCORR_M2COUNT_THR, m2CountThr[on]); + OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, m2CountThrLow[on]); + + OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, + AR_PHY_SFCORR_EXT_M1_THRESH_LOW, m1ThreshLow[on]); + OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, + AR_PHY_SFCORR_EXT_M2_THRESH_LOW, m2ThreshLow[on]); + OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, + AR_PHY_SFCORR_EXT_M1_THRESH, m1Thresh[on]); + OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, + AR_PHY_SFCORR_EXT_M2_THRESH, m2Thresh[on]); + + if (on) { + OS_REG_SET_BIT(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); + } else { + OS_REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); + } + if (on) + ahp->ah_stats.ast_ani_ofdmon++; + else + ahp->ah_stats.ast_ani_ofdmoff++; + aniState->ofdmWeakSigDetectOff = !on; + break; + } + case HAL_ANI_CCK_WEAK_SIGNAL_THR: { + static const TABLE weakSigThrCck = { 8, 6 }; + u_int high = param ? 1 : 0; + + OS_REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT, + AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK, weakSigThrCck[high]); + if (high) + ahp->ah_stats.ast_ani_cckhigh++; + else + ahp->ah_stats.ast_ani_ccklow++; + aniState->cckWeakSigThreshold = high; + break; + } + case HAL_ANI_FIRSTEP_LEVEL: { + u_int level = param; + + if (level >= params->maxFirstepLevel) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: level out of range (%u > %u)\n", + __func__, level, params->maxFirstepLevel); + return AH_FALSE; + } + OS_REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, + AR_PHY_FIND_SIG_FIRSTEP, params->firstep[level]); + if (level > aniState->firstepLevel) + ahp->ah_stats.ast_ani_stepup++; + else if (level < aniState->firstepLevel) + ahp->ah_stats.ast_ani_stepdown++; + aniState->firstepLevel = level; + break; + } + case HAL_ANI_SPUR_IMMUNITY_LEVEL: { + u_int level = param; + + if (level >= params->maxSpurImmunityLevel) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: 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]); + if (level > aniState->spurImmunityLevel) + ahp->ah_stats.ast_ani_spurup++; + else if (level < aniState->spurImmunityLevel) + ahp->ah_stats.ast_ani_spurdown++; + 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; + ahp->ah_stats.ast_ani_cckerrs = 0; + break; +#endif /* AH_PRIVATE_DIAG */ + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid cmd %u\n", + __func__, cmd); + return AH_FALSE; + } + return AH_TRUE; +} + +static void +ar5416AniOfdmErrTrigger(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + HAL_CHANNEL_INTERNAL *chan = AH_PRIVATE(ah)->ah_curchan; + struct ar5212AniState *aniState; + const struct ar5212AniParams *params; + + HALASSERT(chan != AH_NULL); + + if (!ANI_ENA(ah)) + return; + + aniState = ahp->ah_curani; + params = aniState->params; + /* First, raise noise immunity level, up to max */ + if (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) { + ar5416AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL, + aniState->spurImmunityLevel + 1); + return; + } + + if (ANI_ENA_RSSI(ah)) { + int32_t rssi = BEACON_RSSI(ahp); + if (rssi > params->rssiThrHigh) { + /* + * Beacon rssi is high, can turn off ofdm + * weak sig detect. + */ + if (!aniState->ofdmWeakSigDetectOff) { + ar5416AniControl(ah, + HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, + AH_FALSE); + ar5416AniControl(ah, + HAL_ANI_SPUR_IMMUNITY_LEVEL, 0); + return; + } + /* + * If weak sig detect is already off, as last resort, + * raise firstep level + */ + if (aniState->firstepLevel+1 < params->maxFirstepLevel) { + ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, + aniState->firstepLevel + 1); + return; + } + } else if (rssi > params->rssiThrLow) { + /* + * Beacon rssi in mid range, need ofdm weak signal + * detect, but we can raise firststepLevel. + */ + if (aniState->ofdmWeakSigDetectOff) + ar5416AniControl(ah, + HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, + AH_TRUE); + if (aniState->firstepLevel+1 < params->maxFirstepLevel) + ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, + aniState->firstepLevel + 1); + return; + } else { + /* + * Beacon rssi is low, if in 11b/g mode, turn off ofdm + * weak signal detection and zero firstepLevel to + * maximize CCK sensitivity + */ + /* XXX can optimize */ + if (IS_CHAN_B(chan) || IS_CHAN_G(chan)) { + if (!aniState->ofdmWeakSigDetectOff) + ar5416AniControl(ah, + HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, + AH_FALSE); + if (aniState->firstepLevel > 0) + ar5416AniControl(ah, + HAL_ANI_FIRSTEP_LEVEL, 0); + return; + } + } + } +} + +static void +ar5416AniCckErrTrigger(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + HAL_CHANNEL_INTERNAL *chan = AH_PRIVATE(ah)->ah_curchan; + struct ar5212AniState *aniState; + const struct ar5212AniParams *params; + + HALASSERT(chan != AH_NULL); + + if (!ANI_ENA(ah)) + return; + + /* first, raise noise immunity level, up to max */ + aniState = ahp->ah_curani; + params = aniState->params; + if (aniState->noiseImmunityLevel+1 < params->maxNoiseImmunityLevel) { + ar5416AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, + aniState->noiseImmunityLevel + 1); + return; + } + + if (ANI_ENA_RSSI(ah)) { + int32_t rssi = BEACON_RSSI(ahp); + if (rssi > params->rssiThrLow) { + /* + * Beacon signal in mid and high range, + * raise firstep level. + */ + if (aniState->firstepLevel+1 < params->maxFirstepLevel) + ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, + aniState->firstepLevel + 1); + } else { + /* + * Beacon rssi is low, zero firstep level to maximize + * CCK sensitivity in 11b/g mode. + */ + /* XXX can optimize */ + if (IS_CHAN_B(chan) || IS_CHAN_G(chan)) { + if (aniState->firstepLevel > 0) + ar5416AniControl(ah, + HAL_ANI_FIRSTEP_LEVEL, 0); + } + } + } +} + +static void +ar5416AniRestart(struct ath_hal *ah, struct ar5212AniState *aniState) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + const struct ar5212AniParams *params = aniState->params; + + aniState->listenTime = 0; + /* + * NB: these are written on reset based on the + * ini so we must re-write them! + */ + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: Writing ofdmbase=%u cckbase=%u\n", __func__, + params->ofdmPhyErrBase, params->cckPhyErrBase); + 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); + + /* Clear the mib counters and save them in the stats */ + ar5212UpdateMibCounters(ah, &ahp->ah_mibStats); + aniState->ofdmPhyErrCount = 0; + aniState->cckPhyErrCount = 0; +} + +/* + * Restore/reset the ANI parameters and reset the statistics. + * This routine must be called for every channel change. + * + * NOTE: This is where ah_curani is set; other ani code assumes + * it is setup to reflect the current channel. + */ +void +ar5416AniReset(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan, + HAL_OPMODE opmode, int restore) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + struct ar5212AniState *aniState; + uint32_t rxfilter; + int index; + + index = ar5416GetAniChannelIndex(ah, chan); + aniState = &ahp->ah_ani[index]; + ahp->ah_curani = aniState; +#if 0 + ath_hal_printf(ah,"%s: chan %u/0x%x restore %d setup %d opmode %u\n", + __func__, chan->channel, chan->channelFlags, restore, + aniState->isSetup, opmode); +#else + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: chan %u/0x%x restore %d setup %d opmode %u\n", + __func__, chan->channel, chan->channelFlags, restore, + aniState->isSetup, opmode); +#endif + OS_MARK(ah, AH_MARK_ANI_RESET, opmode); + + /* + * Turn off PHY error frame delivery while we futz with settings. + */ + rxfilter = ar5212GetRxFilter(ah); + ar5212SetRxFilter(ah, rxfilter &~ HAL_RX_FILTER_PHYERR); + /* + * Automatic processing is done only in station mode right now. + */ + if (opmode == HAL_M_STA) + ahp->ah_procPhyErr |= HAL_RSSI_ANI_ENA; + else + ahp->ah_procPhyErr &= ~HAL_RSSI_ANI_ENA; + /* + * Set all ani parameters. We either set them to initial + * values or restore the previous ones for the channel. + * XXX if ANI follows hardware, we don't care what mode we're + * XXX in, we should keep the ani parameters + */ + if (restore && aniState->isSetup) { + ar5416AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, + aniState->noiseImmunityLevel); + ar5416AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL, + aniState->spurImmunityLevel); + ar5416AniControl(ah, HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, + !aniState->ofdmWeakSigDetectOff); + ar5416AniControl(ah, HAL_ANI_CCK_WEAK_SIGNAL_THR, + aniState->cckWeakSigThreshold); + ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, + aniState->firstepLevel); + } else { + ar5416AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, 0); + ar5416AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL, 0); + ar5416AniControl(ah, HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, + AH_TRUE); + ar5416AniControl(ah, HAL_ANI_CCK_WEAK_SIGNAL_THR, AH_FALSE); + ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, 0); + aniState->isSetup = AH_TRUE; + } + ar5416AniRestart(ah, aniState); + + /* restore RX filter mask */ + ar5212SetRxFilter(ah, rxfilter); +} + +/* + * Process a MIB interrupt. We may potentially be invoked because + * any of the MIB counters overflow/trigger so don't assume we're + * here because a PHY error counter triggered. + */ +void +ar5416ProcessMibIntr(struct ath_hal *ah, const HAL_NODE_STATS *stats) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + uint32_t phyCnt1, phyCnt2; + + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: mibc 0x%x phyCnt1 0x%x phyCnt2 0x%x " + "filtofdm 0x%x filtcck 0x%x\n", + __func__, OS_REG_READ(ah, AR_MIBC), + OS_REG_READ(ah, AR_PHYCNT1), OS_REG_READ(ah, AR_PHYCNT2), + OS_REG_READ(ah, AR_FILTOFDM), OS_REG_READ(ah, AR_FILTCCK)); + + /* + * First order of business is to clear whatever caused + * the interrupt so we don't keep getting interrupted. + * We have the usual mib counters that are reset-on-read + * and the additional counters that appeared starting in + * Hainan. We collect the mib counters and explicitly + * zero additional counters we are not using. Anything + * else is reset only if it caused the interrupt. + */ + /* NB: these are not reset-on-read */ + phyCnt1 = OS_REG_READ(ah, AR_PHY_ERR_1); + phyCnt2 = OS_REG_READ(ah, AR_PHY_ERR_2); + /* not used, always reset them in case they are the cause */ + OS_REG_WRITE(ah, AR_FILTOFDM, 0); + OS_REG_WRITE(ah, AR_FILTCCK, 0); + if ((OS_REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING) == 0) + OS_REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR); + + /* Clear the mib counters and save them in the stats */ + ar5212UpdateMibCounters(ah, &ahp->ah_mibStats); + ahp->ah_stats.ast_nodestats = *stats; + + /* + * Check for an ani stat hitting the trigger threshold. + * When this happens we get a MIB interrupt and the top + * 2 bits of the counter register will be 0b11, hence + * the mask check of phyCnt?. + */ + if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) || + ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) { + struct ar5212AniState *aniState = ahp->ah_curani; + const struct ar5212AniParams *params = aniState->params; + uint32_t ofdmPhyErrCnt, cckPhyErrCnt; + + ofdmPhyErrCnt = phyCnt1 - params->ofdmPhyErrBase; + ahp->ah_stats.ast_ani_ofdmerrs += + ofdmPhyErrCnt - aniState->ofdmPhyErrCount; + aniState->ofdmPhyErrCount = ofdmPhyErrCnt; + + cckPhyErrCnt = phyCnt2 - params->cckPhyErrBase; + ahp->ah_stats.ast_ani_cckerrs += + cckPhyErrCnt - aniState->cckPhyErrCount; + aniState->cckPhyErrCount = cckPhyErrCnt; + + /* + * NB: figure out which counter triggered. If both + * trigger we'll only deal with one as the processing + * clobbers the error counter so the trigger threshold + * check will never be true. + */ + if (aniState->ofdmPhyErrCount > params->ofdmTrigHigh) + ar5416AniOfdmErrTrigger(ah); + if (aniState->cckPhyErrCount > params->cckTrigHigh) + ar5416AniCckErrTrigger(ah); + /* NB: always restart to insure the h/w counters are reset */ + ar5416AniRestart(ah, aniState); + } +} + +static void +ar5416AniLowerImmunity(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + struct ar5212AniState *aniState; + const struct ar5212AniParams *params; + + HALASSERT(ANI_ENA(ah)); + + aniState = ahp->ah_curani; + params = aniState->params; + if (ANI_ENA_RSSI(ah)) { + int32_t rssi = BEACON_RSSI(ahp); + if (rssi > params->rssiThrHigh) { + /* + * Beacon signal is high, leave ofdm weak signal + * detection off or it may oscillate. Let it fall + * through. + */ + } else if (rssi > params->rssiThrLow) { + /* + * Beacon rssi in mid range, turn on ofdm weak signal + * detection or lower firstep level. + */ + if (aniState->ofdmWeakSigDetectOff) { + ar5416AniControl(ah, + HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, + AH_TRUE); + return; + } + if (aniState->firstepLevel > 0) { + ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, + aniState->firstepLevel - 1); + return; + } + } else { + /* + * Beacon rssi is low, reduce firstep level. + */ + if (aniState->firstepLevel > 0) { + ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, + aniState->firstepLevel - 1); + return; + } + } + } + /* then lower spur immunity level, down to zero */ + if (aniState->spurImmunityLevel > 0) { + ar5416AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL, + aniState->spurImmunityLevel - 1); + return; + } + /* + * if all else fails, lower noise immunity level down to a min value + * zero for now + */ + if (aniState->noiseImmunityLevel > 0) { + ar5416AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, + aniState->noiseImmunityLevel - 1); + return; + } +} + +#define CLOCK_RATE 44000 /* XXX use mac_usec or similar */ +/* convert HW counter values to ms using 11g clock rate, goo9d enough + for 11a and Turbo */ + +/* + * Return an approximation of the time spent ``listening'' by + * deducting the cycles spent tx'ing and rx'ing from the total + * cycle count since our last call. A return value <0 indicates + * an invalid/inconsistent time. + */ +static int32_t +ar5416AniGetListenTime(struct ath_hal *ah) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + struct ar5212AniState *aniState; + uint32_t txFrameCount, rxFrameCount, cycleCount; + int32_t listenTime; + + txFrameCount = OS_REG_READ(ah, AR_TFCNT); + rxFrameCount = OS_REG_READ(ah, AR_RFCNT); + cycleCount = OS_REG_READ(ah, AR_CCCNT); + + aniState = ahp->ah_curani; + if (aniState->cycleCount == 0 || aniState->cycleCount > cycleCount) { + /* + * Cycle counter wrap (or initial call); it's not possible + * to accurately calculate a value because the registers + * right shift rather than wrap--so punt and return 0. + */ + listenTime = 0; + ahp->ah_stats.ast_ani_lzero++; + } else { + int32_t ccdelta = cycleCount - aniState->cycleCount; + int32_t rfdelta = rxFrameCount - aniState->rxFrameCount; + int32_t tfdelta = txFrameCount - aniState->txFrameCount; + listenTime = (ccdelta - rfdelta - tfdelta) / CLOCK_RATE; + } + aniState->cycleCount = cycleCount; + aniState->txFrameCount = txFrameCount; + aniState->rxFrameCount = rxFrameCount; + return listenTime; +} + +/* + * Update ani stats in preparation for listen time processing. + */ +static void +updateMIBStats(struct ath_hal *ah, struct ar5212AniState *aniState) +{ + struct ath_hal_5212 *ahp = AH5212(ah); + const struct ar5212AniParams *params = aniState->params; + uint32_t phyCnt1, phyCnt2; + int32_t ofdmPhyErrCnt, cckPhyErrCnt; + + /* Clear the mib counters and save them in the stats */ + ar5212UpdateMibCounters(ah, &ahp->ah_mibStats); + + /* NB: these are not reset-on-read */ + phyCnt1 = OS_REG_READ(ah, AR_PHY_ERR_1); + phyCnt2 = OS_REG_READ(ah, AR_PHY_ERR_2); + + /* NB: these are spec'd to never roll-over */ + ofdmPhyErrCnt = phyCnt1 - params->ofdmPhyErrBase; + if (ofdmPhyErrCnt < 0) { + HALDEBUG(ah, HAL_DEBUG_ANI, "OFDM phyErrCnt %d phyCnt1 0x%x\n", + ofdmPhyErrCnt, phyCnt1); + ofdmPhyErrCnt = AR_PHY_COUNTMAX; + } + ahp->ah_stats.ast_ani_ofdmerrs += + ofdmPhyErrCnt - aniState->ofdmPhyErrCount; + aniState->ofdmPhyErrCount = ofdmPhyErrCnt; + + cckPhyErrCnt = phyCnt2 - params->cckPhyErrBase; + if (cckPhyErrCnt < 0) { + HALDEBUG(ah, HAL_DEBUG_ANI, "CCK phyErrCnt %d phyCnt2 0x%x\n", + cckPhyErrCnt, phyCnt2); + cckPhyErrCnt = AR_PHY_COUNTMAX; + } + ahp->ah_stats.ast_ani_cckerrs += + cckPhyErrCnt - aniState->cckPhyErrCount; + aniState->cckPhyErrCount = cckPhyErrCnt; +} + +/* + * 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, + HAL_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; + if (!ANI_ENA(ah)) + return; + + listenTime = ar5416AniGetListenTime(ah); + if (listenTime < 0) { + ahp->ah_stats.ast_ani_lneg++; + /* restart ANI period if listenTime is invalid */ + ar5416AniRestart(ah, aniState); + } + /* XXX beware of overflow? */ + aniState->listenTime += listenTime; + + OS_MARK(ah, AH_MARK_ANI_POLL, aniState->listenTime); + + params = aniState->params; + if (aniState->listenTime > 5*params->period) { + /* + * Check to see if need to lower immunity if + * 5 aniPeriods have passed + */ + updateMIBStats(ah, aniState); + if (aniState->ofdmPhyErrCount <= aniState->listenTime * + params->ofdmTrigLow/1000 && + aniState->cckPhyErrCount <= aniState->listenTime * + params->cckTrigLow/1000) + ar5416AniLowerImmunity(ah); + ar5416AniRestart(ah, aniState); + } else if (aniState->listenTime > params->period) { + updateMIBStats(ah, aniState); + /* check to see if need to raise immunity */ + if (aniState->ofdmPhyErrCount > aniState->listenTime * + params->ofdmTrigHigh / 1000) { + ar5416AniOfdmErrTrigger(ah); + ar5416AniRestart(ah, aniState); + } else if (aniState->cckPhyErrCount > aniState->listenTime * + params->cckTrigHigh / 1000) { + ar5416AniCckErrTrigger(ah); + ar5416AniRestart(ah, aniState); + } + } +} +#endif /* AH_SUPPORT_AR5416 */ diff --git a/ar5416/ar5416_attach.c b/ar5416/ar5416_attach.c index 6d489fff8ed2..49ebfa51ffa1 100644 --- a/ar5416/ar5416_attach.c +++ b/ar5416/ar5416_attach.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: ar5416_attach.c,v 1.19 2008/11/10 04:08:04 sam Exp $ + * $Id: ar5416_attach.c,v 1.27 2008/11/27 22:30:07 sam Exp $ */ #include "opt_ah.h" @@ -83,6 +83,8 @@ ar5416InitState(struct ath_hal_5416 *ahp5416, uint16_t devid, HAL_SOFTC sc, ah->ah_phyDisable = ar5416PhyDisable; ah->ah_disable = ar5416Disable; ah->ah_perCalibration = ar5416PerCalibration; + ah->ah_perCalibrationN = ar5416PerCalibrationN, + ah->ah_resetCalValid = ar5416ResetCalValid, ah->ah_setTxPowerLimit = ar5416SetTxPowerLimit; /* Transmit functions */ @@ -97,6 +99,8 @@ ar5416InitState(struct ath_hal_5416 *ahp5416, uint16_t devid, HAL_SOFTC sc, ah->ah_stopPcuReceive = ar5416StopPcuReceive; ah->ah_setupRxDesc = ar5416SetupRxDesc; ah->ah_procRxDesc = ar5416ProcRxDesc; + ah->ah_rxMonitor = ar5416AniPoll, + ah->ah_procMibEvent = ar5416ProcessMibIntr, /* Misc Functions */ ah->ah_getDiagState = ar5416GetDiagState; @@ -157,24 +161,10 @@ ar5416InitState(struct ath_hal_5416 *ahp5416, uint16_t devid, HAL_SOFTC sc, ahp->ah_priv.ah_getChipPowerLimits = ar5416GetChipPowerLimits; /* - * XXX - Do we need a board specific chain mask? * Start by setting all Owl devices to 2x2 */ AH5416(ah)->ah_rx_chainmask = AR5416_DEFAULT_RXCHAINMASK; AH5416(ah)->ah_tx_chainmask = AR5416_DEFAULT_TXCHAINMASK; - AH5416(ah)->ah_clksel = 0; /* XXX */ - /* NB: ah_keytype is initialized to zero which is ok */ -#if 0 - ah->ah_descinfo.rxctl_numwords = RXCTL_NUMWORDS(ah); - ah->ah_descinfo.rxctl_offset = RXCTL_OFFSET(ah); - ah->ah_descinfo.rxstatus_numwords = RXSTATUS_NUMWORDS(ah); - ah->ah_descinfo.rxstatus_offset = RXSTATUS_OFFSET(ah); - - ah->ah_descinfo.txctl_numwords = TXCTL_NUMWORDS(ah); - ah->ah_descinfo.txctl_offset = TXCTL_OFFSET(ah); - ah->ah_descinfo.txstatus_numwords = TXSTATUS_NUMWORDS(ah); - ah->ah_descinfo.txstatus_offset = TXSTATUS_OFFSET(ah); -#endif } /* @@ -330,7 +320,7 @@ ar5416Attach(uint16_t devid, HAL_SOFTC sc, * 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 + * placed into hardware. */ if (ahp->ah_miscMode != 0) OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode); @@ -344,9 +334,8 @@ ar5416Attach(uint16_t devid, HAL_SOFTC sc, goto bad; } - ar5212InitializeGainValues(ah); /* gain ladder */ ar5416AniSetup(ah); /* Anti Noise Immunity */ - ar5416InitNfHistBuff(AH5416(ah)->ah_nfCalHist); + ar5416InitNfHistBuff(AH5416(ah)->ah_cal.nfCalHist); HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__); @@ -367,7 +356,7 @@ ar5416Detach(struct ath_hal *ah) HALASSERT(ah != AH_NULL); HALASSERT(ah->ah_magic == AR5416_MAGIC); - ar5212AniDetach(ah); + ar5416AniDetach(ah); ar5212RfDetach(ah); ah->ah_disable(ah); ar5416SetPowerMode(ah, HAL_PM_FULL_SLEEP, AH_TRUE); diff --git a/ar5416/ar5416_beacon.c b/ar5416/ar5416_beacon.c index 43d03175fd72..ed3812d5427f 100644 --- a/ar5416/ar5416_beacon.c +++ b/ar5416/ar5416_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: ar5416_beacon.c,v 1.7 2008/11/10 04:08:04 sam Exp $ + * $Id: ar5416_beacon.c,v 1.8 2008/11/11 01:03:12 sam Exp $ */ #include "opt_ah.h" @@ -32,7 +32,7 @@ /* * Initialize all of the hardware registers used to * send beacons. Note that for station operation the - * driver calls ar5212SetStaBeaconTimers instead. + * driver calls ar5416SetStaBeaconTimers instead. */ void ar5416SetBeaconTimers(struct ath_hal *ah, const HAL_BEACON_TIMERS *bt) diff --git a/ar5416/ar5416_cal.c b/ar5416/ar5416_cal.c new file mode 100644 index 000000000000..1f2314b372ee --- /dev/null +++ b/ar5416/ar5416_cal.c @@ -0,0 +1,669 @@ +/* + * Copyright (c) 2002-2008 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. + * + * $Id: ar5416_cal.c,v 1.7 2008/11/11 17:43:23 sam Exp $ + */ +#include "opt_ah.h" + +#ifdef AH_SUPPORT_AR5416 + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ah_eeprom_v14.h" + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" +#ifdef AH_SUPPORT_AR9280 +#include "ar5416/ar9280.h" +#endif + +/* Owl specific stuff */ +#define NUM_NOISEFLOOR_READINGS 6 /* 3 chains * (ctl + ext) */ + +static void ar5416StartNFCal(struct ath_hal *ah); +static void ar5416LoadNF(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *); +static int16_t ar5416GetNf(struct ath_hal *, HAL_CHANNEL_INTERNAL *); + +/* + * Determine if calibration is supported by device and channel flags + */ +static OS_INLINE HAL_BOOL +ar5416IsCalSupp(struct ath_hal *ah, HAL_CHANNEL *chan, HAL_CAL_TYPE calType) +{ + struct ar5416PerCal *cal = &AH5416(ah)->ah_cal; + + switch (calType & cal->suppCals) { + case IQ_MISMATCH_CAL: + /* Run IQ Mismatch for non-CCK only */ + return !IS_CHAN_B(chan); + case ADC_GAIN_CAL: + case ADC_DC_CAL: + /* Run ADC Gain Cal for non-CCK & non 2GHz-HT20 only */ + return !IS_CHAN_B(chan) && + !(IS_CHAN_2GHZ(chan) && IS_CHAN_HT20(chan)); + } + return AH_FALSE; +} + +/* + * Setup HW to collect samples used for current cal + */ +static void +ar5416SetupMeasurement(struct ath_hal *ah, HAL_CAL_LIST *currCal) +{ + /* Start calibration w/ 2^(INIT_IQCAL_LOG_COUNT_MAX+1) samples */ + OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4, + AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX, + currCal->calData->calCountMax); + + /* Select calibration to run */ + switch (currCal->calData->calType) { + case IQ_MISMATCH_CAL: + OS_REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "%s: start IQ Mismatch calibration\n", __func__); + break; + case ADC_GAIN_CAL: + OS_REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "%s: start ADC Gain calibration\n", __func__); + break; + case ADC_DC_CAL: + OS_REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "%s: start ADC DC calibration\n", __func__); + break; + case ADC_DC_INIT_CAL: + OS_REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "%s: start Init ADC DC calibration\n", __func__); + break; + } + /* Kick-off cal */ + OS_REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4, AR_PHY_TIMING_CTRL4_DO_CAL); +} + +/* + * Initialize shared data structures and prepare a cal to be run. + */ +static void +ar5416ResetMeasurement(struct ath_hal *ah, HAL_CAL_LIST *currCal) +{ + struct ar5416PerCal *cal = &AH5416(ah)->ah_cal; + + /* Reset data structures shared between different calibrations */ + OS_MEMZERO(cal->caldata, sizeof(cal->caldata)); + cal->calSamples = 0; + + /* Setup HW for new calibration */ + ar5416SetupMeasurement(ah, currCal); + + /* Change SW state to RUNNING for this calibration */ + currCal->calState = CAL_RUNNING; +} + +#if 0 +/* + * Run non-periodic calibrations. + */ +static HAL_BOOL +ar5416RunInitCals(struct ath_hal *ah, int init_cal_count) +{ + struct ath_hal_5416 *ahp = AH5416(ah); + struct ar5416PerCal *cal = &AH5416(ah)->ah_cal; + HAL_CHANNEL_INTERNAL ichan; /* XXX bogus */ + HAL_CAL_LIST *curCal = ahp->ah_cal_curr; + HAL_BOOL isCalDone; + int i; + + if (curCal == AH_NULL) + return AH_FALSE; + + ichan.calValid = 0; + for (i = 0; i < init_cal_count; i++) { + /* Reset this Cal */ + ar5416ResetMeasurement(ah, curCal); + /* Poll for offset calibration complete */ + if (!ath_hal_wait(ah, AR_PHY_TIMING_CTRL4, AR_PHY_TIMING_CTRL4_DO_CAL, 0)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: Cal %d failed to finish in 100ms.\n", + __func__, curCal->calData->calType); + /* Re-initialize list pointers for periodic cals */ + cal->cal_list = cal->cal_last = cal->cal_curr = AH_NULL; + return AH_FALSE; + } + /* Run this cal */ + ar5416DoCalibration(ah, &ichan, ahp->ah_rxchainmask, + curCal, &isCalDone); + if (!isCalDone) + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: init cal %d did not complete.\n", + __func__, curCal->calData->calType); + if (curCal->calNext != AH_NULL) + curCal = curCal->calNext; + } + + /* Re-initialize list pointers for periodic cals */ + cal->cal_list = cal->cal_last = cal->cal_curr = AH_NULL; + return AH_TRUE; +} +#endif + +/* + * Initialize Calibration infrastructure. + */ +HAL_BOOL +ar5416InitCal(struct ath_hal *ah, HAL_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)) { + /* 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 */ + 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 did not complete in 1ms; " + "noisy environment?\n", __func__); + return AH_FALSE; + } + + /* + * Do NF calibration after DC offset and other CALs. + * Per system engineers, noise floor value can sometimes be 20 dB + * higher than normal value if DC offset and noise floor cal are + * triggered at the same time. + */ + OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); + + /* 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)) { + /* Setup all non-periodic, init time only calibrations */ + /* XXX: Init DC Offset not working yet */ +#if 0 + if (ar5416IsCalSupp(ah, chan, ADC_DC_INIT_CAL)) { + INIT_CAL(&cal->adcDcCalInitData); + INSERT_CAL(cal, &cal->adcDcCalInitData); + } + /* Initialize current pointer to first element in list */ + cal->cal_curr = cal->cal_list; + + if (cal->ah_cal_curr != AH_NULL && !ar5416RunInitCals(ah, 0)) + return AH_FALSE; +#endif + } + + /* If Cals are supported, add them to list via INIT/INSERT_CAL */ + if (ar5416IsCalSupp(ah, chan, ADC_GAIN_CAL)) { + INIT_CAL(&cal->adcGainCalData); + INSERT_CAL(cal, &cal->adcGainCalData); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "%s: enable ADC Gain Calibration.\n", __func__); + } + if (ar5416IsCalSupp(ah, chan, ADC_DC_CAL)) { + INIT_CAL(&cal->adcDcCalData); + INSERT_CAL(cal, &cal->adcDcCalData); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "%s: enable ADC DC Calibration.\n", __func__); + } + if (ar5416IsCalSupp(ah, chan, IQ_MISMATCH_CAL)) { + INIT_CAL(&cal->iqCalData); + INSERT_CAL(cal, &cal->iqCalData); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "%s: enable IQ Calibration.\n", __func__); + } + /* Initialize current pointer to first element in list */ + cal->cal_curr = cal->cal_list; + + /* Kick off measurements for the first cal */ + if (cal->cal_curr != AH_NULL) + ar5416ResetMeasurement(ah, cal->cal_curr); + + /* Mark all calibrations on this channel as being invalid */ + ichan->calValid = 0; + + return AH_TRUE; +} + +/* + * Entry point for upper layers to restart current cal. + * Reset the calibration valid bit in channel. + */ +HAL_BOOL +ar5416ResetCalValid(struct ath_hal *ah, HAL_CHANNEL *chan) +{ + struct ar5416PerCal *cal = &AH5416(ah)->ah_cal; + HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan); + HAL_CAL_LIST *currCal = cal->cal_curr; + + if (!AR_SREV_SOWL_10_OR_LATER(ah)) + return AH_FALSE; + if (currCal == AH_NULL) + return AH_FALSE; + if (ichan == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid channel %u/0x%x; no mapping\n", + __func__, chan->channel, chan->channelFlags); + return AH_FALSE; + } + /* + * Expected that this calibration has run before, post-reset. + * Current state should be done + */ + if (currCal->calState != CAL_DONE) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: Calibration state incorrect, %d\n", + __func__, currCal->calState); + return AH_FALSE; + } + + /* Verify Cal is supported on this channel */ + if (!ar5416IsCalSupp(ah, chan, currCal->calData->calType)) + return AH_FALSE; + + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "%s: Resetting Cal %d state for channel %u/0x%x\n", + __func__, currCal->calData->calType, chan->channel, + chan->channelFlags); + + /* Disable cal validity in channel */ + ichan->calValid &= ~currCal->calData->calType; + currCal->calState = CAL_WAITING; + + return AH_TRUE; +} + +/* + * Recalibrate the lower PHY chips to account for temperature/environment + * changes. + */ +static void +ar5416DoCalibration(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *ichan, + uint8_t rxchainmask, HAL_CAL_LIST *currCal, HAL_BOOL *isCalDone) +{ + struct ar5416PerCal *cal = &AH5416(ah)->ah_cal; + + /* Cal is assumed not done until explicitly set below */ + *isCalDone = AH_FALSE; + + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "%s: %s Calibration, state %d, calValid 0x%x\n", + __func__, currCal->calData->calName, currCal->calState, + ichan->calValid); + + /* Calibration in progress. */ + if (currCal->calState == CAL_RUNNING) { + /* Check to see if it has finished. */ + if (!(OS_REG_READ(ah, AR_PHY_TIMING_CTRL4) & AR_PHY_TIMING_CTRL4_DO_CAL)) { + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "%s: sample %d of %d finished\n", + __func__, cal->calSamples, + currCal->calData->calNumSamples); + /* + * Collect measurements for active chains. + */ + currCal->calData->calCollect(ah); + if (++cal->calSamples >= currCal->calData->calNumSamples) { + int i, numChains = 0; + for (i = 0; i < AR5416_MAX_CHAINS; i++) { + if (rxchainmask & (1 << i)) + numChains++; + } + /* + * Process accumulated data + */ + currCal->calData->calPostProc(ah, numChains); + + /* Calibration has finished. */ + ichan->calValid |= currCal->calData->calType; + currCal->calState = CAL_DONE; + *isCalDone = AH_TRUE; + } else { + /* + * Set-up to collect of another sub-sample. + */ + ar5416SetupMeasurement(ah, currCal); + } + } + } else if (!(ichan->calValid & currCal->calData->calType)) { + /* If current cal is marked invalid in channel, kick it off */ + ar5416ResetMeasurement(ah, currCal); + } +} + +/* + * Internal interface to schedule periodic calibration work. + */ +HAL_BOOL +ar5416PerCalibrationN(struct ath_hal *ah, HAL_CHANNEL *chan, + u_int rxchainmask, HAL_BOOL longcal, HAL_BOOL *isCalDone) +{ + struct ar5416PerCal *cal = &AH5416(ah)->ah_cal; + HAL_CAL_LIST *currCal = cal->cal_curr; + HAL_CHANNEL_INTERNAL *ichan; + + OS_MARK(ah, AH_MARK_PERCAL, chan->channel); + + *isCalDone = AH_TRUE; + + /* Invalid channel check */ + ichan = ath_hal_checkchannel(ah, chan); + if (ichan == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid channel %u/0x%x; no mapping\n", + __func__, chan->channel, chan->channelFlags); + return AH_FALSE; + } + + /* + * For given calibration: + * 1. Call generic cal routine + * 2. When this cal is done (isCalDone) if we have more cals waiting + * (eg after reset), mask this to upper layers by not propagating + * isCalDone if it is set to TRUE. + * Instead, change isCalDone to FALSE and setup the waiting cal(s) + * to be run. + */ + if (currCal != AH_NULL && + (currCal->calState == CAL_RUNNING || + currCal->calState == CAL_WAITING)) { + ar5416DoCalibration(ah, ichan, rxchainmask, currCal, isCalDone); + if (*isCalDone == AH_TRUE) { + cal->cal_curr = currCal = currCal->calNext; + if (currCal->calState == CAL_WAITING) { + *isCalDone = AH_FALSE; + ar5416ResetMeasurement(ah, currCal); + } + } + } + + /* Do NF cal only at longer intervals */ + if (longcal) { + /* + * Get the value from the previous NF cal + * and update the history buffer. + */ + ar5416GetNf(ah, ichan); + + /* + * 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); + + if ((ichan->channelFlags & CHANNEL_CW_INT) != 0) { + /* report up and clear internal state */ + chan->channelFlags |= CHANNEL_CW_INT; + ichan->channelFlags &= ~CHANNEL_CW_INT; + } + } + return AH_TRUE; +} + +/* + * Recalibrate the lower PHY chips to account for temperature/environment + * changes. + */ +HAL_BOOL +ar5416PerCalibration(struct ath_hal *ah, HAL_CHANNEL *chan, HAL_BOOL *isIQdone) +{ + struct ath_hal_5416 *ahp = AH5416(ah); + struct ar5416PerCal *cal = &AH5416(ah)->ah_cal; + HAL_CAL_LIST *curCal = cal->cal_curr; + + if (curCal != AH_NULL && curCal->calData->calType == IQ_MISMATCH_CAL) { + return ar5416PerCalibrationN(ah, chan, ahp->ah_rx_chainmask, + AH_TRUE, isIQdone); + } else { + HAL_BOOL isCalDone; + + *isIQdone = AH_FALSE; + return ar5416PerCalibrationN(ah, chan, ahp->ah_rx_chainmask, + AH_TRUE, &isCalDone); + } +} + +static HAL_BOOL +ar5416GetEepromNoiseFloorThresh(struct ath_hal *ah, + const HAL_CHANNEL_INTERNAL *chan, int16_t *nft) +{ + switch (chan->channelFlags & CHANNEL_ALL_NOTURBO) { + case CHANNEL_A: + case CHANNEL_A_HT20: + case CHANNEL_A_HT40PLUS: + case CHANNEL_A_HT40MINUS: + ath_hal_eepromGet(ah, AR_EEP_NFTHRESH_5, nft); + break; + case CHANNEL_B: + case CHANNEL_G: + case CHANNEL_G_HT20: + case CHANNEL_G_HT40PLUS: + case CHANNEL_G_HT40MINUS: + ath_hal_eepromGet(ah, AR_EEP_NFTHRESH_2, nft); + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid channel flags 0x%x\n", + __func__, chan->channelFlags); + return AH_FALSE; + } + return AH_TRUE; +} + +static void +ar5416StartNFCal(struct ath_hal *ah) +{ + OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_ENABLE_NF); + OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NO_UPDATE_NF); + OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); +} + +static void +ar5416LoadNF(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan) +{ + static const uint32_t ar5416_cca_regs[] = { + AR_PHY_CCA, + AR_PHY_CH1_CCA, + AR_PHY_CH2_CCA, + AR_PHY_EXT_CCA, + AR_PHY_CH1_EXT_CCA, + AR_PHY_CH2_EXT_CCA + }; + struct ar5212NfCalHist *h; + int i, j; + int32_t val; + uint8_t chainmask; + + /* + * Force NF calibration for all chains. + */ + if (AR_SREV_KITE(ah)) { + /* Kite has only one chain */ + chainmask = 0x9; + } else if (AR_SREV_MERLIN(ah)) { + /* Merlin has only two chains */ + chainmask = 0x1B; + } else { + chainmask = 0x3F; + } + + /* + * Write filtered NF values into maxCCApwr register parameter + * so we can load below. + */ + h = AH5416(ah)->ah_cal.nfCalHist; + for (i = 0; i < AR5416_NUM_NF_READINGS; i ++) + if (chainmask & (1 << i)) { + val = OS_REG_READ(ah, ar5416_cca_regs[i]); + val &= 0xFFFFFE00; + val |= (((uint32_t)(h[i].privNF) << 1) & 0x1ff); + OS_REG_WRITE(ah, ar5416_cca_regs[i], val); + } + + /* 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); + OS_REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NO_UPDATE_NF); + 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); + } + + /* + * Restore maxCCAPower register parameter again so that we're not capped + * by the median we just loaded. This will be initial (and max) value + * of next noise floor calibration the baseband does. + */ + for (i = 0; i < AR5416_NUM_NF_READINGS; i ++) + if (chainmask & (1 << i)) { + val = OS_REG_READ(ah, ar5416_cca_regs[i]); + val &= 0xFFFFFE00; + val |= (((uint32_t)(-50) << 1) & 0x1ff); + OS_REG_WRITE(ah, ar5416_cca_regs[i], val); + } +} + +void +ar5416InitNfHistBuff(struct ar5212NfCalHist *h) +{ + int i, j; + + for (i = 0; i < AR5416_NUM_NF_READINGS; i ++) { + h[i].currIndex = 0; + h[i].privNF = AR5416_CCA_MAX_GOOD_VALUE; + h[i].invalidNFcount = AR512_NF_CAL_HIST_MAX; + for (j = 0; j < AR512_NF_CAL_HIST_MAX; j ++) + h[i].nfCalBuffer[j] = AR5416_CCA_MAX_GOOD_VALUE; + } +} + +/* + * Update the noise floor buffer as a ring buffer + */ +static void +ar5416UpdateNFHistBuff(struct ar5212NfCalHist *h, int16_t *nfarray) +{ + int i; + + for (i = 0; i < AR5416_NUM_NF_READINGS; i ++) { + h[i].nfCalBuffer[h[i].currIndex] = nfarray[i]; + + if (++h[i].currIndex >= AR512_NF_CAL_HIST_MAX) + h[i].currIndex = 0; + if (h[i].invalidNFcount > 0) { + if (nfarray[i] < AR5416_CCA_MIN_BAD_VALUE || + nfarray[i] > AR5416_CCA_MAX_HIGH_VALUE) { + h[i].invalidNFcount = AR512_NF_CAL_HIST_MAX; + } else { + h[i].invalidNFcount--; + h[i].privNF = nfarray[i]; + } + } else { + h[i].privNF = ar5212GetNfHistMid(h[i].nfCalBuffer); + } + } +} + +/* + * Read the NF and check it against the noise floor threshhold + */ +static int16_t +ar5416GetNf(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan) +{ + int16_t nf, nfThresh; + + if (OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: NF didn't complete in calibration window\n", __func__); + nf = 0; + } else { + /* Finished NF cal, check against threshold */ + int16_t nfarray[NUM_NOISEFLOOR_READINGS] = { 0 }; + + /* TODO - enhance for multiple chains and ext ch */ + ath_hal_getNoiseFloor(ah, nfarray); + nf = nfarray[0]; + if (ar5416GetEepromNoiseFloorThresh(ah, chan, &nfThresh)) { + if (nf > nfThresh) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: noise floor failed detected; " + "detected %d, threshold %d\n", __func__, + nf, nfThresh); + /* + * NB: Don't discriminate 2.4 vs 5Ghz, if this + * happens it indicates a problem regardless + * of the band. + */ + chan->channelFlags |= CHANNEL_CW_INT; + nf = 0; + } + } else { + nf = 0; + } + ar5416UpdateNFHistBuff(AH5416(ah)->ah_cal.nfCalHist, nfarray); + chan->rawNoiseFloor = nf; + } + return nf; +} +#endif /* AH_SUPPORT_AR5416 */ diff --git a/ar5416/ar5416_cal.h b/ar5416/ar5416_cal.h new file mode 100644 index 000000000000..124002985bf6 --- /dev/null +++ b/ar5416/ar5416_cal.h @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2002-2008 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. + * + * $Id: ar5416_cal.h,v 1.3 2008/11/11 17:43:23 sam Exp $ + */ +#ifndef _ATH_AR5416_CAL_H_ +#define _ATH_AR5416_CAL_H_ + +typedef enum { + ADC_DC_INIT_CAL = 0x1, + ADC_GAIN_CAL = 0x2, + ADC_DC_CAL = 0x4, + IQ_MISMATCH_CAL = 0x8 +} HAL_CAL_TYPE; + +/* Calibrate state */ +typedef enum { + CAL_INACTIVE, + CAL_WAITING, + CAL_RUNNING, + CAL_DONE +} HAL_CAL_STATE; + +typedef union { + uint32_t u; + int32_t s; +} HAL_CAL_SAMPLE; + +#define MIN_CAL_SAMPLES 1 +#define MAX_CAL_SAMPLES 64 +#define INIT_LOG_COUNT 5 +#define PER_MIN_LOG_COUNT 2 +#define PER_MAX_LOG_COUNT 10 + +/* Per Calibration data structure */ +typedef struct per_cal_data { + const char *calName; /* for diagnostics */ + HAL_CAL_TYPE calType; /* Type of calibration */ + uint32_t calNumSamples; /* # SW samples to collect */ + uint32_t calCountMax; /* # HW samples to collect */ + void (*calCollect)(struct ath_hal *); /* Accumulator function */ + /* Post-processing function */ + void (*calPostProc)(struct ath_hal *, uint8_t); +} HAL_PERCAL_DATA; + +/* List structure for calibration data */ +typedef struct cal_list { + struct cal_list *calNext; + HAL_CAL_STATE calState; + const HAL_PERCAL_DATA *calData; +} HAL_CAL_LIST; + +struct ar5416PerCal { + /* + * Periodic calibration state. + */ + HAL_CAL_TYPE suppCals; + HAL_CAL_LIST iqCalData; + HAL_CAL_LIST adcGainCalData; + HAL_CAL_LIST adcDcCalInitData; + HAL_CAL_LIST adcDcCalData; + HAL_CAL_LIST *cal_list; + HAL_CAL_LIST *cal_last; + HAL_CAL_LIST *cal_curr; +#define AR5416_MAX_CHAINS 3 /* XXX dup's eeprom def */ + HAL_CAL_SAMPLE caldata[4][AR5416_MAX_CHAINS]; + int calSamples; + /* + * Noise floor cal histogram support. + * XXX be nice to re-use space in ar5212 + */ +#define AR5416_NUM_NF_READINGS 6 /* (3 chains * (ctl + ext) */ + struct ar5212NfCalHist nfCalHist[AR5416_NUM_NF_READINGS]; +}; + +#define INIT_CAL(_perCal) do { \ + (_perCal)->calState = CAL_WAITING; \ + (_perCal)->calNext = AH_NULL; \ +} while (0) + +#define INSERT_CAL(_cal, _perCal) do { \ + if ((_cal)->cal_last == AH_NULL) { \ + (_cal)->cal_list = (_cal)->cal_last = (_perCal); \ + ((_cal)->cal_last)->calNext = (_perCal); \ + } else { \ + ((_cal)->cal_last)->calNext = (_perCal); \ + (_cal)->cal_last = (_perCal); \ + (_perCal)->calNext = (_cal)->cal_list; \ + } \ +} while (0) + +HAL_BOOL ar5416InitCal(struct ath_hal *ah, HAL_CHANNEL *chan); +HAL_BOOL ar5416PerCalibration(struct ath_hal *, HAL_CHANNEL *, + HAL_BOOL *isIQdone); +HAL_BOOL ar5416PerCalibrationN(struct ath_hal *ah, HAL_CHANNEL *chan, + u_int chainMask, HAL_BOOL longCal, HAL_BOOL *isCalDone); +HAL_BOOL ar5416ResetCalValid(struct ath_hal *ah, HAL_CHANNEL *chan); + +void ar5416IQCalCollect(struct ath_hal *ah); +void ar5416IQCalibration(struct ath_hal *ah, uint8_t numChains); +void ar5416AdcGainCalCollect(struct ath_hal *ah); +void ar5416AdcGainCalibration(struct ath_hal *ah, uint8_t numChains); +void ar5416AdcDcCalCollect(struct ath_hal *ah); +void ar5416AdcDcCalibration(struct ath_hal *ah, uint8_t numChains); +void ar5416InitNfHistBuff(struct ar5212NfCalHist *h); +#endif /* _ATH_AR5416_CAL_H_ */ diff --git a/ar5416/ar5416_cal_adcdc.c b/ar5416/ar5416_cal_adcdc.c new file mode 100644 index 000000000000..00948e224f52 --- /dev/null +++ b/ar5416/ar5416_cal_adcdc.c @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2002-2008 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. + * + * $Id: ar5416_cal_adcdc.c,v 1.2 2008/11/11 17:43:23 sam Exp $ + */ +#include "opt_ah.h" + +#ifdef AH_SUPPORT_AR5416 + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" + +/* Adc DC Offset Cal aliases */ +#define totalAdcDcOffsetIOddPhase(i) caldata[0][i].s +#define totalAdcDcOffsetIEvenPhase(i) caldata[1][i].s +#define totalAdcDcOffsetQOddPhase(i) caldata[2][i].s +#define totalAdcDcOffsetQEvenPhase(i) caldata[3][i].s + +void +ar5416AdcDcCalCollect(struct ath_hal *ah) +{ + struct ar5416PerCal *cal = &AH5416(ah)->ah_cal; + int i; + + for (i = 0; i < AR5416_MAX_CHAINS; i++) { + cal->totalAdcDcOffsetIOddPhase(i) += (int32_t) + OS_REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); + cal->totalAdcDcOffsetIEvenPhase(i) += (int32_t) + OS_REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); + cal->totalAdcDcOffsetQOddPhase(i) += (int32_t) + OS_REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); + cal->totalAdcDcOffsetQEvenPhase(i) += (int32_t) + OS_REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); + + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n", + cal->calSamples, i, + cal->totalAdcDcOffsetIOddPhase(i), + cal->totalAdcDcOffsetIEvenPhase(i), + cal->totalAdcDcOffsetQOddPhase(i), + cal->totalAdcDcOffsetQEvenPhase(i)); + } +} + +void +ar5416AdcDcCalibration(struct ath_hal *ah, uint8_t numChains) +{ + struct ar5416PerCal *cal = &AH5416(ah)->ah_cal; + const HAL_PERCAL_DATA *calData = cal->cal_curr->calData; + uint32_t numSamples; + int i; + + numSamples = (1 << (calData->calCountMax + 5)) * calData->calNumSamples; + for (i = 0; i < numChains; i++) { + uint32_t iOddMeasOffset = cal->totalAdcDcOffsetIOddPhase(i); + uint32_t iEvenMeasOffset = cal->totalAdcDcOffsetIEvenPhase(i); + int32_t qOddMeasOffset = cal->totalAdcDcOffsetQOddPhase(i); + int32_t qEvenMeasOffset = cal->totalAdcDcOffsetQEvenPhase(i); + int32_t qDcMismatch, iDcMismatch; + uint32_t val; + + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "Starting ADC DC Offset Cal for Chain %d\n", i); + + HALDEBUG(ah, HAL_DEBUG_PERCAL, " pwr_meas_odd_i = %d\n", + iOddMeasOffset); + HALDEBUG(ah, HAL_DEBUG_PERCAL, " pwr_meas_even_i = %d\n", + iEvenMeasOffset); + HALDEBUG(ah, HAL_DEBUG_PERCAL, " pwr_meas_odd_q = %d\n", + qOddMeasOffset); + HALDEBUG(ah, HAL_DEBUG_PERCAL, " pwr_meas_even_q = %d\n", + qEvenMeasOffset); + + HALASSERT(numSamples); + + iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) / + numSamples) & 0x1ff; + qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) / + numSamples) & 0x1ff; + HALDEBUG(ah, HAL_DEBUG_PERCAL, + " dc_offset_mismatch_i = 0x%08x\n", iDcMismatch); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + " dc_offset_mismatch_q = 0x%08x\n", qDcMismatch); + + val = OS_REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); + val &= 0xc0000fff; + val |= (qDcMismatch << 12) | (iDcMismatch << 21); + OS_REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); + + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "ADC DC Offset Cal done for Chain %d\n", i); + } + OS_REG_SET_BIT(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0), + AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE); +} +#endif /* AH_SUPPORT_AR5416 */ diff --git a/ar5416/ar5416_cal_adcgain.c b/ar5416/ar5416_cal_adcgain.c new file mode 100644 index 000000000000..9e8d861f3845 --- /dev/null +++ b/ar5416/ar5416_cal_adcgain.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2002-2008 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. + * + * $Id: ar5416_cal_adcgain.c,v 1.2 2008/11/11 17:43:23 sam Exp $ + */ +#include "opt_ah.h" + +#ifdef AH_SUPPORT_AR5416 + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" + +/* Adc Gain Cal aliases */ +#define totalAdcIOddPhase(i) caldata[0][i].u +#define totalAdcIEvenPhase(i) caldata[1][i].u +#define totalAdcQOddPhase(i) caldata[2][i].u +#define totalAdcQEvenPhase(i) caldata[3][i].u + +/* + * Collect data from HW to later perform ADC Gain Calibration + */ +void +ar5416AdcGainCalCollect(struct ath_hal *ah) +{ + struct ar5416PerCal *cal = &AH5416(ah)->ah_cal; + int i; + + /* + * Accumulate ADC Gain cal measures for active chains + */ + for (i = 0; i < AR5416_MAX_CHAINS; i++) { + cal->totalAdcIOddPhase(i) += + OS_REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); + cal->totalAdcIEvenPhase(i) += + OS_REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); + cal->totalAdcQOddPhase(i) += + OS_REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); + cal->totalAdcQEvenPhase(i) += + OS_REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); + + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n", + cal->calSamples, i, cal->totalAdcIOddPhase(i), + cal->totalAdcIEvenPhase(i), cal->totalAdcQOddPhase(i), + cal->totalAdcQEvenPhase(i)); + } +} + +/* + * Use HW data to do ADC Gain Calibration + */ +void +ar5416AdcGainCalibration(struct ath_hal *ah, uint8_t numChains) +{ + struct ar5416PerCal *cal = &AH5416(ah)->ah_cal; + uint32_t i; + + for (i = 0; i < numChains; i++) { + uint32_t iOddMeasOffset = cal->totalAdcIOddPhase(i); + uint32_t iEvenMeasOffset = cal->totalAdcIEvenPhase(i); + uint32_t qOddMeasOffset = cal->totalAdcQOddPhase(i); + uint32_t qEvenMeasOffset = cal->totalAdcQEvenPhase(i); + + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "Start ADC Gain Cal for Chain %d\n", i); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + " pwr_meas_odd_i = 0x%08x\n", iOddMeasOffset); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + " pwr_meas_even_i = 0x%08x\n", iEvenMeasOffset); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + " pwr_meas_odd_q = 0x%08x\n", qOddMeasOffset); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + " pwr_meas_even_q = 0x%08x\n", qEvenMeasOffset); + + if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) { + uint32_t iGainMismatch = + ((iEvenMeasOffset*32)/iOddMeasOffset) & 0x3f; + uint32_t qGainMismatch = + ((qOddMeasOffset*32)/qEvenMeasOffset) & 0x3f; + uint32_t val; + + HALDEBUG(ah, HAL_DEBUG_PERCAL, + " gain_mismatch_i = 0x%08x\n", + iGainMismatch); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + " gain_mismatch_q = 0x%08x\n", + qGainMismatch); + + val = OS_REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); + val &= 0xfffff000; + val |= (qGainMismatch) | (iGainMismatch << 6); + OS_REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); + + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "ADC Gain Cal done for Chain %d\n", i); + } + } + OS_REG_SET_BIT(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0), + AR_PHY_NEW_ADC_GAIN_CORR_ENABLE); +} +#endif /* AH_SUPPORT_AR5416 */ diff --git a/ar5416/ar5416_cal_iq.c b/ar5416/ar5416_cal_iq.c new file mode 100644 index 000000000000..7b9ca149a0e1 --- /dev/null +++ b/ar5416/ar5416_cal_iq.c @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2002-2008 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. + * + * $Id: ar5416_cal_iq.c,v 1.2 2008/11/11 17:43:23 sam Exp $ + */ +#include "opt_ah.h" + +#ifdef AH_SUPPORT_AR5416 + +#include "ah.h" +#include "ah_internal.h" +#include "ah_devid.h" + +#include "ar5416/ar5416.h" +#include "ar5416/ar5416reg.h" +#include "ar5416/ar5416phy.h" + +/* IQ Cal aliases */ +#define totalPowerMeasI(i) caldata[0][i].u +#define totalPowerMeasQ(i) caldata[1][i].u +#define totalIqCorrMeas(i) caldata[2][i].s + +/* + * Collect data from HW to later perform IQ Mismatch Calibration + */ +void +ar5416IQCalCollect(struct ath_hal *ah) +{ + struct ar5416PerCal *cal = &AH5416(ah)->ah_cal; + int i; + + /* + * Accumulate IQ cal measures for active chains + */ + for (i = 0; i < AR5416_MAX_CHAINS; i++) { + cal->totalPowerMeasI(i) += + OS_REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); + cal->totalPowerMeasQ(i) += + OS_REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); + cal->totalIqCorrMeas(i) += (int32_t) + OS_REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n", + cal->calSamples, i, cal->totalPowerMeasI(i), + cal->totalPowerMeasQ(i), cal->totalIqCorrMeas(i)); + } +} + +/* + * Use HW data to do IQ Mismatch Calibration + */ +void +ar5416IQCalibration(struct ath_hal *ah, uint8_t numChains) +{ + struct ar5416PerCal *cal = &AH5416(ah)->ah_cal; + int i; + + for (i = 0; i < numChains; i++) { + uint32_t powerMeasI = cal->totalPowerMeasI(i); + uint32_t powerMeasQ = cal->totalPowerMeasQ(i); + uint32_t iqCorrMeas = cal->totalIqCorrMeas(i); + uint32_t qCoffDenom, iCoffDenom; + int iqCorrNeg; + + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "Start IQ Cal and Correction for Chain %d\n", i); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "Orignal: iq_corr_meas = 0x%08x\n", iqCorrMeas); + + iqCorrNeg = 0; + /* iqCorrMeas is always negative. */ + if (iqCorrMeas > 0x80000000) { + iqCorrMeas = (0xffffffff - iqCorrMeas) + 1; + iqCorrNeg = 1; + } + + HALDEBUG(ah, HAL_DEBUG_PERCAL, " pwr_meas_i = 0x%08x\n", + powerMeasI); + HALDEBUG(ah, HAL_DEBUG_PERCAL, " pwr_meas_q = 0x%08x\n", + powerMeasQ); + HALDEBUG(ah, HAL_DEBUG_PERCAL, " iqCorrNeg is 0x%08x\n", + iqCorrNeg); + + iCoffDenom = (powerMeasI/2 + powerMeasQ/2)/ 128; + qCoffDenom = powerMeasQ / 64; + /* Protect against divide-by-0 */ + if (powerMeasQ != 0) { + /* IQ corr_meas is already negated if iqcorr_neg == 1 */ + int32_t iCoff = iqCorrMeas/iCoffDenom; + int32_t qCoff = powerMeasI/qCoffDenom - 64; + + HALDEBUG(ah, HAL_DEBUG_PERCAL, " iCoff = 0x%08x\n", + iCoff); + HALDEBUG(ah, HAL_DEBUG_PERCAL, " qCoff = 0x%08x\n", + qCoff); + + /* Negate iCoff if iqCorrNeg == 0 */ + iCoff = iCoff & 0x3f; + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "New: iCoff = 0x%08x\n", iCoff); + + if (iqCorrNeg == 0x0) + iCoff = 0x40 - iCoff; + if (qCoff > 15) + qCoff = 15; + else if (qCoff <= -16) + qCoff = 16; + HALDEBUG(ah, HAL_DEBUG_PERCAL, + " : iCoff = 0x%x qCoff = 0x%x\n", iCoff, qCoff); + + OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4_CHAIN(i), + AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, iCoff); + OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4_CHAIN(i), + AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, qCoff); + HALDEBUG(ah, HAL_DEBUG_PERCAL, + "IQ Cal and Correction done for Chain %d\n", i); + } + } + OS_REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4, + AR_PHY_TIMING_CTRL4_IQCORR_ENABLE); +} +#endif /* AH_SUPPORT_AR5416 */ diff --git a/ar5416/ar5416_misc.c b/ar5416/ar5416_misc.c index b04d93105355..ce5f6bcdc497 100644 --- a/ar5416/ar5416_misc.c +++ b/ar5416/ar5416_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: ar5416_misc.c,v 1.9 2008/11/10 04:08:04 sam Exp $ + * $Id: ar5416_misc.c,v 1.12 2008/11/27 22:30:07 sam Exp $ */ #include "opt_ah.h" @@ -277,7 +277,7 @@ ar5416GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, case HAL_BB_HANG_RIFS: return 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_SOWL(ah) ? HAL_OK : HAL_ENOTSUPP; case HAL_BB_HANG_RX_CLEAR: return AR_SREV_MERLIN(ah) ? HAL_OK : HAL_ENOTSUPP; } @@ -285,7 +285,8 @@ 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)) ? HAL_OK : HAL_ENOTSUPP; + AR_SREV_SOWL(ah)) ? + HAL_OK : HAL_ENOTSUPP; default: break; } @@ -316,6 +317,7 @@ ar5416GetDiagState(struct ath_hal *ah, int request, ahp->ah_hangs = 0; if (hangs & HAL_BB_HANGS) ahp->ah_hangs |= ar5416DetectBBHang(ah); + /* NB: if BB is hung MAC will be hung too so skip check */ if (ahp->ah_hangs == 0 && (hangs & HAL_MAC_HANGS)) ahp->ah_hangs |= ar5416DetectMacHang(ah); *result = &ahp->ah_hangs; diff --git a/ar5416/ar5416_phy.c b/ar5416/ar5416_phy.c index ab91e53b74e5..0384d94682a8 100644 --- a/ar5416/ar5416_phy.c +++ b/ar5416/ar5416_phy.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: ar5416_phy.c,v 1.3 2008/11/10 01:19:39 sam Exp $ + * $Id: ar5416_phy.c,v 1.4 2008/11/27 22:30:08 sam Exp $ */ #include "opt_ah.h" @@ -40,7 +40,7 @@ HAL_RATE_TABLE ar5416_11ng_table = { /* 2 Mb */ { AH_TRUE, CCK, 2000, 0x1a, 0x04, (0x80| 4), 1 }, /* 5.5 Mb */ { AH_TRUE, CCK, 5500, 0x19, 0x04, (0x80|11), 2 }, /* 11 Mb */ { AH_TRUE, CCK, 11000, 0x18, 0x04, (0x80|22), 3 }, -/* We remove rates 6, 9 from rate ctrl */ +/* Remove rates 6, 9 from rate ctrl */ /* 6 Mb */ { AH_FALSE, OFDM, 6000, 0x0b, 0x00, 12, 4 }, /* 9 Mb */ { AH_FALSE, OFDM, 9000, 0x0f, 0x00, 18, 4 }, /* 12 Mb */ { AH_TRUE, OFDM, 12000, 0x0a, 0x00, 24, 6 }, diff --git a/ar5416/ar5416_power.c b/ar5416/ar5416_power.c index b27d0ed62a92..b951cfdba6ff 100644 --- a/ar5416/ar5416_power.c +++ b/ar5416/ar5416_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: ar5416_power.c,v 1.5 2008/11/10 04:08:04 sam Exp $ + * $Id: ar5416_power.c,v 1.6 2008/11/11 00:11:30 sam Exp $ */ #include "opt_ah.h" diff --git a/ar5416/ar5416_recv.c b/ar5416/ar5416_recv.c index 59f071136979..5701ec6e6749 100644 --- a/ar5416/ar5416_recv.c +++ b/ar5416/ar5416_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: ar5416_recv.c,v 1.5 2008/11/10 04:08:04 sam Exp $ + * $Id: ar5416_recv.c,v 1.7 2008/11/11 20:46:06 sam Exp $ */ #include "opt_ah.h" @@ -36,12 +36,15 @@ ar5416StartPcuReceive(struct ath_hal *ah) { struct ath_hal_private *ahp = AH_PRIVATE(ah); - OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT); - HALDEBUG(ah, HAL_DEBUG_RX, "%s: Start PCU Receive \n", __func__); ar5212EnableMibCounters(ah); /* NB: restore current settings */ - ar5212AniReset(ah, ahp->ah_curchan, ahp->ah_opmode, AH_TRUE); + ar5416AniReset(ah, ahp->ah_curchan, ahp->ah_opmode, AH_TRUE); + /* + * NB: must do after enabling phy errors to avoid rx + * frames w/ corrupted descriptor status. + */ + OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT); } /* diff --git a/ar5416/ar5416_reset.c b/ar5416/ar5416_reset.c index 65cfe58bf391..b1717a61be08 100644 --- a/ar5416/ar5416_reset.c +++ b/ar5416/ar5416_reset.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: ar5416_reset.c,v 1.20 2008/11/10 04:08:05 sam Exp $ + * $Id: ar5416_reset.c,v 1.27 2008/11/27 22:30:08 sam Exp $ */ #include "opt_ah.h" @@ -50,26 +50,18 @@ 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 HAL_BOOL ar5416InitCal(struct ath_hal *ah, HAL_CHANNEL *chan); - static HAL_BOOL ar5416SetTransmitPower(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan, uint16_t *rfXpdGain); #if 0 static HAL_BOOL ar5416ChannelChange(struct ath_hal *, HAL_CHANNEL *); #endif -static void ar5416StartNFCal(struct ath_hal *ah); -static void ar5416LoadNF(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *); -static int16_t ar5416GetNf(struct ath_hal *, HAL_CHANNEL_INTERNAL *); static void ar5416SetDeltaSlope(struct ath_hal *, HAL_CHANNEL_INTERNAL *); static void ar5416SpurMitigate(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan); #ifdef AH_SUPPORT_AR9280 static void ar9280SpurMitigate(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan); #endif -/* Owl specific stuff */ -#define NUM_NOISEFLOOR_READINGS 6 /* 3 chains * (ctl + ext) */ - 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, HAL_CHANNEL *chan); @@ -110,9 +102,6 @@ static HAL_BOOL ar5416FillVpdTable(uint8_t pwrMin, uint8_t pwrMax, uint8_t *pPwrList, uint8_t *pVpdList, uint16_t numIntercepts, uint8_t *pRetVpdList); -static void ar5416GetNoiseFloor(struct ath_hal *ah, - int16_t nfarray[NUM_NOISEFLOOR_READINGS]); - /* * Places the device in and out of reset and then places sane * values in the registers based on EEPROM config, initialization @@ -648,8 +637,8 @@ ar5416InitBB(struct ath_hal *ah, HAL_CHANNEL *chan) /* * If the AP starts the calibration before the base band timeout - * completes we could get rx_clear false triggering, to avoid this - * we add delay an extra BASE_ACTIVATE_DELAY usecs to ensure this + * completes we could get rx_clear false triggering. Add an + * extra BASE_ACTIVATE_DELAY usecs to ensure this condition * does not happen. */ if (IS_CHAN_HALF_RATE(AH_PRIVATE(ah)->ah_curchan)) { @@ -790,969 +779,6 @@ ar5416ChipReset(struct ath_hal *ah, HAL_CHANNEL *chan) return AH_TRUE; } -/* - * Determine if calibration is supported by device and channel flags - */ -static OS_INLINE HAL_BOOL -ar5416IsCalSupp(struct ath_hal *ah, HAL_CHANNEL *chan, HAL_CAL_TYPE calType) -{ - struct ath_hal_5416 *ahp = AH5416(ah); - - switch (calType & ahp->ah_suppCals) { - case IQ_MISMATCH_CAL: - /* Run IQ Mismatch for non-CCK only */ - return !IS_CHAN_B(chan); - case ADC_GAIN_CAL: - case ADC_DC_CAL: - /* Run ADC Gain Cal for non-CCK & non 2GHz-HT20 only */ - return !IS_CHAN_B(chan) && - !(IS_CHAN_2GHZ(chan) && IS_CHAN_HT20(chan)); - } - return AH_FALSE; -} - -/* - * Setup HW to collect samples used for current cal - */ -static void -ar5416SetupMeasurement(struct ath_hal *ah, HAL_CAL_LIST *currCal) -{ - /* Start calibration w/ 2^(INIT_IQCAL_LOG_COUNT_MAX+1) samples */ - OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4, - AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX, - currCal->calData->calCountMax); - - /* Select calibration to run */ - switch (currCal->calData->calType) { - case IQ_MISMATCH_CAL: - OS_REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ); - HALDEBUG(ah, HAL_DEBUG_PERCAL, - "%s: start IQ Mismatch calibration\n", __func__); - break; - case ADC_GAIN_CAL: - OS_REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN); - HALDEBUG(ah, HAL_DEBUG_PERCAL, - "%s: start ADC Gain calibration\n", __func__); - break; - case ADC_DC_CAL: - OS_REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER); - HALDEBUG(ah, HAL_DEBUG_PERCAL, - "%s: start ADC DC calibration\n", __func__); - break; - case ADC_DC_INIT_CAL: - OS_REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT); - HALDEBUG(ah, HAL_DEBUG_PERCAL, - "%s: start Init ADC DC calibration\n", __func__); - break; - } - /* Kick-off cal */ - OS_REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4, AR_PHY_TIMING_CTRL4_DO_CAL); -} - -/* - * Initialize shared data structures and prepare a cal to be run. - */ -static void -ar5416ResetMeasurement(struct ath_hal *ah, HAL_CAL_LIST *currCal) -{ - struct ath_hal_5416 *ahp = AH5416(ah); - - /* Reset data structures shared between different calibrations */ - OS_MEMZERO(ahp->ah_caldata, sizeof(ahp->ah_caldata)); - ahp->ah_calSamples = 0; - - /* Setup HW for new calibration */ - ar5416SetupMeasurement(ah, currCal); - - /* Change SW state to RUNNING for this calibration */ - currCal->calState = CAL_RUNNING; -} - -#if 0 -/* - * Run non-periodic calibrations. - */ -static HAL_BOOL -ar5416RunInitCals(struct ath_hal *ah, int init_cal_count) -{ - struct ath_hal_5416 *ahp = AH5416(ah); - HAL_CHANNEL_INTERNAL ichan; /* XXX bogus */ - HAL_CAL_LIST *curCal = ahp->ah_cal_curr; - HAL_BOOL isCalDone; - int i; - - if (curCal == AH_NULL) - return AH_FALSE; - - ichan.calValid = 0; - for (i = 0; i < init_cal_count; i++) { - /* Reset this Cal */ - ar5416ResetMeasurement(ah, curCal); - /* Poll for offset calibration complete */ - if (!ath_hal_wait(ah, AR_PHY_TIMING_CTRL4, AR_PHY_TIMING_CTRL4_DO_CAL, 0)) { - HALDEBUG(ah, HAL_DEBUG_ANY, - "%s: Cal %d failed to finish in 100ms.\n", - __func__, curCal->calData->calType); - /* Re-initialize list pointers for periodic cals */ - ahp->ah_cal_list = ahp->ah_cal_last = - ahp->ah_cal_curr = AH_NULL; - return AH_FALSE; - } - /* Run this cal */ - ar5416DoCalibration(ah, &ichan, ahp->ah_rxchainmask, - curCal, &isCalDone); - if (!isCalDone) - HALDEBUG(ah, HAL_DEBUG_ANY, - "%s: init cal %d did not complete.\n", - __func__, curCal->calData->calType); - if (curCal->calNext != AH_NULL) - curCal = curCal->calNext; - } - - /* Re-initialize list pointers for periodic cals */ - ahp->ah_cal_list = ahp->ah_cal_last = - ahp->ah_cal_curr = AH_NULL; - return AH_TRUE; -} -#endif - -/* - * Initialize Calibration infrastructure. - */ -static HAL_BOOL -ar5416InitCal(struct ath_hal *ah, HAL_CHANNEL *chan) -{ - struct ath_hal_5416 *ahp = AH5416(ah); - HAL_CHANNEL_INTERNAL *ichan; - - ichan = ath_hal_checkchannel(ah, chan); - HALASSERT(ichan != AH_NULL); - - /* Calibrate the AGC */ - 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 did not complete in 1ms; " - "noisy environment?\n", __func__); - return AH_FALSE; - } - - /* - * Do NF calibration after DC offset and other CALs. - * Per system engineers, noise floor value can sometimes be 20 dB - * higher than normal value if DC offset and noise floor cal are - * triggered at the same time. - */ - OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); - - /* Initialize list pointers */ - ahp->ah_cal_list = ahp->ah_cal_last = - ahp->ah_cal_curr = AH_NULL; - - /* - * Enable IQ, ADC Gain, ADC DC Offset Cals - */ - if (AR_SREV_SOWL_10_OR_LATER(ah)) { - /* Setup all non-periodic, init time only calibrations */ - /* XXX: Init DC Offset not working yet */ -#if 0 - if (ar5416IsCalSupp(ah, chan, ADC_DC_INIT_CAL)) { - INIT_CAL(&ahp->ah_adcDcCalInitData); - INSERT_CAL(ahp, &ahp->ah_adcDcCalInitData); - } - /* Initialize current pointer to first element in list */ - ahp->ah_cal_curr = ahp->ah_cal_list; - - if (ahp->ah_cal_curr != AH_NULL && !ar5416RunInitCals(ah, 0)) - return AH_FALSE; -#endif - } - - /* If Cals are supported, add them to list via INIT/INSERT_CAL */ - if (ar5416IsCalSupp(ah, chan, ADC_GAIN_CAL)) { - INIT_CAL(&ahp->ah_adcGainCalData); - INSERT_CAL(ahp, &ahp->ah_adcGainCalData); - HALDEBUG(ah, HAL_DEBUG_PERCAL, - "%s: enable ADC Gain Calibration.\n", __func__); - } - if (ar5416IsCalSupp(ah, chan, ADC_DC_CAL)) { - INIT_CAL(&ahp->ah_adcDcCalData); - INSERT_CAL(ahp, &ahp->ah_adcDcCalData); - HALDEBUG(ah, HAL_DEBUG_PERCAL, - "%s: enable ADC DC Calibration.\n", __func__); - } - if (ar5416IsCalSupp(ah, chan, IQ_MISMATCH_CAL)) { - INIT_CAL(&ahp->ah_iqCalData); - INSERT_CAL(ahp, &ahp->ah_iqCalData); - HALDEBUG(ah, HAL_DEBUG_PERCAL, - "%s: enable IQ Calibration.\n", __func__); - } - /* Initialize current pointer to first element in list */ - ahp->ah_cal_curr = ahp->ah_cal_list; - - /* Kick off measurements for the first cal */ - if (ahp->ah_cal_curr != AH_NULL) - ar5416ResetMeasurement(ah, ahp->ah_cal_curr); - - /* Mark all calibrations on this channel as being invalid */ - ichan->calValid = 0; - - return AH_TRUE; -} - -/* - * Entry point for upper layers to restart current cal. - * Reset the calibration valid bit in channel. - */ -void -ar5416ResetCalValid(struct ath_hal *ah, HAL_CHANNEL *chan, HAL_BOOL *isCalDone) -{ - struct ath_hal_5416 *ahp = AH5416(ah); - HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan); - HAL_CAL_LIST *currCal = ahp->ah_cal_curr; - - *isCalDone = AH_TRUE; - - if (!AR_SREV_SOWL_10_OR_LATER(ah)) - return; - if (currCal == AH_NULL) - return; - if (ichan == AH_NULL) { - HALDEBUG(ah, HAL_DEBUG_ANY, - "%s: invalid channel %u/0x%x; no mapping\n", - __func__, chan->channel, chan->channelFlags); - return; - } - /* - * Expected that this calibration has run before, post-reset. - * Current state should be done - */ - if (currCal->calState != CAL_DONE) { - HALDEBUG(ah, HAL_DEBUG_ANY, - "%s: Calibration state incorrect, %d\n", - __func__, currCal->calState); - return; - } - - /* Verify Cal is supported on this channel */ - if (!ar5416IsCalSupp(ah, chan, currCal->calData->calType)) - return; - - HALDEBUG(ah, HAL_DEBUG_PERCAL, - "%s: Resetting Cal %d state for channel %u/0x%x\n", - __func__, currCal->calData->calType, chan->channel, - chan->channelFlags); - - /* Disable cal validity in channel */ - ichan->calValid &= ~currCal->calData->calType; - currCal->calState = CAL_WAITING; - - /* Indicate to upper layers that we need polling for Howl/Sowl */ - *isCalDone = AH_FALSE; -} - -/* - * Recalibrate the lower PHY chips to account for temperature/environment - * changes. - */ -static void -ar5416DoCalibration(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *ichan, - uint8_t rxchainmask, HAL_CAL_LIST *currCal, HAL_BOOL *isCalDone) -{ - struct ath_hal_5416 *ahp = AH5416(ah); - - /* Cal is assumed not done until explicitly set below */ - *isCalDone = AH_FALSE; - - HALDEBUG(ah, HAL_DEBUG_PERCAL, - "%s: %s Calibration, state %d, calValid 0x%x\n", - __func__, currCal->calData->calName, currCal->calState, - ichan->calValid); - - /* Calibration in progress. */ - if (currCal->calState == CAL_RUNNING) { - /* Check to see if it has finished. */ - if (!(OS_REG_READ(ah, AR_PHY_TIMING_CTRL4) & AR_PHY_TIMING_CTRL4_DO_CAL)) { - HALDEBUG(ah, HAL_DEBUG_PERCAL, - "%s: sample %d of %d finished\n", - __func__, ahp->ah_calSamples, - currCal->calData->calNumSamples); - /* - * Collect measurements for active chains. - */ - currCal->calData->calCollect(ah); - if (++ahp->ah_calSamples >= currCal->calData->calNumSamples) { - int i, numChains = 0; - for (i = 0; i < AR5416_MAX_CHAINS; i++) { - if (rxchainmask & (1 << i)) - numChains++; - } - /* - * Process accumulated data - */ - currCal->calData->calPostProc(ah, numChains); - - /* Calibration has finished. */ - ichan->calValid |= currCal->calData->calType; - currCal->calState = CAL_DONE; - *isCalDone = AH_TRUE; - } else { - /* - * Set-up to collect of another sub-sample. - */ - ar5416SetupMeasurement(ah, currCal); - } - } - } else if (!(ichan->calValid & currCal->calData->calType)) { - /* If current cal is marked invalid in channel, kick it off */ - ar5416ResetMeasurement(ah, currCal); - } -} - -/* - * Internal interface to schedule periodic calibration work. - */ -static HAL_BOOL -_ar5416PerCalibration(struct ath_hal *ah, HAL_CHANNEL *chan, - uint8_t rxchainmask, HAL_BOOL longcal, HAL_BOOL *isCalDone) -{ - struct ath_hal_5416 *ahp = AH5416(ah); - HAL_CAL_LIST *currCal = ahp->ah_cal_curr; - HAL_CHANNEL_INTERNAL *ichan; - - OS_MARK(ah, AH_MARK_PERCAL, chan->channel); - - *isCalDone = AH_TRUE; - - /* Invalid channel check */ - ichan = ath_hal_checkchannel(ah, chan); - if (ichan == AH_NULL) { - HALDEBUG(ah, HAL_DEBUG_ANY, - "%s: invalid channel %u/0x%x; no mapping\n", - __func__, chan->channel, chan->channelFlags); - return AH_FALSE; - } - - /* - * For given calibration: - * 1. Call generic cal routine - * 2. When this cal is done (isCalDone) if we have more cals waiting - * (eg after reset), mask this to upper layers by not propagating - * isCalDone if it is set to TRUE. - * Instead, change isCalDone to FALSE and setup the waiting cal(s) - * to be run. - */ - if (currCal != AH_NULL && - (currCal->calState == CAL_RUNNING || - currCal->calState == CAL_WAITING)) { - ar5416DoCalibration(ah, ichan, rxchainmask, currCal, isCalDone); - if (*isCalDone == AH_TRUE) { - ahp->ah_cal_curr = currCal = currCal->calNext; - if (currCal->calState == CAL_WAITING) { - *isCalDone = AH_FALSE; - ar5416ResetMeasurement(ah, currCal); - } - } - } - - /* Do NF cal only at longer intervals */ - if (longcal) { - /* - * Get the value from the previous NF cal - * and update the history buffer. - */ - ar5416GetNf(ah, ichan); - - /* - * 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); - - if ((ichan->channelFlags & CHANNEL_CW_INT) != 0) { - /* report up and clear internal state */ - chan->channelFlags |= CHANNEL_CW_INT; - ichan->channelFlags &= ~CHANNEL_CW_INT; - } - } - return AH_TRUE; -} - -/* - * Recalibrate the lower PHY chips to account for temperature/environment - * changes. - */ -HAL_BOOL -ar5416PerCalibration(struct ath_hal *ah, HAL_CHANNEL *chan, HAL_BOOL *isIQdone) -{ - struct ath_hal_5416 *ahp = AH5416(ah); - HAL_CAL_LIST *curCal = ahp->ah_cal_curr; - - if (curCal != AH_NULL && curCal->calData->calType == IQ_MISMATCH_CAL) { - return _ar5416PerCalibration(ah, chan, ahp->ah_rx_chainmask, - AH_TRUE, isIQdone); - } else { - HAL_BOOL isCalDone; - - *isIQdone = AH_FALSE; - return _ar5416PerCalibration(ah, chan, ahp->ah_rx_chainmask, - AH_TRUE, &isCalDone); - } -} - -/* - * Collect data from HW to later perform IQ Mismatch Calibration - */ -void -ar5416IQCalCollect(struct ath_hal *ah) -{ - struct ath_hal_5416 *ahp = AH5416(ah); - int i; - - /* - * Accumulate IQ cal measures for active chains - */ - for (i = 0; i < AR5416_MAX_CHAINS; i++) { - ahp->ah_totalPowerMeasI(i) += - OS_REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); - ahp->ah_totalPowerMeasQ(i) += - OS_REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); - ahp->ah_totalIqCorrMeas(i) += (int32_t) - OS_REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); - HALDEBUG(ah, HAL_DEBUG_PERCAL, - "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n", - ahp->ah_calSamples, i, ahp->ah_totalPowerMeasI(i), - ahp->ah_totalPowerMeasQ(i), ahp->ah_totalIqCorrMeas(i)); - } -} - -/* - * Use HW data to do IQ Mismatch Calibration - */ -void -ar5416IQCalibration(struct ath_hal *ah, uint8_t numChains) -{ - struct ath_hal_5416 *ahp = AH5416(ah); - int i; - - for (i = 0; i < numChains; i++) { - uint32_t powerMeasI = ahp->ah_totalPowerMeasI(i); - uint32_t powerMeasQ = ahp->ah_totalPowerMeasQ(i); - uint32_t iqCorrMeas = ahp->ah_totalIqCorrMeas(i); - uint32_t qCoffDenom, iCoffDenom; - int iqCorrNeg; - - HALDEBUG(ah, HAL_DEBUG_PERCAL, - "Start IQ Cal and Correction for Chain %d\n", i); - HALDEBUG(ah, HAL_DEBUG_PERCAL, - "Orignal: iq_corr_meas = 0x%08x\n", iqCorrMeas); - - iqCorrNeg = 0; - /* iqCorrMeas is always negative. */ - if (iqCorrMeas > 0x80000000) { - iqCorrMeas = (0xffffffff - iqCorrMeas) + 1; - iqCorrNeg = 1; - } - - HALDEBUG(ah, HAL_DEBUG_PERCAL, " pwr_meas_i = 0x%08x\n", - powerMeasI); - HALDEBUG(ah, HAL_DEBUG_PERCAL, " pwr_meas_q = 0x%08x\n", - powerMeasQ); - HALDEBUG(ah, HAL_DEBUG_PERCAL, " iqCorrNeg is 0x%08x\n", - iqCorrNeg); - - iCoffDenom = (powerMeasI/2 + powerMeasQ/2)/ 128; - qCoffDenom = powerMeasQ / 64; - /* Protect against divide-by-0 */ - if (powerMeasQ != 0) { - /* IQ corr_meas is already negated if iqcorr_neg == 1 */ - int32_t iCoff = iqCorrMeas/iCoffDenom; - int32_t qCoff = powerMeasI/qCoffDenom - 64; - - HALDEBUG(ah, HAL_DEBUG_PERCAL, " iCoff = 0x%08x\n", - iCoff); - HALDEBUG(ah, HAL_DEBUG_PERCAL, " qCoff = 0x%08x\n", - qCoff); - - /* Negate iCoff if iqCorrNeg == 0 */ - iCoff = iCoff & 0x3f; - HALDEBUG(ah, HAL_DEBUG_PERCAL, - "New: iCoff = 0x%08x\n", iCoff); - - if (iqCorrNeg == 0x0) - iCoff = 0x40 - iCoff; - if (qCoff > 15) - qCoff = 15; - else if (qCoff <= -16) - qCoff = 16; - HALDEBUG(ah, HAL_DEBUG_PERCAL, - " : iCoff = 0x%x qCoff = 0x%x\n", iCoff, qCoff); - - OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4_CHAIN(i), - AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, iCoff); - OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4_CHAIN(i), - AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, qCoff); - HALDEBUG(ah, HAL_DEBUG_PERCAL, - "IQ Cal and Correction done for Chain %d\n", i); - } - } - OS_REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4, - AR_PHY_TIMING_CTRL4_IQCORR_ENABLE); -} - -/* - * Collect data from HW to later perform ADC Gain Calibration - */ -void -ar5416AdcGainCalCollect(struct ath_hal *ah) -{ - struct ath_hal_5416 *ahp = AH5416(ah); - int i; - - /* - * Accumulate ADC Gain cal measures for active chains - */ - for (i = 0; i < AR5416_MAX_CHAINS; i++) { - ahp->ah_totalAdcIOddPhase(i) += - OS_REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); - ahp->ah_totalAdcIEvenPhase(i) += - OS_REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); - ahp->ah_totalAdcQOddPhase(i) += - OS_REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); - ahp->ah_totalAdcQEvenPhase(i) += - OS_REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); - - HALDEBUG(ah, HAL_DEBUG_PERCAL, - "%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n", - ahp->ah_calSamples, i, ahp->ah_totalAdcIOddPhase(i), - ahp->ah_totalAdcIEvenPhase(i), ahp->ah_totalAdcQOddPhase(i), - ahp->ah_totalAdcQEvenPhase(i)); - } -} - -/* - * Use HW data to do ADC Gain Calibration - */ -void -ar5416AdcGainCalibration(struct ath_hal *ah, uint8_t numChains) -{ - struct ath_hal_5416 *ahp = AH5416(ah); - uint32_t i; - - for (i = 0; i < numChains; i++) { - uint32_t iOddMeasOffset = ahp->ah_totalAdcIOddPhase(i); - uint32_t iEvenMeasOffset = ahp->ah_totalAdcIEvenPhase(i); - uint32_t qOddMeasOffset = ahp->ah_totalAdcQOddPhase(i); - uint32_t qEvenMeasOffset = ahp->ah_totalAdcQEvenPhase(i); - - HALDEBUG(ah, HAL_DEBUG_PERCAL, - "Start ADC Gain Cal for Chain %d\n", i); - HALDEBUG(ah, HAL_DEBUG_PERCAL, - " pwr_meas_odd_i = 0x%08x\n", iOddMeasOffset); - HALDEBUG(ah, HAL_DEBUG_PERCAL, - " pwr_meas_even_i = 0x%08x\n", iEvenMeasOffset); - HALDEBUG(ah, HAL_DEBUG_PERCAL, - " pwr_meas_odd_q = 0x%08x\n", qOddMeasOffset); - HALDEBUG(ah, HAL_DEBUG_PERCAL, - " pwr_meas_even_q = 0x%08x\n", qEvenMeasOffset); - - if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) { - uint32_t iGainMismatch = - ((iEvenMeasOffset*32)/iOddMeasOffset) & 0x3f; - uint32_t qGainMismatch = - ((qOddMeasOffset*32)/qEvenMeasOffset) & 0x3f; - uint32_t val; - - HALDEBUG(ah, HAL_DEBUG_PERCAL, - " gain_mismatch_i = 0x%08x\n", - iGainMismatch); - HALDEBUG(ah, HAL_DEBUG_PERCAL, - " gain_mismatch_q = 0x%08x\n", - qGainMismatch); - - val = OS_REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); - val &= 0xfffff000; - val |= (qGainMismatch) | (iGainMismatch << 6); - OS_REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); - - HALDEBUG(ah, HAL_DEBUG_PERCAL, - "ADC Gain Cal done for Chain %d\n", i); - } - } - OS_REG_SET_BIT(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0), - AR_PHY_NEW_ADC_GAIN_CORR_ENABLE); -} - -void -ar5416AdcDcCalCollect(struct ath_hal *ah) -{ - struct ath_hal_5416 *ahp = AH5416(ah); - int i; - - for (i = 0; i < AR5416_MAX_CHAINS; i++) { - ahp->ah_totalAdcDcOffsetIOddPhase(i) += (int32_t) - OS_REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); - ahp->ah_totalAdcDcOffsetIEvenPhase(i) += (int32_t) - OS_REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); - ahp->ah_totalAdcDcOffsetQOddPhase(i) += (int32_t) - OS_REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); - ahp->ah_totalAdcDcOffsetQEvenPhase(i) += (int32_t) - OS_REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); - - HALDEBUG(ah, HAL_DEBUG_PERCAL, - "%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n", - ahp->ah_calSamples, i, - ahp->ah_totalAdcDcOffsetIOddPhase(i), - ahp->ah_totalAdcDcOffsetIEvenPhase(i), - ahp->ah_totalAdcDcOffsetQOddPhase(i), - ahp->ah_totalAdcDcOffsetQEvenPhase(i)); - } -} - -void -ar5416AdcDcCalibration(struct ath_hal *ah, uint8_t numChains) -{ - struct ath_hal_5416 *ahp = AH5416(ah); - const HAL_PERCAL_DATA *calData = ahp->ah_cal_curr->calData; - uint32_t numSamples; - int i; - - numSamples = (1 << (calData->calCountMax + 5)) * calData->calNumSamples; - for (i = 0; i < numChains; i++) { - uint32_t iOddMeasOffset = ahp->ah_totalAdcDcOffsetIOddPhase(i); - uint32_t iEvenMeasOffset = ahp->ah_totalAdcDcOffsetIEvenPhase(i); - int32_t qOddMeasOffset = ahp->ah_totalAdcDcOffsetQOddPhase(i); - int32_t qEvenMeasOffset = ahp->ah_totalAdcDcOffsetQEvenPhase(i); - int32_t qDcMismatch, iDcMismatch; - uint32_t val; - - HALDEBUG(ah, HAL_DEBUG_PERCAL, - "Starting ADC DC Offset Cal for Chain %d\n", i); - - HALDEBUG(ah, HAL_DEBUG_PERCAL, " pwr_meas_odd_i = %d\n", - iOddMeasOffset); - HALDEBUG(ah, HAL_DEBUG_PERCAL, " pwr_meas_even_i = %d\n", - iEvenMeasOffset); - HALDEBUG(ah, HAL_DEBUG_PERCAL, " pwr_meas_odd_q = %d\n", - qOddMeasOffset); - HALDEBUG(ah, HAL_DEBUG_PERCAL, " pwr_meas_even_q = %d\n", - qEvenMeasOffset); - - HALASSERT(numSamples); - - iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) / - numSamples) & 0x1ff; - qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) / - numSamples) & 0x1ff; - HALDEBUG(ah, HAL_DEBUG_PERCAL, - " dc_offset_mismatch_i = 0x%08x\n", iDcMismatch); - HALDEBUG(ah, HAL_DEBUG_PERCAL, - " dc_offset_mismatch_q = 0x%08x\n", qDcMismatch); - - val = OS_REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); - val &= 0xc0000fff; - val |= (qDcMismatch << 12) | (iDcMismatch << 21); - OS_REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); - - HALDEBUG(ah, HAL_DEBUG_PERCAL, - "ADC DC Offset Cal done for Chain %d\n", i); - } - OS_REG_SET_BIT(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0), - AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE); -} - -#ifdef AH_SUPPORT_AR9280 -static void -ar9280GetNoiseFloor(struct ath_hal *ah, int16_t nfarray[NUM_NOISEFLOOR_READINGS]) -{ - 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; -} -#endif /* AH_SUPPORT_AR9280 */ - -static void -ar5416GetNoiseFloor(struct ath_hal *ah, int16_t nfarray[NUM_NOISEFLOOR_READINGS]) -{ - struct ath_hal_5416 *ahp = AH5416(ah); - int16_t nf; - - switch (ahp->ah_rx_chainmask) { - case 0x7: - nf = MS(OS_REG_READ(ah, AR_PHY_CH2_CCA), AR_PHY_CH2_MINCCA_PWR); - if (nf & 0x100) - nf = 0 - ((nf ^ 0x1ff) + 1); - HALDEBUG(ah, HAL_DEBUG_NFCAL, - "NF calibrated [ctl] [chain 2] is %d\n", nf); - nfarray[4] = nf; - - nf = MS(OS_REG_READ(ah, AR_PHY_CH2_EXT_CCA), AR_PHY_CH2_EXT_MINCCA_PWR); - if (nf & 0x100) - nf = 0 - ((nf ^ 0x1ff) + 1); - HALDEBUG(ah, HAL_DEBUG_NFCAL, - "NF calibrated [ext] [chain 2] is %d\n", nf); - nfarray[5] = nf; - /* fall thru... */ - case 0x3: - case 0x5: - nf = MS(OS_REG_READ(ah, AR_PHY_CH1_CCA), AR_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[2] = nf; - - - nf = MS(OS_REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR_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[3] = nf; - /* fall thru... */ - case 0x1: - nf = MS(OS_REG_READ(ah, AR_PHY_CCA), AR_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_EXT_CCA), AR_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[1] = nf; - - break; - } -} - -static HAL_BOOL -ar5416GetEepromNoiseFloorThresh(struct ath_hal *ah, - const HAL_CHANNEL_INTERNAL *chan, int16_t *nft) -{ - switch (chan->channelFlags & CHANNEL_ALL_NOTURBO) { - case CHANNEL_A: - case CHANNEL_A_HT20: - case CHANNEL_A_HT40PLUS: - case CHANNEL_A_HT40MINUS: - ath_hal_eepromGet(ah, AR_EEP_NFTHRESH_5, nft); - break; - case CHANNEL_B: - case CHANNEL_G: - case CHANNEL_G_HT20: - case CHANNEL_G_HT40PLUS: - case CHANNEL_G_HT40MINUS: - ath_hal_eepromGet(ah, AR_EEP_NFTHRESH_2, nft); - break; - default: - HALDEBUG(ah, HAL_DEBUG_ANY, - "%s: invalid channel flags 0x%x\n", - __func__, chan->channelFlags); - return AH_FALSE; - } - return AH_TRUE; -} - -static void -ar5416StartNFCal(struct ath_hal *ah) -{ - OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_ENABLE_NF); - OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NO_UPDATE_NF); - OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); -} - -static void -ar5416LoadNF(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan) -{ - static const uint32_t ar5416_cca_regs[] = { - AR_PHY_CCA, - AR_PHY_CH1_CCA, - AR_PHY_CH2_CCA, - AR_PHY_EXT_CCA, - AR_PHY_CH1_EXT_CCA, - AR_PHY_CH2_EXT_CCA - }; - struct ar5212NfCalHist *h; - int i, j; - int32_t val; - uint8_t chainmask; - - /* - * Force NF calibration for all chains, otherwise Vista station - * would conduct a bad performance - */ - if (AR_SREV_KITE(ah)) { - /* Kite has only one chain */ - chainmask = 0x9; - } else if (AR_SREV_MERLIN(ah)) { - /* Merlin has only two chains */ - chainmask = 0x1B; - } else { - chainmask = 0x3F; - } - - /* - * Write filtered NF values into maxCCApwr register parameter - * so we can load below. - */ - h = AH5416(ah)->ah_nfCalHist; - for (i = 0; i < AR5416_NUM_NF_READINGS; i ++) - if (chainmask & (1 << i)) { - val = OS_REG_READ(ah, ar5416_cca_regs[i]); - val &= 0xFFFFFE00; - val |= (((uint32_t)(h[i].privNF) << 1) & 0x1ff); - OS_REG_WRITE(ah, ar5416_cca_regs[i], val); - } - - /* 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); - OS_REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NO_UPDATE_NF); - 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); - } - - /* - * Restore maxCCAPower register parameter again so that we're not capped - * by the median we just loaded. This will be initial (and max) value - * of next noise floor calibration the baseband does. - */ - for (i = 0; i < AR5416_NUM_NF_READINGS; i ++) - if (chainmask & (1 << i)) { - val = OS_REG_READ(ah, ar5416_cca_regs[i]); - val &= 0xFFFFFE00; - val |= (((uint32_t)(-50) << 1) & 0x1ff); - OS_REG_WRITE(ah, ar5416_cca_regs[i], val); - } -} - -void -ar5416InitNfHistBuff(struct ar5212NfCalHist *h) -{ - int i, j; - - for (i = 0; i < AR5416_NUM_NF_READINGS; i ++) { - h[i].currIndex = 0; - h[i].privNF = AR5416_CCA_MAX_GOOD_VALUE; - h[i].invalidNFcount = AR512_NF_CAL_HIST_MAX; - for (j = 0; j < AR512_NF_CAL_HIST_MAX; j ++) - h[i].nfCalBuffer[j] = AR5416_CCA_MAX_GOOD_VALUE; - } -} - -/* - * Update the noise floor buffer as a ring buffer - */ -static void -ar5416UpdateNFHistBuff(struct ar5212NfCalHist *h, int16_t *nfarray) -{ - int i; - - for (i = 0; i < AR5416_NUM_NF_READINGS; i ++) { - h[i].nfCalBuffer[h[i].currIndex] = nfarray[i]; - - if (++h[i].currIndex >= AR512_NF_CAL_HIST_MAX) - h[i].currIndex = 0; - if (h[i].invalidNFcount > 0) { - if (nfarray[i] < AR5416_CCA_MIN_BAD_VALUE || - nfarray[i] > AR5416_CCA_MAX_HIGH_VALUE) { - h[i].invalidNFcount = AR512_NF_CAL_HIST_MAX; - } else { - h[i].invalidNFcount--; - h[i].privNF = nfarray[i]; - } - } else { - h[i].privNF = ar5212GetNfHistMid(h[i].nfCalBuffer); - } - } -} - -/* - * Read the NF and check it against the noise floor threshhold - */ -static int16_t -ar5416GetNf(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan) -{ - int16_t nf, nfThresh; - - if (OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) { - HALDEBUG(ah, HAL_DEBUG_ANY, - "%s: NF didn't complete in calibration window\n", __func__); - nf = 0; - } else { - /* Finished NF cal, check against threshold */ - int16_t nfarray[NUM_NOISEFLOOR_READINGS]= { 0 }; - - /* TODO - enhance for multiple chains and ext ch */ -#ifdef AH_SUPPORT_AR9280 - if (AR_SREV_MERLIN_10_OR_LATER(ah)) - ar9280GetNoiseFloor(ah, nfarray); - else -#endif - ar5416GetNoiseFloor(ah, nfarray); - nf = nfarray[0]; - if (ar5416GetEepromNoiseFloorThresh(ah, chan, &nfThresh)) { - if (nf > nfThresh) { - HALDEBUG(ah, HAL_DEBUG_ANY, - "%s: noise floor failed detected; " - "detected %d, threshold %d\n", __func__, - nf, nfThresh); - /* - * NB: Don't discriminate 2.4 vs 5Ghz, if this - * happens it indicates a problem regardless - * of the band. - */ - chan->channelFlags |= CHANNEL_CW_INT; - nf = 0; - } - } else { - nf = 0; - } - ar5416UpdateNFHistBuff(AH5416(ah)->ah_nfCalHist, nfarray); - chan->rawNoiseFloor = nf; - } - return nf; -} - /* * Delta slope coefficient computation. * Required for OFDM operation. @@ -2154,7 +1180,7 @@ ar9280SpurMitigate(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *ichan) #if 1 /* * MRC CCK can interfere with beacon detection and cause deaf/mute. - * Disable MRC CCK + * Disable MRC CCK for now. */ OS_REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, AR_PHY_FORCE_CLKEN_CCK_MRC_MUX); #else @@ -2872,10 +1898,13 @@ ar5416SetBoardValues(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan) HALASSERT(AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER14_1); pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]); - txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 38; /* workaround for eeprom versions <= 14.2 */ + txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 44; /* workaround for eeprom versions <= 14.2 */ OS_REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon); for (i = 0; i < AR5416_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) { @@ -2896,6 +1925,7 @@ ar5416SetBoardValues(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan) /* * Large signal upgrade. + * XXX update */ if ((i == 0) || AR_SREV_OWL_20_OR_LATER(ah)) { @@ -3626,6 +2656,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) ) { /* * fix the gain delta, but get a delta that can be applied to min to diff --git a/ar5416/ar5416_xmit.c b/ar5416/ar5416_xmit.c index 84be68ce17a8..5789852447b5 100644 --- a/ar5416/ar5416_xmit.c +++ b/ar5416/ar5416_xmit.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: ar5416_xmit.c,v 1.8 2008/11/10 04:08:05 sam Exp $ + * $Id: ar5416_xmit.c,v 1.9 2008/11/27 22:30:08 sam Exp $ */ #include "opt_ah.h" diff --git a/ar5416/ar5416desc.h b/ar5416/ar5416desc.h index dab2a539f711..7c60b24c89c9 100644 --- a/ar5416/ar5416desc.h +++ b/ar5416/ar5416desc.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: ar5416desc.h,v 1.6 2008/11/10 04:08:05 sam Exp $ + * $Id: ar5416desc.h,v 1.7 2008/11/11 00:11:30 sam Exp $ */ #ifndef _ATH_AR5416_DESC_H_ #define _ATH_AR5416_DESC_H diff --git a/ar5416/ar5416phy.h b/ar5416/ar5416phy.h index a747b6fd664d..416aae68d23d 100644 --- a/ar5416/ar5416phy.h +++ b/ar5416/ar5416phy.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: ar5416phy.h,v 1.8 2008/11/06 22:08:01 sam Exp $ + * $Id: ar5416phy.h,v 1.10 2008/11/11 20:46:06 sam Exp $ */ #ifndef _DEV_ATH_AR5416PHY_H_ #define _DEV_ATH_AR5416PHY_H_ @@ -218,6 +218,14 @@ #define AR_PHY_SPUR_REG 0x994c #define AR_PHY_SFCORR_EXT 0x99c0 +#define AR_PHY_SFCORR_EXT_M1_THRESH 0x0000007F +#define AR_PHY_SFCORR_EXT_M1_THRESH_S 0 +#define AR_PHY_SFCORR_EXT_M2_THRESH 0x00003F80 +#define AR_PHY_SFCORR_EXT_M2_THRESH_S 7 +#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW 0x001FC000 +#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW_S 14 +#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW 0x0FE00000 +#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW_S 21 #define AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S 28 /* enable vit puncture per rate, 8 bits, lsb is low rate */ @@ -237,4 +245,6 @@ #define AR_PHY_CHANNEL_MASK_01_30 0x99d4 #define AR_PHY_CHANNEL_MASK_31_60 0x99d8 +#define AR_PHY_CL_CAL_CTL 0xA358 /* carrier leak cal control */ +#define AR_PHY_CL_CAL_ENABLE 0x00000002 #endif /* _DEV_ATH_AR5416PHY_H_ */ diff --git a/ar5416/ar5416reg.h b/ar5416/ar5416reg.h index f7d1254b7848..770ec22babba 100644 --- a/ar5416/ar5416reg.h +++ b/ar5416/ar5416reg.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: ar5416reg.h,v 1.9 2008/11/06 22:07:22 sam Exp $ + * $Id: ar5416reg.h,v 1.10 2008/11/11 00:11:30 sam Exp $ */ #ifndef _DEV_ATH_AR5416REG_H #define _DEV_ATH_AR5416REG_H @@ -445,10 +445,6 @@ #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 AR_SREV_VERSION_HOWL 0x014 -#define AR_SREV_HOWL(_ah) \ - (AH_PRIVATE((_ah))->ah_macVersion == AR_SREV_VERSION_HOWL) - /* Expanded Mac Silicon Rev (16 bits starting with Sowl) */ #define AR_XSREV_ID 0xFFFFFFFF /* Chip ID */ #define AR_XSREV_ID_S 0 diff --git a/ar5416/ar9160_attach.c b/ar5416/ar9160_attach.c index 4cf8992c5dec..373d773533f6 100644 --- a/ar5416/ar9160_attach.c +++ b/ar5416/ar9160_attach.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: ar9160_attach.c,v 1.10 2008/11/10 04:08:05 sam Exp $ + * $Id: ar9160_attach.c,v 1.14 2008/11/27 22:30:08 sam Exp $ */ #include "opt_ah.h" @@ -129,11 +129,11 @@ ar9160Attach(uint16_t devid, HAL_SOFTC sc, /* override 5416 methods for our needs */ ah->ah_detach = ar9160Detach; - AH5416(ah)->ah_iqCalData.calData = &ar9160_iq_cal; - AH5416(ah)->ah_adcGainCalData.calData = &ar9160_adc_gain_cal; - AH5416(ah)->ah_adcDcCalData.calData = &ar9160_adc_dc_cal; - AH5416(ah)->ah_adcDcCalInitData.calData = &ar9160_adc_init_dc_cal; - AH5416(ah)->ah_suppCals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL; + AH5416(ah)->ah_cal.iqCalData.calData = &ar9160_iq_cal; + AH5416(ah)->ah_cal.adcGainCalData.calData = &ar9160_adc_gain_cal; + AH5416(ah)->ah_cal.adcDcCalData.calData = &ar9160_adc_dc_cal; + AH5416(ah)->ah_cal.adcDcCalInitData.calData = &ar9160_adc_init_dc_cal; + AH5416(ah)->ah_cal.suppCals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL; if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) { /* reset chip */ @@ -255,14 +255,13 @@ ar9160Attach(uint16_t devid, HAL_SOFTC sc, * 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 + * placed into hardware. */ if (ahp->ah_miscMode != 0) OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode); - ar5212InitializeGainValues(ah); /* gain ladder */ ar9160AniSetup(ah); /* Anti Noise Immunity */ - ar5416InitNfHistBuff(AH5416(ah)->ah_nfCalHist); + ar5416InitNfHistBuff(AH5416(ah)->ah_cal.nfCalHist); HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__); diff --git a/version.h b/version.h index 4c16163f6dab..96940a9c6bc1 100644 --- a/version.h +++ b/version.h @@ -14,6 +14,6 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Id: version.h,v 1.31 2008/11/10 01:05:31 sam Exp $ + * $Id: version.h,v 1.64 2008/11/27 22:29:27 sam Exp $ */ -#define ATH_HAL_VERSION "0.11.2.0" +#define ATH_HAL_VERSION "0.11.3.7"