summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsam <sam@FreeBSD.org>2008-11-28 00:48:05 +0000
committersam <sam@FreeBSD.org>2008-11-28 00:48:05 +0000
commitfbadb9202d650a76b696844f7dd6697005746a36 (patch)
tree3c87ff6bc74e9518416a409cc0f038e1ee07bc51
parent753d7a0d87ff5d8b518495a0857264089da96049 (diff)
downloadFreeBSD-src-fbadb9202d650a76b696844f7dd6697005746a36.zip
FreeBSD-src-fbadb9202d650a76b696844f7dd6697005746a36.tar.gz
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
-rw-r--r--ah.c71
-rw-r--r--ah.h20
-rw-r--r--ah_desc.h3
-rw-r--r--ah_devid.h4
-rw-r--r--ah_eeprom.h20
-rw-r--r--ah_eeprom_v1.c253
-rw-r--r--ah_eeprom_v1.h99
-rw-r--r--ah_eeprom_v14.c6
-rw-r--r--ah_eeprom_v3.c7
-rw-r--r--ah_internal.h27
-rw-r--r--ah_regdomain.c2083
-rw-r--r--ar5210/ar5210.h83
-rw-r--r--ar5210/ar5210_attach.c175
-rw-r--r--ar5210/ar5210_misc.c53
-rw-r--r--ar5210/ar5210_reset.c62
-rw-r--r--ar5210/ar5210desc.h2
-rw-r--r--ar5211/ar5211.h8
-rw-r--r--ar5211/ar5211_attach.c10
-rw-r--r--ar5211/ar5211_interrupts.c6
-rw-r--r--ar5211/ar5211_misc.c60
-rw-r--r--ar5211/ar5211_reset.c60
-rw-r--r--ar5211/ar5211_xmit.c2
-rw-r--r--ar5212/ar2316.c20
-rw-r--r--ar5212/ar2317.c14
-rw-r--r--ar5212/ar2413.c20
-rw-r--r--ar5212/ar2425.c48
-rw-r--r--ar5212/ar5212.h74
-rw-r--r--ar5212/ar5212_ani.c79
-rw-r--r--ar5212/ar5212_attach.c42
-rw-r--r--ar5212/ar5212_interrupts.c6
-rw-r--r--ar5212/ar5212_misc.c101
-rw-r--r--ar5212/ar5212_phy.c12
-rw-r--r--ar5212/ar5212_reset.c466
-rw-r--r--ar5212/ar5212_rfgain.c333
-rw-r--r--ar5212/ar5212phy.h21
-rw-r--r--ar5212/ar5212reg.h37
-rw-r--r--ar5212/ar5311reg.h1
-rw-r--r--ar5212/ar5413.c20
-rw-r--r--ar5312/ar5312.h17
-rw-r--r--ar5312/ar5312_attach.c15
-rw-r--r--ar5312/ar5312_misc.c15
-rw-r--r--ar5312/ar5312_reset.c45
-rw-r--r--ar5416/ar2133.c61
-rw-r--r--ar5416/ar5416.h131
-rw-r--r--ar5416/ar5416_ani.c888
-rw-r--r--ar5416/ar5416_attach.c27
-rw-r--r--ar5416/ar5416_beacon.c4
-rw-r--r--ar5416/ar5416_cal.c669
-rw-r--r--ar5416/ar5416_cal.h119
-rw-r--r--ar5416/ar5416_cal_adcdc.c114
-rw-r--r--ar5416/ar5416_cal_adcgain.c119
-rw-r--r--ar5416/ar5416_cal_iq.c135
-rw-r--r--ar5416/ar5416_misc.c8
-rw-r--r--ar5416/ar5416_phy.c4
-rw-r--r--ar5416/ar5416_power.c2
-rw-r--r--ar5416/ar5416_recv.c11
-rw-r--r--ar5416/ar5416_reset.c989
-rw-r--r--ar5416/ar5416_xmit.c2
-rw-r--r--ar5416/ar5416desc.h2
-rw-r--r--ar5416/ar5416phy.h12
-rw-r--r--ar5416/ar5416reg.h6
-rw-r--r--ar5416/ar9160_attach.c17
-rw-r--r--version.h4
63 files changed, 4853 insertions, 2971 deletions
diff --git a/ah.c b/ah.c
index c531b78d..409259d 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;
}
@@ -247,6 +275,17 @@ ath_hal_attach(uint16_t devid, HAL_SOFTC sc,
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;
*error = HAL_ENXIO;
@@ -419,6 +458,19 @@ ath_hal_computetxtime(struct ath_hal *ah,
}
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)
{
return ((freq * 10) + (((freq % 5) == 2) ? 5 : 0) - 49400) / 5;
@@ -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 e5d47bd..0ec30ac 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 50e010e..6cfad06 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 204cf3f..0844c77 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 fb57c49..0adfcd1 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 0000000..91f895c
--- /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 0000000..2c23589
--- /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 67bcded..1941c2b 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 717578d..b2c304b 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 78eba8d..dc21e5e 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 2a6f2c5..d021c28 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.
+ * 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 /* 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)))}
+#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 */
-
- { 5120, 5240, 5, 6, 20, 20, NO_DFS, NO_PSCAN, 0 }, /* F1_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 */
-
- { 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, 5320, 20, 6, 20, 20, DFS_ETSI, PSCAN_ETSI, 0 }, /* F1_5180_5320 */
-
- { 5240, 5280, 23, 0, 20, 20, DFS_FCC3, PSCAN_FCC | PSCAN_ETSI, 0 }, /* F1_5240_5280 */
-
- { 5260, 5280, 23, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI, 0 }, /* F1_5260_5280 */
-
- { 5260, 5320, 18, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI, 0 }, /* F1_5260_5320 */
+ { 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 },
+#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 },
+#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 },
+#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 },
+#define F1_5180_5320 AFTER(F8_5180_5240)
+
+ { 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 },
+#define F1_5260_5280 AFTER(F1_5240_5280)
+
+ { 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 */
-
- { 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, 5700, 5, 6, 20, 20, DFS_FCC3 | DFS_ETSI, NO_PSCAN, 0 }, /* F1_5260_5700 */
-
- { 5280, 5320, 17, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 0 }, /* F1_5280_5320 */
-
- { 5500, 5620, 30, 6, 20, 20, DFS_ETSI, PSCAN_ETSI, 0 }, /* F1_5500_5620 */
-
- { 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 */
+#define F2_5260_5320 AFTER(F1_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 },
+#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 },
+#define F1_5280_5320 AFTER(F3_5260_5700)
+
+ { 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 },
+#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 */
-
- { 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 */
+#define F4_5500_5700 AFTER(F3_5500_5700)
+
+ { 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 */
-
- { 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 */
-
- { 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 */
-
- { 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 */
-
- { 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 */
-
- { 5765, 5805, 30, 6, 40, 40, NO_DFS, NO_PSCAN, 0}, /* T1_5765_5805 */
+ { 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},
+#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},
+#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},
+#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},
+#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},
+#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 */
-
- { 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, 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 */
+ { 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},
+#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},
+#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)},
-
- {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},
-
- {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},
-
- {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},
-
- {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},
-
- {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},
-
- {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},
-
- {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},
-
- {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},
-
- {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},
-
- {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},
-
- {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},
-
- {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},
-
- {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},
-
- {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},
-
- {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},
-
- {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},
-
- {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},
-
- {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},
-
- {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},
-
- {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 = 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),
+ },
+
+ {.regDmnEnum = APL1,
+ .conformanceTestLimit = FCC,
+ .chan11a = BM1(F4_5745_5825),
+ },
+
+ {.regDmnEnum = APL2,
+ .conformanceTestLimit = FCC,
+ .chan11a = BM1(F1_5745_5805),
+ },
+
+ {.regDmnEnum = APL3,
+ .conformanceTestLimit = FCC,
+ .chan11a = BM2(F1_5280_5320, F2_5745_5805),
+ },
+
+ {.regDmnEnum = APL4,
+ .conformanceTestLimit = FCC,
+ .chan11a = BM2(F4_5180_5240, F3_5745_5825),
+ },
+
+ {.regDmnEnum = APL5,
+ .conformanceTestLimit = FCC,
+ .chan11a = BM1(F2_5745_5825),
+ },
+
+ {.regDmnEnum = APL6,
+ .conformanceTestLimit = ETSI,
+ .dfsMask = DFS_ETSI,
+ .pscan = PSCAN_FCC_T | PSCAN_FCC,
+ .chan11a = BM3(F4_5180_5240, F2_5260_5320, F3_5745_5825),
+ .chan11a_turbo = BM3(T2_5210_5210, T1_5250_5290, T1_5760_5800),
+ },
+
+ {.regDmnEnum = APL8,
+ .conformanceTestLimit = ETSI,
+ .flags = DISALLOW_ADHOC_11A|DISALLOW_ADHOC_11A_TURB,
+ .chan11a = BM2(F6_5260_5320, F4_5745_5825),
+ },
+
+ {.regDmnEnum = APL9,
+ .conformanceTestLimit = ETSI,
+ .dfsMask = DFS_ETSI,
+ .pscan = PSCAN_ETSI,
+ .flags = DISALLOW_ADHOC_11A|DISALLOW_ADHOC_11A_TURB,
+ .chan11a = BM3(F1_5180_5320, F1_5500_5620, F3_5745_5805),
+ },
+
+ {.regDmnEnum = ETSI1,
+ .conformanceTestLimit = ETSI,
+ .dfsMask = DFS_ETSI,
+ .pscan = PSCAN_ETSI,
+ .flags = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
+ .chan11a = BM3(W2_5180_5240, F2_5260_5320, F2_5500_5700),
+ },
+
+ {.regDmnEnum = ETSI2,
+ .conformanceTestLimit = ETSI,
+ .dfsMask = DFS_ETSI,
+ .pscan = PSCAN_ETSI,
+ .flags = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
+ .chan11a = BM1(F3_5180_5240),
+ },
+
+ {.regDmnEnum = ETSI3,
+ .conformanceTestLimit = ETSI,
+ .dfsMask = DFS_ETSI,
+ .pscan = PSCAN_ETSI,
+ .flags = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
+ .chan11a = BM2(W2_5180_5240, F2_5260_5320),
+ },
+
+ {.regDmnEnum = ETSI4,
+ .conformanceTestLimit = ETSI,
+ .dfsMask = DFS_ETSI,
+ .pscan = PSCAN_ETSI,
+ .flags = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
+ .chan11a = BM2(F3_5180_5240, F1_5260_5320),
+ },
+
+ {.regDmnEnum = ETSI5,
+ .conformanceTestLimit = ETSI,
+ .dfsMask = DFS_ETSI,
+ .pscan = PSCAN_ETSI,
+ .flags = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
+ .chan11a = BM1(F1_5180_5240),
+ },
+
+ {.regDmnEnum = ETSI6,
+ .conformanceTestLimit = ETSI,
+ .dfsMask = DFS_ETSI,
+ .pscan = PSCAN_ETSI,
+ .flags = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
+ .chan11a = BM3(F5_5180_5240, F1_5260_5280, F3_5500_5700),
+ },
+
+ {.regDmnEnum = FCC1,
+ .conformanceTestLimit = FCC,
+ .chan11a = BM3(F2_5180_5240, F4_5260_5320, F5_5745_5825),
+ .chan11a_turbo = BM3(T1_5210_5210, T2_5250_5290, T2_5760_5800),
+ .chan11a_dyn_turbo = BM3(T1_5200_5240, T1_5280_5280, T1_5765_5805),
+ },
+
+ {.regDmnEnum = FCC2,
+ .conformanceTestLimit = FCC,
+ .chan11a = BM3(F6_5180_5240, F5_5260_5320, F6_5745_5825),
+ .chan11a_dyn_turbo = BM3(T2_5200_5240, T1_5280_5280, T1_5765_5805),
+ },
+
+ {.regDmnEnum = FCC3,
+ .conformanceTestLimit = FCC,
+ .dfsMask = DFS_FCC3,
+ .pscan = PSCAN_FCC | PSCAN_FCC_T,
+ .chan11a = BM4(F2_5180_5240,
+ F3_5260_5320,
+ F1_5500_5700,
+ F5_5745_5825),
+ .chan11a_turbo = BM4(T1_5210_5210,
+ T1_5250_5250,
+ T1_5290_5290,
+ T2_5760_5800),
+ .chan11a_dyn_turbo = BM3(T1_5200_5240, T2_5280_5280, T1_5540_5660),
+ },
+
+ {.regDmnEnum = FCC4,
+ .conformanceTestLimit = FCC,
+ .dfsMask = DFS_FCC3,
+ .pscan = PSCAN_FCC | PSCAN_FCC_T,
+ .chan11a = BM1(F1_4950_4980),
+ .chan11a_half = BM1(F1_4945_4985),
+ .chan11a_quarter = BM1(F1_4942_4987),
+ },
+
+ /* FCC1 w/ 1/2 and 1/4 width channels */
+ {.regDmnEnum = FCC5,
+ .conformanceTestLimit = FCC,
+ .chan11a = BM3(F2_5180_5240, F4_5260_5320, F5_5745_5825),
+ .chan11a_turbo = BM3(T1_5210_5210, T2_5250_5290, T2_5760_5800),
+ .chan11a_dyn_turbo = BM3(T1_5200_5240, T1_5280_5280, T1_5765_5805),
+ .chan11a_half = BM3(F7_5180_5240, F7_5260_5320, F9_5745_5825),
+ .chan11a_quarter = BM3(F8_5180_5240, F8_5260_5320,F10_5745_5825),
+ },
+
+ {.regDmnEnum = MKK1,
+ .conformanceTestLimit = MKK,
+ .pscan = PSCAN_MKK1,
+ .flags = DISALLOW_ADHOC_11A_TURB,
+ .chan11a = BM1(F1_5170_5230),
+ },
+
+ {.regDmnEnum = MKK2,
+ .conformanceTestLimit = MKK,
+ .pscan = PSCAN_MKK2,
+ .flags = DISALLOW_ADHOC_11A_TURB,
+ .chan11a = BM3(F1_4920_4980, F1_5040_5080, F1_5170_5230),
+ .chan11a_half = BM4(F1_4915_4925,
+ F1_4935_4945,
+ F1_5035_5040,
+ F1_5055_5055),
+ },
/* UNI-1 even */
- {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},
-
- {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)},
-
- {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)},
-
- {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)},
-
- {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)},
-
- {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)},
-
- {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)},
-
- {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)},
-
- {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)},
-
- {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)},
-
- {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)},
-
- {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)},
-
- {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)},
-
- {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)},
-
- {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)},
-
- {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)},
-
- {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)},
-
- {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)},
-
- {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)},
-
- {NULL1, NO_CTL, NO_DFS, NO_PSCAN, NO_REQ,
- BMZERO,
- BMZERO,
- BMZERO,
- BMZERO,
- BMZERO,
- BMZERO}
+ {.regDmnEnum = APLD,
+ .conformanceTestLimit = NO_CTL,
+ .chan11b = BM2(F2_2312_2372,F2_2412_2472),
+ .chan11g = BM2(G2_2312_2372,G2_2412_2472),
+ },
+
+ {.regDmnEnum = ETSIA,
+ .conformanceTestLimit = NO_CTL,
+ .pscan = PSCAN_ETSIA,
+ .flags = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
+ .chan11b = BM1(F1_2457_2472),
+ .chan11g = BM1(G1_2457_2472),
+ .chan11g_turbo = BM1(T2_2437_2437)
+ },
+
+ {.regDmnEnum = ETSIB,
+ .conformanceTestLimit = ETSI,
+ .pscan = PSCAN_ETSIB,
+ .flags = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
+ .chan11b = BM1(F1_2432_2442),
+ .chan11g = BM1(G1_2432_2442),
+ .chan11g_turbo = BM1(T2_2437_2437)
+ },
+
+ {.regDmnEnum = ETSIC,
+ .conformanceTestLimit = ETSI,
+ .pscan = PSCAN_ETSIC,
+ .flags = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
+ .chan11b = BM1(F3_2412_2472),
+ .chan11g = BM1(G3_2412_2472),
+ .chan11g_turbo = BM1(T2_2437_2437)
+ },
+
+ {.regDmnEnum = FCCA,
+ .conformanceTestLimit = FCC,
+ .chan11b = BM1(F1_2412_2462),
+ .chan11g = BM1(G1_2412_2462),
+ .chan11g_turbo = BM1(T2_2437_2437),
+ },
+
+ /* FCCA w/ 1/2 and 1/4 width channels */
+ {.regDmnEnum = FCCB,
+ .conformanceTestLimit = FCC,
+ .chan11b = BM1(F1_2412_2462),
+ .chan11g = BM1(G1_2412_2462),
+ .chan11g_turbo = BM1(T2_2437_2437),
+ .chan11g_half = BM1(G3_2412_2462),
+ .chan11g_quarter = BM1(G4_2412_2462),
+ },
+
+ {.regDmnEnum = MKKA,
+ .conformanceTestLimit = MKK,
+ .pscan = PSCAN_MKKA | PSCAN_MKKA_G
+ | PSCAN_MKKA1 | PSCAN_MKKA1_G
+ | PSCAN_MKKA2 | PSCAN_MKKA2_G,
+ .flags = DISALLOW_ADHOC_11A_TURB,
+ .chan11b = BM3(F2_2412_2462, F1_2467_2472, F2_2484_2484),
+ .chan11g = BM2(G2_2412_2462, G1_2467_2472),
+ .chan11g_turbo = BM1(T2_2437_2437)
+ },
+
+ {.regDmnEnum = MKKC,
+ .conformanceTestLimit = MKK,
+ .chan11b = BM1(F2_2412_2472),
+ .chan11g = BM1(G2_2412_2472),
+ .chan11g_turbo = BM1(T2_2437_2437)
+ },
+
+ {.regDmnEnum = WORLD,
+ .conformanceTestLimit = ETSI,
+ .chan11b = BM1(F2_2412_2472),
+ .chan11g = BM1(G2_2412_2472),
+ .chan11g_turbo = BM1(T2_2437_2437)
+ },
+
+ {.regDmnEnum = WOR0_WORLD,
+ .conformanceTestLimit = NO_CTL,
+ .dfsMask = DFS_FCC3 | DFS_ETSI,
+ .pscan = PSCAN_WWR,
+ .flags = ADHOC_PER_11D,
+ .chan11a = BM5(W1_5260_5320,
+ W1_5180_5240,
+ W1_5170_5230,
+ W1_5745_5825,
+ W1_5500_5700),
+ .chan11a_turbo = BM3(WT1_5210_5250,
+ WT1_5290_5290,
+ WT1_5760_5800),
+ .chan11b = BM8(W1_2412_2412,
+ W1_2437_2442,
+ W1_2462_2462,
+ W1_2472_2472,
+ W1_2417_2432,
+ W1_2447_2457,
+ W1_2467_2467,
+ W1_2484_2484),
+ .chan11g = BM7(WG1_2412_2412,
+ WG1_2437_2442,
+ WG1_2462_2462,
+ WG1_2472_2472,
+ WG1_2417_2432,
+ WG1_2447_2457,
+ WG1_2467_2467),
+ .chan11g_turbo = BM1(T3_2437_2437)
+ },
+
+ {.regDmnEnum = WOR01_WORLD,
+ .conformanceTestLimit = NO_CTL,
+ .dfsMask = DFS_FCC3 | DFS_ETSI,
+ .pscan = PSCAN_WWR,
+ .flags = ADHOC_PER_11D,
+ .chan11a = BM5(W1_5260_5320,
+ W1_5180_5240,
+ W1_5170_5230,
+ W1_5745_5825,
+ W1_5500_5700),
+ .chan11a_turbo = BM3(WT1_5210_5250,
+ WT1_5290_5290,
+ WT1_5760_5800),
+ .chan11b = BM5(W1_2412_2412,
+ W1_2437_2442,
+ W1_2462_2462,
+ W1_2417_2432,
+ W1_2447_2457),
+ .chan11g = BM5(WG1_2412_2412,
+ WG1_2437_2442,
+ WG1_2462_2462,
+ WG1_2417_2432,
+ WG1_2447_2457),
+ .chan11g_turbo = BM1(T3_2437_2437)},
+
+ {.regDmnEnum = WOR02_WORLD,
+ .conformanceTestLimit = NO_CTL,
+ .dfsMask = DFS_FCC3 | DFS_ETSI,
+ .pscan = PSCAN_WWR,
+ .flags = ADHOC_PER_11D,
+ .chan11a = BM5(W1_5260_5320,
+ W1_5180_5240,
+ W1_5170_5230,
+ W1_5745_5825,
+ W1_5500_5700),
+ .chan11a_turbo = BM3(WT1_5210_5250,
+ WT1_5290_5290,
+ WT1_5760_5800),
+ .chan11b = BM7(W1_2412_2412,
+ W1_2437_2442,
+ W1_2462_2462,
+ W1_2472_2472,
+ W1_2417_2432,
+ W1_2447_2457,
+ W1_2467_2467),
+ .chan11g = BM7(WG1_2412_2412,
+ WG1_2437_2442,
+ WG1_2462_2462,
+ WG1_2472_2472,
+ WG1_2417_2432,
+ WG1_2447_2457,
+ WG1_2467_2467),
+ .chan11g_turbo = BM1(T3_2437_2437)},
+
+ {.regDmnEnum = EU1_WORLD,
+ .conformanceTestLimit = NO_CTL,
+ .dfsMask = DFS_FCC3 | DFS_ETSI,
+ .pscan = PSCAN_WWR,
+ .flags = ADHOC_PER_11D,
+ .chan11a = BM5(W1_5260_5320,
+ W1_5180_5240,
+ W1_5170_5230,
+ W1_5745_5825,
+ W1_5500_5700),
+ .chan11a_turbo = BM3(WT1_5210_5250,
+ WT1_5290_5290,
+ WT1_5760_5800),
+ .chan11b = BM7(W1_2412_2412,
+ W1_2437_2442,
+ W1_2462_2462,
+ W2_2472_2472,
+ W1_2417_2432,
+ W1_2447_2457,
+ W2_2467_2467),
+ .chan11g = BM7(WG1_2412_2412,
+ WG1_2437_2442,
+ WG1_2462_2462,
+ WG2_2472_2472,
+ WG1_2417_2432,
+ WG1_2447_2457,
+ WG2_2467_2467),
+ .chan11g_turbo = BM1(T3_2437_2437)},
+
+ {.regDmnEnum = WOR1_WORLD,
+ .conformanceTestLimit = NO_CTL,
+ .dfsMask = DFS_FCC3 | DFS_ETSI,
+ .pscan = PSCAN_WWR,
+ .flags = 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)
+ },
+
+ {.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)},
+
+ {.regDmnEnum = WOR3_WORLD,
+ .conformanceTestLimit = NO_CTL,
+ .dfsMask = DFS_FCC3 | DFS_ETSI,
+ .pscan = PSCAN_WWR,
+ .flags = ADHOC_PER_11D,
+ .chan11a = BM4(W1_5260_5320,
+ W1_5180_5240,
+ W1_5170_5230,
+ W1_5745_5825),
+ .chan11a_turbo = BM3(WT1_5210_5250,
+ WT1_5290_5290,
+ WT1_5760_5800),
+ .chan11b = BM7(W1_2412_2412,
+ W1_2437_2442,
+ W1_2462_2462,
+ W1_2472_2472,
+ W1_2417_2432,
+ W1_2447_2457,
+ W1_2467_2467),
+ .chan11g = BM7(WG1_2412_2412,
+ WG1_2437_2442,
+ WG1_2462_2462,
+ WG1_2472_2472,
+ WG1_2417_2432,
+ WG1_2447_2457,
+ WG1_2467_2467),
+ .chan11g_turbo = BM1(T3_2437_2437)},
+
+ {.regDmnEnum = WOR4_WORLD,
+ .conformanceTestLimit = NO_CTL,
+ .dfsMask = DFS_FCC3 | DFS_ETSI,
+ .pscan = PSCAN_WWR,
+ .flags = 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)},
+
+ {.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)},
+
+ {.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)},
+
+ {.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
}
/*
@@ -1884,6 +2167,32 @@ ath_hal_ispublicsafetysku(struct ath_hal *ah)
}
/*
+ * 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 = &regDmn5GhzFreq[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 = &regDmn2Ghz11gFreq[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 8f1c3b1..d857998 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 5311908..37fa425 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;
- goto eebad;
- }
- if (eeval != 0x5aa5) {
- HALDEBUG(ah, HAL_DEBUG_ANY,
- "%s: invalid EEPROM magic number 0x%x\n", __func__, eeval);
- ecode = HAL_EEMAGIC;
+ ecode = ath_hal_v1EepromAttach(ah);
+ if (ecode != HAL_OK) {
goto eebad;
}
-
- if (!ar5210EepromRead(ah, AR_EEPROM_PROTECT, &eeval)) {
+ ecode = ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, &eeval);
+ if (ecode != HAL_OK) {
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;
- }
-
- /*
- * 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;
- }
+ }
+ OS_REG_WRITE(ah, AR_PCICFG, pcicfg); /* disable EEPROM access */
- 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 03f118e..710c03a 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 26a98a8..363c813 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 6f105e1..d7d382c 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 5ee0646..e71d78c 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 cf658ec..664b648 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 3381dc5..c3203296 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 caeef5b..ee8ede9 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 87d6fac..80c7962 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 d40549a..23d4a8a 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 9279864..207e7b7 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 3f11d8f..084fd5b 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 803c77b..a16f705 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 5bd64d5..0b8ef20 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 d8f9aa4..1236123 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 {
@@ -302,17 +306,11 @@ struct ath_hal_5212 {
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 8d9d8c0..1440f23 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 413a002..a0baf5f 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 8383645..6e636db 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 5f01104..f55b7f2 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"
@@ -80,11 +80,43 @@ ar5212SetBssIdMask(struct ath_hal *ah, const uint8_t *mask)
}
/*
+ * 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 48469ad..ae238f7 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 11bf2d2..ee87d5b 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 0000000..088cd26
--- /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 fd76fd1..e040ec7 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 9d5754c..681c6e3 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 ebf9b64..efb8568 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 ee87659..6b15a6c 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 08edf2f..4714ea1 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 52d2132..e919924 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 12e173b..7928318 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 8490431..6c0bb0a 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 9fb95df..d966693 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 db7a821..34e76b9 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 0000000..fbcab4d
--- /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 6d489ff..49ebfa5 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 43d0317..ed3812d 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 0000000..1f2314b
--- /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 0000000..1240029
--- /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 0000000..00948e2
--- /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 0000000..9e8d861
--- /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 0000000..7b9ca14
--- /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 b04d931..ce5f6bc 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 ab91e53..0384d94 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 b27d0ed..b951cfd 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 59f0711..5701ec6 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 65cfe58..b1717a6 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)) {
@@ -791,969 +780,6 @@ ar5416ChipReset(struct ath_hal *ah, HAL_CHANNEL *chan)
}
/*
- * 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 84be68c..5789852 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 dab2a53..7c60b24 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 a747b6f..416aae6 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 f7d1254..770ec22 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 4cf8992..373d773 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 4c16163..96940a9 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"
OpenPOWER on IntegriCloud