Home | History | Annotate | Line # | Download | only in ar5211
      1 /*
      2  * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
      3  * Copyright (c) 2002-2006 Atheros Communications, Inc.
      4  *
      5  * Permission to use, copy, modify, and/or distribute this software for any
      6  * purpose with or without fee is hereby granted, provided that the above
      7  * copyright notice and this permission notice appear in all copies.
      8  *
      9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     16  *
     17  * $Id: ar5211_misc.c,v 1.2 2011/03/07 11:25:42 cegger Exp $
     18  */
     19 #include "opt_ah.h"
     20 
     21 #include "ah.h"
     22 #include "ah_internal.h"
     23 
     24 #include "ar5211/ar5211.h"
     25 #include "ar5211/ar5211reg.h"
     26 #include "ar5211/ar5211phy.h"
     27 
     28 #include "ah_eeprom_v3.h"
     29 
     30 #define	AR_NUM_GPIO	6		/* 6 GPIO bits */
     31 #define	AR_GPIOD_MASK	0x2f		/* 6-bit mask */
     32 
     33 void
     34 ar5211GetMacAddress(struct ath_hal *ah, uint8_t *mac)
     35 {
     36 	struct ath_hal_5211 *ahp = AH5211(ah);
     37 
     38 	OS_MEMCPY(mac, ahp->ah_macaddr, IEEE80211_ADDR_LEN);
     39 }
     40 
     41 HAL_BOOL
     42 ar5211SetMacAddress(struct ath_hal *ah, const uint8_t *mac)
     43 {
     44 	struct ath_hal_5211 *ahp = AH5211(ah);
     45 
     46 	OS_MEMCPY(ahp->ah_macaddr, mac, IEEE80211_ADDR_LEN);
     47 	return AH_TRUE;
     48 }
     49 
     50 void
     51 ar5211GetBssIdMask(struct ath_hal *ah, uint8_t *mask)
     52 {
     53 	static const uint8_t ones[IEEE80211_ADDR_LEN] =
     54 		{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
     55 	OS_MEMCPY(mask, ones, IEEE80211_ADDR_LEN);
     56 }
     57 
     58 HAL_BOOL
     59 ar5211SetBssIdMask(struct ath_hal *ah, const uint8_t *mask)
     60 {
     61 	return AH_FALSE;
     62 }
     63 
     64 /*
     65  * Read 16 bits of data from the specified EEPROM offset.
     66  */
     67 HAL_BOOL
     68 ar5211EepromRead(struct ath_hal *ah, u_int off, uint16_t *data)
     69 {
     70 	OS_REG_WRITE(ah, AR_EEPROM_ADDR, off);
     71 	OS_REG_WRITE(ah, AR_EEPROM_CMD, AR_EEPROM_CMD_READ);
     72 
     73 	if (!ath_hal_wait(ah, AR_EEPROM_STS,
     74 	    AR_EEPROM_STS_READ_COMPLETE | AR_EEPROM_STS_READ_ERROR,
     75 	    AR_EEPROM_STS_READ_COMPLETE)) {
     76 		HALDEBUG(ah, HAL_DEBUG_ANY,
     77 		    "%s: read failed for entry 0x%x\n", __func__, off);
     78 		return AH_FALSE;
     79 	}
     80 	*data = OS_REG_READ(ah, AR_EEPROM_DATA) & 0xffff;
     81 	return AH_TRUE;
     82 }
     83 
     84 #ifdef AH_SUPPORT_WRITE_EEPROM
     85 /*
     86  * Write 16 bits of data to the specified EEPROM offset.
     87  */
     88 HAL_BOOL
     89 ar5211EepromWrite(struct ath_hal *ah, u_int off, uint16_t data)
     90 {
     91 	return AH_FALSE;
     92 }
     93 #endif /* AH_SUPPORT_WRITE_EEPROM */
     94 
     95 /*
     96  * Attempt to change the cards operating regulatory domain to the given value
     97  */
     98 HAL_BOOL
     99 ar5211SetRegulatoryDomain(struct ath_hal *ah,
    100 	uint16_t regDomain, HAL_STATUS *status)
    101 {
    102 	HAL_STATUS ecode;
    103 
    104 	if (AH_PRIVATE(ah)->ah_currentRD == regDomain) {
    105 		ecode = HAL_EINVAL;
    106 		goto bad;
    107 	}
    108 	/*
    109 	 * Check if EEPROM is configured to allow this; must
    110 	 * be a proper version and the protection bits must
    111 	 * permit re-writing that segment of the EEPROM.
    112 	 */
    113 	if (ath_hal_eepromGetFlag(ah, AR_EEP_WRITEPROTECT)) {
    114 		ecode = HAL_EEWRITE;
    115 		goto bad;
    116 	}
    117 #ifdef AH_SUPPORT_WRITE_REGDOMAIN
    118 	if (ar5211EepromWrite(ah, AR_EEPROM_REG_DOMAIN, regDomain)) {
    119 		HALDEBUG(ah, HAL_DEBUG_ANY,
    120 		    "%s: set regulatory domain to %u (0x%x)\n",
    121 		    __func__, regDomain, regDomain);
    122 		AH_PRIVATE(ah)->ah_currentRD = regDomain;
    123 		return AH_TRUE;
    124 	}
    125 #endif
    126 	ecode = HAL_EIO;
    127 bad:
    128 	if (status)
    129 		*status = ecode;
    130 	return AH_FALSE;
    131 }
    132 
    133 /*
    134  * Return the wireless modes (a,b,g,t) supported by hardware.
    135  *
    136  * This value is what is actually supported by the hardware
    137  * and is unaffected by regulatory/country code settings.
    138  *
    139  */
    140 u_int
    141 ar5211GetWirelessModes(struct ath_hal *ah)
    142 {
    143 	u_int mode = 0;
    144 
    145 	if (ath_hal_eepromGetFlag(ah, AR_EEP_AMODE)) {
    146 		mode = HAL_MODE_11A;
    147 		if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO5DISABLE))
    148 			mode |= HAL_MODE_TURBO | HAL_MODE_108A;
    149 	}
    150 	if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE))
    151 		mode |= HAL_MODE_11B;
    152 	return mode;
    153 }
    154 
    155 #if 0
    156 HAL_BOOL
    157 ar5211GetTurboDisable(struct ath_hal *ah)
    158 {
    159 	return (AH5211(ah)->ah_turboDisable != 0);
    160 }
    161 #endif
    162 
    163 /*
    164  * Called if RfKill is supported (according to EEPROM).  Set the interrupt and
    165  * GPIO values so the ISR and can disable RF on a switch signal
    166  */
    167 void
    168 ar5211EnableRfKill(struct ath_hal *ah)
    169 {
    170 	uint16_t rfsilent = AH_PRIVATE(ah)->ah_rfsilent;
    171 	int select = MS(rfsilent, AR_EEPROM_RFSILENT_GPIO_SEL);
    172 	int polarity = MS(rfsilent, AR_EEPROM_RFSILENT_POLARITY);
    173 
    174 	/*
    175 	 * Configure the desired GPIO port for input
    176 	 * and enable baseband rf silence.
    177 	 */
    178 	ar5211GpioCfgInput(ah, select);
    179 	OS_REG_SET_BIT(ah, AR_PHY_BASE, 0x00002000);
    180 	/*
    181 	 * If radio disable switch connection to GPIO bit x is enabled
    182 	 * program GPIO interrupt.
    183 	 * If rfkill bit on eeprom is 1, setupeeprommap routine has already
    184 	 * verified that it is a later version of eeprom, it has a place for
    185 	 * rfkill bit and it is set to 1, indicating that GPIO bit x hardware
    186 	 * connection is present.
    187 	 */
    188 	ar5211GpioSetIntr(ah, select, (ar5211GpioGet(ah, select) != polarity));
    189 }
    190 
    191 /*
    192  * Configure GPIO Output lines
    193  */
    194 HAL_BOOL
    195 ar5211GpioCfgOutput(struct ath_hal *ah, uint32_t gpio, HAL_GPIO_MUX_TYPE type)
    196 {
    197 	uint32_t reg;
    198 
    199 	HALASSERT(gpio < AR_NUM_GPIO);
    200 
    201 	reg =  OS_REG_READ(ah, AR_GPIOCR);
    202 	reg &= ~(AR_GPIOCR_0_CR_A << (gpio * AR_GPIOCR_CR_SHIFT));
    203 	reg |= AR_GPIOCR_0_CR_A << (gpio * AR_GPIOCR_CR_SHIFT);
    204 
    205 	OS_REG_WRITE(ah, AR_GPIOCR, reg);
    206 	return AH_TRUE;
    207 }
    208 
    209 /*
    210  * Configure GPIO Input lines
    211  */
    212 HAL_BOOL
    213 ar5211GpioCfgInput(struct ath_hal *ah, uint32_t gpio)
    214 {
    215 	uint32_t reg;
    216 
    217 	HALASSERT(gpio < AR_NUM_GPIO);
    218 
    219 	reg =  OS_REG_READ(ah, AR_GPIOCR);
    220 	reg &= ~(AR_GPIOCR_0_CR_A << (gpio * AR_GPIOCR_CR_SHIFT));
    221 	reg |= AR_GPIOCR_0_CR_N << (gpio * AR_GPIOCR_CR_SHIFT);
    222 
    223 	OS_REG_WRITE(ah, AR_GPIOCR, reg);
    224 	return AH_TRUE;
    225 }
    226 
    227 /*
    228  * Once configured for I/O - set output lines
    229  */
    230 HAL_BOOL
    231 ar5211GpioSet(struct ath_hal *ah, uint32_t gpio, uint32_t val)
    232 {
    233 	uint32_t reg;
    234 
    235 	HALASSERT(gpio < AR_NUM_GPIO);
    236 
    237 	reg =  OS_REG_READ(ah, AR_GPIODO);
    238 	reg &= ~(1 << gpio);
    239 	reg |= (val&1) << gpio;
    240 
    241 	OS_REG_WRITE(ah, AR_GPIODO, reg);
    242 	return AH_TRUE;
    243 }
    244 
    245 /*
    246  * Once configured for I/O - get input lines
    247  */
    248 uint32_t
    249 ar5211GpioGet(struct ath_hal *ah, uint32_t gpio)
    250 {
    251 	if (gpio < AR_NUM_GPIO) {
    252 		uint32_t val = OS_REG_READ(ah, AR_GPIODI);
    253 		val = ((val & AR_GPIOD_MASK) >> gpio) & 0x1;
    254 		return val;
    255 	} else  {
    256 		return 0xffffffff;
    257 	}
    258 }
    259 
    260 /*
    261  * Set the GPIO 0 Interrupt (gpio is ignored)
    262  */
    263 void
    264 ar5211GpioSetIntr(struct ath_hal *ah, u_int gpio, uint32_t ilevel)
    265 {
    266 	uint32_t val = OS_REG_READ(ah, AR_GPIOCR);
    267 
    268 	/* Clear the bits that we will modify. */
    269 	val &= ~(AR_GPIOCR_INT_SEL0 | AR_GPIOCR_INT_SELH | AR_GPIOCR_INT_ENA |
    270 			AR_GPIOCR_0_CR_A);
    271 
    272 	val |= AR_GPIOCR_INT_SEL0 | AR_GPIOCR_INT_ENA;
    273 	if (ilevel)
    274 		val |= AR_GPIOCR_INT_SELH;
    275 
    276 	/* Don't need to change anything for low level interrupt. */
    277 	OS_REG_WRITE(ah, AR_GPIOCR, val);
    278 
    279 	/* Change the interrupt mask. */
    280 	ar5211SetInterrupts(ah, AH5211(ah)->ah_maskReg | HAL_INT_GPIO);
    281 }
    282 
    283 /*
    284  * Change the LED blinking pattern to correspond to the connectivity
    285  */
    286 void
    287 ar5211SetLedState(struct ath_hal *ah, HAL_LED_STATE state)
    288 {
    289 	static const uint32_t ledbits[8] = {
    290 		AR_PCICFG_LEDCTL_NONE|AR_PCICFG_LEDMODE_PROP, /* HAL_LED_INIT */
    291 		AR_PCICFG_LEDCTL_PEND|AR_PCICFG_LEDMODE_PROP, /* HAL_LED_SCAN */
    292 		AR_PCICFG_LEDCTL_PEND|AR_PCICFG_LEDMODE_PROP, /* HAL_LED_AUTH */
    293 		AR_PCICFG_LEDCTL_ASSOC|AR_PCICFG_LEDMODE_PROP,/* HAL_LED_ASSOC*/
    294 		AR_PCICFG_LEDCTL_ASSOC|AR_PCICFG_LEDMODE_PROP,/* HAL_LED_RUN */
    295 		AR_PCICFG_LEDCTL_NONE|AR_PCICFG_LEDMODE_RAND,
    296 		AR_PCICFG_LEDCTL_NONE|AR_PCICFG_LEDMODE_RAND,
    297 		AR_PCICFG_LEDCTL_NONE|AR_PCICFG_LEDMODE_RAND,
    298 	};
    299 	OS_REG_WRITE(ah, AR_PCICFG,
    300 		(OS_REG_READ(ah, AR_PCICFG) &~
    301 			(AR_PCICFG_LEDCTL | AR_PCICFG_LEDMODE))
    302 		| ledbits[state & 0x7]
    303 	);
    304 }
    305 
    306 /*
    307  * Change association related fields programmed into the hardware.
    308  * Writing a valid BSSID to the hardware effectively enables the hardware
    309  * to synchronize its TSF to the correct beacons and receive frames coming
    310  * from that BSSID. It is called by the SME JOIN operation.
    311  */
    312 void
    313 ar5211WriteAssocid(struct ath_hal *ah, const uint8_t *bssid, uint16_t assocId)
    314 {
    315 	struct ath_hal_5211 *ahp = AH5211(ah);
    316 
    317 	/* XXX save bssid for possible re-use on reset */
    318 	OS_MEMCPY(ahp->ah_bssid, bssid, IEEE80211_ADDR_LEN);
    319 	OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid));
    320 	OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid+4) |
    321 				     ((assocId & 0x3fff)<<AR_BSS_ID1_AID_S));
    322 }
    323 
    324 /*
    325  * Get the current hardware tsf for stamlme.
    326  */
    327 uint64_t
    328 ar5211GetTsf64(struct ath_hal *ah)
    329 {
    330 	uint32_t low1, low2, u32;
    331 
    332 	/* sync multi-word read */
    333 	low1 = OS_REG_READ(ah, AR_TSF_L32);
    334 	u32 = OS_REG_READ(ah, AR_TSF_U32);
    335 	low2 = OS_REG_READ(ah, AR_TSF_L32);
    336 	if (low2 < low1) {	/* roll over */
    337 		/*
    338 		 * If we are not preempted this will work.  If we are
    339 		 * then we re-reading AR_TSF_U32 does no good as the
    340 		 * low bits will be meaningless.  Likewise reading
    341 		 * L32, U32, U32, then comparing the last two reads
    342 		 * to check for rollover doesn't help if preempted--so
    343 		 * we take this approach as it costs one less PCI
    344 		 * read which can be noticeable when doing things
    345 		 * like timestamping packets in monitor mode.
    346 		 */
    347 		u32++;
    348 	}
    349 	return (((uint64_t) u32) << 32) | ((uint64_t) low2);
    350 }
    351 
    352 /*
    353  * Get the current hardware tsf for stamlme.
    354  */
    355 uint32_t
    356 ar5211GetTsf32(struct ath_hal *ah)
    357 {
    358 	return OS_REG_READ(ah, AR_TSF_L32);
    359 }
    360 
    361 /*
    362  * Reset the current hardware tsf for stamlme
    363  */
    364 void
    365 ar5211ResetTsf(struct ath_hal *ah)
    366 {
    367 	uint32_t val = OS_REG_READ(ah, AR_BEACON);
    368 
    369 	OS_REG_WRITE(ah, AR_BEACON, val | AR_BEACON_RESET_TSF);
    370 }
    371 
    372 /*
    373  * Grab a semi-random value from hardware registers - may not
    374  * change often
    375  */
    376 uint32_t
    377 ar5211GetRandomSeed(struct ath_hal *ah)
    378 {
    379 	uint32_t nf;
    380 
    381 	nf = (OS_REG_READ(ah, AR_PHY(25)) >> 19) & 0x1ff;
    382 	if (nf & 0x100)
    383 		nf = 0 - ((nf ^ 0x1ff) + 1);
    384 	return (OS_REG_READ(ah, AR_TSF_U32) ^
    385 		OS_REG_READ(ah, AR_TSF_L32) ^ nf);
    386 }
    387 
    388 /*
    389  * Detect if our card is present
    390  */
    391 HAL_BOOL
    392 ar5211DetectCardPresent(struct ath_hal *ah)
    393 {
    394 	uint16_t macVersion, macRev;
    395 	uint32_t v;
    396 
    397 	/*
    398 	 * Read the Silicon Revision register and compare that
    399 	 * to what we read at attach time.  If the same, we say
    400 	 * a card/device is present.
    401 	 */
    402 	v = OS_REG_READ(ah, AR_SREV) & AR_SREV_ID_M;
    403 	macVersion = v >> AR_SREV_ID_S;
    404 	macRev = v & AR_SREV_REVISION_M;
    405 	return (AH_PRIVATE(ah)->ah_macVersion == macVersion &&
    406 		AH_PRIVATE(ah)->ah_macRev == macRev);
    407 }
    408 
    409 /*
    410  * Update MIB Counters
    411  */
    412 void
    413 ar5211UpdateMibCounters(struct ath_hal *ah, HAL_MIB_STATS *stats)
    414 {
    415 	stats->ackrcv_bad += OS_REG_READ(ah, AR_ACK_FAIL);
    416 	stats->rts_bad	  += OS_REG_READ(ah, AR_RTS_FAIL);
    417 	stats->fcs_bad	  += OS_REG_READ(ah, AR_FCS_FAIL);
    418 	stats->rts_good	  += OS_REG_READ(ah, AR_RTS_OK);
    419 	stats->beacons	  += OS_REG_READ(ah, AR_BEACON_CNT);
    420 }
    421 
    422 HAL_BOOL
    423 ar5211SetSifsTime(struct ath_hal *ah, u_int us)
    424 {
    425 	struct ath_hal_5211 *ahp = AH5211(ah);
    426 
    427 	if (us > ath_hal_mac_usec(ah, 0xffff)) {
    428 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad SIFS time %u\n",
    429 		    __func__, us);
    430 		ahp->ah_sifstime = (u_int) -1;	/* restore default handling */
    431 		return AH_FALSE;
    432 	} else {
    433 		/* convert to system clocks */
    434 		OS_REG_WRITE(ah, AR_D_GBL_IFS_SIFS, ath_hal_mac_clks(ah, us));
    435 		ahp->ah_slottime = us;
    436 		return AH_TRUE;
    437 	}
    438 }
    439 
    440 u_int
    441 ar5211GetSifsTime(struct ath_hal *ah)
    442 {
    443 	u_int clks = OS_REG_READ(ah, AR_D_GBL_IFS_SIFS) & 0xffff;
    444 	return ath_hal_mac_usec(ah, clks);	/* convert from system clocks */
    445 }
    446 
    447 HAL_BOOL
    448 ar5211SetSlotTime(struct ath_hal *ah, u_int us)
    449 {
    450 	struct ath_hal_5211 *ahp = AH5211(ah);
    451 
    452 	if (us < HAL_SLOT_TIME_9 || us > ath_hal_mac_usec(ah, 0xffff)) {
    453 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad slot time %u\n",
    454 		    __func__, us);
    455 		ahp->ah_slottime = us;	/* restore default handling */
    456 		return AH_FALSE;
    457 	} else {
    458 		/* convert to system clocks */
    459 		OS_REG_WRITE(ah, AR_D_GBL_IFS_SLOT, ath_hal_mac_clks(ah, us));
    460 		ahp->ah_slottime = us;
    461 		return AH_TRUE;
    462 	}
    463 }
    464 
    465 u_int
    466 ar5211GetSlotTime(struct ath_hal *ah)
    467 {
    468 	u_int clks = OS_REG_READ(ah, AR_D_GBL_IFS_SLOT) & 0xffff;
    469 	return ath_hal_mac_usec(ah, clks);	/* convert from system clocks */
    470 }
    471 
    472 HAL_BOOL
    473 ar5211SetAckTimeout(struct ath_hal *ah, u_int us)
    474 {
    475 	struct ath_hal_5211 *ahp = AH5211(ah);
    476 
    477 	if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) {
    478 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad ack timeout %u\n",
    479 		    __func__, us);
    480 		ahp->ah_acktimeout = (u_int) -1; /* restore default handling */
    481 		return AH_FALSE;
    482 	} else {
    483 		/* convert to system clocks */
    484 		OS_REG_RMW_FIELD(ah, AR_TIME_OUT,
    485 			AR_TIME_OUT_ACK, ath_hal_mac_clks(ah, us));
    486 		ahp->ah_acktimeout = us;
    487 		return AH_TRUE;
    488 	}
    489 }
    490 
    491 u_int
    492 ar5211GetAckTimeout(struct ath_hal *ah)
    493 {
    494 	u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_ACK);
    495 	return ath_hal_mac_usec(ah, clks);	/* convert from system clocks */
    496 }
    497 
    498 u_int
    499 ar5211GetAckCTSRate(struct ath_hal *ah)
    500 {
    501 	return ((AH5211(ah)->ah_staId1Defaults & AR_STA_ID1_ACKCTS_6MB) == 0);
    502 }
    503 
    504 HAL_BOOL
    505 ar5211SetAckCTSRate(struct ath_hal *ah, u_int high)
    506 {
    507 	struct ath_hal_5211 *ahp = AH5211(ah);
    508 
    509 	if (high) {
    510 		OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB);
    511 		ahp->ah_staId1Defaults &= ~AR_STA_ID1_ACKCTS_6MB;
    512 	} else {
    513 		OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB);
    514 		ahp->ah_staId1Defaults |= AR_STA_ID1_ACKCTS_6MB;
    515 	}
    516 	return AH_TRUE;
    517 }
    518 
    519 HAL_BOOL
    520 ar5211SetCTSTimeout(struct ath_hal *ah, u_int us)
    521 {
    522 	struct ath_hal_5211 *ahp = AH5211(ah);
    523 
    524 	if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) {
    525 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad cts timeout %u\n",
    526 		    __func__, us);
    527 		ahp->ah_ctstimeout = (u_int) -1; /* restore default handling */
    528 		return AH_FALSE;
    529 	} else {
    530 		/* convert to system clocks */
    531 		OS_REG_RMW_FIELD(ah, AR_TIME_OUT,
    532 			AR_TIME_OUT_CTS, ath_hal_mac_clks(ah, us));
    533 		ahp->ah_ctstimeout = us;
    534 		return AH_TRUE;
    535 	}
    536 }
    537 
    538 u_int
    539 ar5211GetCTSTimeout(struct ath_hal *ah)
    540 {
    541 	u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_CTS);
    542 	return ath_hal_mac_usec(ah, clks);	/* convert from system clocks */
    543 }
    544 
    545 HAL_BOOL
    546 ar5211SetDecompMask(struct ath_hal *ah, uint16_t keyidx, int en)
    547 {
    548 	/* nothing to do */
    549         return AH_TRUE;
    550 }
    551 
    552 void
    553 ar5211SetCoverageClass(struct ath_hal *ah, uint8_t coverageclass, int now)
    554 {
    555 }
    556 
    557 /*
    558  * Control Adaptive Noise Immunity Parameters
    559  */
    560 HAL_BOOL
    561 ar5211AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param)
    562 {
    563 	return AH_FALSE;
    564 }
    565 
    566 void
    567 ar5211AniPoll(struct ath_hal *ah, const HAL_NODE_STATS *stats, HAL_CHANNEL *chan)
    568 {
    569 }
    570 
    571 void
    572 ar5211MibEvent(struct ath_hal *ah, const HAL_NODE_STATS *stats)
    573 {
    574 }
    575 
    576 /*
    577  * Get the rssi of frame curently being received.
    578  */
    579 uint32_t
    580 ar5211GetCurRssi(struct ath_hal *ah)
    581 {
    582 	return (OS_REG_READ(ah, AR_PHY_CURRENT_RSSI) & 0xff);
    583 }
    584 
    585 u_int
    586 ar5211GetDefAntenna(struct ath_hal *ah)
    587 {
    588 	return (OS_REG_READ(ah, AR_DEF_ANTENNA) & 0x7);
    589 }
    590 
    591 void
    592 ar5211SetDefAntenna(struct ath_hal *ah, u_int antenna)
    593 {
    594 	OS_REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7));
    595 }
    596 
    597 HAL_ANT_SETTING
    598 ar5211GetAntennaSwitch(struct ath_hal *ah)
    599 {
    600 	return AH5211(ah)->ah_diversityControl;
    601 }
    602 
    603 HAL_BOOL
    604 ar5211SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings)
    605 {
    606 	const HAL_CHANNEL *chan =
    607 		(const HAL_CHANNEL *) AH_PRIVATE(ah)->ah_curchan;
    608 
    609 	if (chan == AH_NULL) {
    610 		AH5211(ah)->ah_diversityControl = settings;
    611 		return AH_TRUE;
    612 	}
    613 	return ar5211SetAntennaSwitchInternal(ah, settings, chan);
    614 }
    615 
    616 HAL_STATUS
    617 ar5211GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
    618 	uint32_t capability, uint32_t *result)
    619 {
    620 
    621 	switch (type) {
    622 	case HAL_CAP_CIPHER:		/* cipher handled in hardware */
    623 		switch (capability) {
    624 		case HAL_CIPHER_AES_OCB:
    625 		case HAL_CIPHER_WEP:
    626 		case HAL_CIPHER_CLR:
    627 			return HAL_OK;
    628 		default:
    629 			return HAL_ENOTSUPP;
    630 		}
    631 	default:
    632 		return ath_hal_getcapability(ah, type, capability, result);
    633 	}
    634 }
    635 
    636 HAL_BOOL
    637 ar5211SetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
    638 	uint32_t capability, uint32_t setting, HAL_STATUS *status)
    639 {
    640 	switch (type) {
    641 	case HAL_CAP_DIAG:		/* hardware diagnostic support */
    642 		/*
    643 		 * NB: could split this up into virtual capabilities,
    644 		 *     (e.g. 1 => ACK, 2 => CTS, etc.) but it hardly
    645 		 *     seems worth the additional complexity.
    646 		 */
    647 #ifdef AH_DEBUG
    648 		AH_PRIVATE(ah)->ah_diagreg = setting;
    649 #else
    650 		AH_PRIVATE(ah)->ah_diagreg = setting & 0x6;	/* ACK+CTS */
    651 #endif
    652 		OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg);
    653 		return AH_TRUE;
    654 	default:
    655 		return ath_hal_setcapability(ah, type, capability,
    656 			setting, status);
    657 	}
    658 }
    659 
    660 HAL_BOOL
    661 ar5211GetDiagState(struct ath_hal *ah, int request,
    662 	const void *args, uint32_t argsize,
    663 	void **result, uint32_t *resultsize)
    664 {
    665 	struct ath_hal_5211 *ahp = AH5211(ah);
    666 
    667 	(void) ahp;
    668 	if (ath_hal_getdiagstate(ah, request, args, argsize, result, resultsize))
    669 		return AH_TRUE;
    670 	switch (request) {
    671 	case HAL_DIAG_EEPROM:
    672 		return ath_hal_eepromDiag(ah, request,
    673 		    args, argsize, result, resultsize);
    674 	case HAL_DIAG_RFGAIN:
    675 		*result = &ahp->ah_gainValues;
    676 		*resultsize = sizeof(GAIN_VALUES);
    677 		return AH_TRUE;
    678 	case HAL_DIAG_RFGAIN_CURSTEP:
    679 		*result = __DECONST(void *, ahp->ah_gainValues.currStep);
    680 		*resultsize = (*result == AH_NULL) ?
    681 			0 : sizeof(GAIN_OPTIMIZATION_STEP);
    682 		return AH_TRUE;
    683 	}
    684 	return AH_FALSE;
    685 }
    686