Home | History | Annotate | Line # | Download | only in ar5210
      1 /*
      2  * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
      3  * Copyright (c) 2002-2004 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: ar5210_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 "ar5210/ar5210.h"
     25 #include "ar5210/ar5210reg.h"
     26 #include "ar5210/ar5210phy.h"
     27 
     28 #include "ah_eeprom_v1.h"
     29 
     30 #define	AR_NUM_GPIO	6		/* 6 GPIO bits */
     31 #define	AR_GPIOD_MASK	0x2f		/* 6-bit mask */
     32 
     33 void
     34 ar5210GetMacAddress(struct ath_hal *ah, uint8_t *mac)
     35 {
     36 	struct ath_hal_5210 *ahp = AH5210(ah);
     37 
     38 	OS_MEMCPY(mac, ahp->ah_macaddr, IEEE80211_ADDR_LEN);
     39 }
     40 
     41 HAL_BOOL
     42 ar5210SetMacAddress(struct ath_hal *ah, const uint8_t *mac)
     43 {
     44 	struct ath_hal_5210 *ahp = AH5210(ah);
     45 
     46 	OS_MEMCPY(ahp->ah_macaddr, mac, IEEE80211_ADDR_LEN);
     47 	return AH_TRUE;
     48 }
     49 
     50 void
     51 ar5210GetBssIdMask(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 ar5210SetBssIdMask(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 ar5210EepromRead(struct ath_hal *ah, u_int off, uint16_t *data)
     69 {
     70 	(void) OS_REG_READ(ah, AR_EP_AIR(off));	/* activate read op */
     71 	if (!ath_hal_wait(ah, AR_EP_STA,
     72 	    AR_EP_STA_RDCMPLT | AR_EP_STA_RDERR, AR_EP_STA_RDCMPLT)) {
     73 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: read failed for entry 0x%x\n",
     74 		    __func__, AR_EP_AIR(off));
     75 		return AH_FALSE;
     76 	}
     77 	*data = OS_REG_READ(ah, AR_EP_RDATA) & 0xffff;
     78 	return AH_TRUE;
     79 }
     80 
     81 #ifdef AH_SUPPORT_WRITE_EEPROM
     82 /*
     83  * Write 16 bits of data to the specified EEPROM offset.
     84  */
     85 HAL_BOOL
     86 ar5210EepromWrite(struct ath_hal *ah, u_int off, uint16_t data)
     87 {
     88 	return AH_FALSE;
     89 }
     90 #endif /* AH_SUPPORT_WRITE_EEPROM */
     91 
     92 /*
     93  * Attempt to change the cards operating regulatory domain to the given value
     94  */
     95 HAL_BOOL
     96 ar5210SetRegulatoryDomain(struct ath_hal *ah,
     97 	uint16_t regDomain, HAL_STATUS *status)
     98 {
     99 	HAL_STATUS ecode;
    100 
    101 	if (AH_PRIVATE(ah)->ah_currentRD == regDomain) {
    102 		ecode = HAL_EINVAL;
    103 		goto bad;
    104 	}
    105 	/*
    106 	 * Check if EEPROM is configured to allow this; must
    107 	 * be a proper version and the protection bits must
    108 	 * permit re-writing that segment of the EEPROM.
    109 	 */
    110 	if (ath_hal_eepromGetFlag(ah, AR_EEP_WRITEPROTECT)) {
    111 		ecode = HAL_EEWRITE;
    112 		goto bad;
    113 	}
    114 	ecode = HAL_EIO;		/* disallow all writes */
    115 bad:
    116 	if (status)
    117 		*status = ecode;
    118 	return AH_FALSE;
    119 }
    120 
    121 /*
    122  * Return the wireless modes (a,b,g,t) supported by hardware.
    123  *
    124  * This value is what is actually supported by the hardware
    125  * and is unaffected by regulatory/country code settings.
    126  *
    127  */
    128 u_int
    129 ar5210GetWirelessModes(struct ath_hal *ah)
    130 {
    131 	/* XXX could enable turbo mode but can't do all rates */
    132 	return HAL_MODE_11A;
    133 }
    134 
    135 /*
    136  * Called if RfKill is supported (according to EEPROM).  Set the interrupt and
    137  * GPIO values so the ISR and can disable RF on a switch signal
    138  */
    139 void
    140 ar5210EnableRfKill(struct ath_hal *ah)
    141 {
    142 	uint16_t rfsilent = AH_PRIVATE(ah)->ah_rfsilent;
    143 	int select = MS(rfsilent, AR_EEPROM_RFSILENT_GPIO_SEL);
    144 	int polarity = MS(rfsilent, AR_EEPROM_RFSILENT_POLARITY);
    145 
    146 	/*
    147 	 * If radio disable switch connection to GPIO bit 0 is enabled
    148 	 * program GPIO interrupt.
    149 	 * If rfkill bit on eeprom is 1, setupeeprommap routine has already
    150 	 * verified that it is a later version of eeprom, it has a place for
    151 	 * rfkill bit and it is set to 1, indicating that GPIO bit 0 hardware
    152 	 * connection is present.
    153 	 */
    154 	ar5210Gpio0SetIntr(ah, select, (ar5210GpioGet(ah, select) == polarity));
    155 }
    156 
    157 /*
    158  * Configure GPIO Output lines
    159  */
    160 HAL_BOOL
    161 ar5210GpioCfgOutput(struct ath_hal *ah, uint32_t gpio, HAL_GPIO_MUX_TYPE type)
    162 {
    163 	HALASSERT(gpio < AR_NUM_GPIO);
    164 
    165 	OS_REG_WRITE(ah, AR_GPIOCR,
    166 		  (OS_REG_READ(ah, AR_GPIOCR) &~ AR_GPIOCR_ALL(gpio))
    167 		| AR_GPIOCR_OUT1(gpio));
    168 
    169 	return AH_TRUE;
    170 }
    171 
    172 /*
    173  * Configure GPIO Input lines
    174  */
    175 HAL_BOOL
    176 ar5210GpioCfgInput(struct ath_hal *ah, uint32_t gpio)
    177 {
    178 	HALASSERT(gpio < AR_NUM_GPIO);
    179 
    180 	OS_REG_WRITE(ah, AR_GPIOCR,
    181 		  (OS_REG_READ(ah, AR_GPIOCR) &~ AR_GPIOCR_ALL(gpio))
    182 		| AR_GPIOCR_IN(gpio));
    183 
    184 	return AH_TRUE;
    185 }
    186 
    187 /*
    188  * Once configured for I/O - set output lines
    189  */
    190 HAL_BOOL
    191 ar5210GpioSet(struct ath_hal *ah, uint32_t gpio, uint32_t val)
    192 {
    193 	uint32_t reg;
    194 
    195 	HALASSERT(gpio < AR_NUM_GPIO);
    196 
    197 	reg =  OS_REG_READ(ah, AR_GPIODO);
    198 	reg &= ~(1 << gpio);
    199 	reg |= (val&1) << gpio;
    200 
    201 	OS_REG_WRITE(ah, AR_GPIODO, reg);
    202 	return AH_TRUE;
    203 }
    204 
    205 /*
    206  * Once configured for I/O - get input lines
    207  */
    208 uint32_t
    209 ar5210GpioGet(struct ath_hal *ah, uint32_t gpio)
    210 {
    211 	if (gpio < AR_NUM_GPIO) {
    212 		uint32_t val = OS_REG_READ(ah, AR_GPIODI);
    213 		val = ((val & AR_GPIOD_MASK) >> gpio) & 0x1;
    214 		return val;
    215 	} else  {
    216 		return 0xffffffff;
    217 	}
    218 }
    219 
    220 /*
    221  * Set the GPIO 0 Interrupt
    222  */
    223 void
    224 ar5210Gpio0SetIntr(struct ath_hal *ah, u_int gpio, uint32_t ilevel)
    225 {
    226 	uint32_t val = OS_REG_READ(ah, AR_GPIOCR);
    227 
    228 	/* Clear the bits that we will modify. */
    229 	val &= ~(AR_GPIOCR_INT_SEL(gpio) | AR_GPIOCR_INT_SELH | AR_GPIOCR_INT_ENA |
    230 			AR_GPIOCR_ALL(gpio));
    231 
    232 	val |= AR_GPIOCR_INT_SEL(gpio) | AR_GPIOCR_INT_ENA;
    233 	if (ilevel)
    234 		val |= AR_GPIOCR_INT_SELH;
    235 
    236 	/* Don't need to change anything for low level interrupt. */
    237 	OS_REG_WRITE(ah, AR_GPIOCR, val);
    238 
    239 	/* Change the interrupt mask. */
    240 	ar5210SetInterrupts(ah, AH5210(ah)->ah_maskReg | HAL_INT_GPIO);
    241 }
    242 
    243 /*
    244  * Change the LED blinking pattern to correspond to the connectivity
    245  */
    246 void
    247 ar5210SetLedState(struct ath_hal *ah, HAL_LED_STATE state)
    248 {
    249 	uint32_t val;
    250 
    251 	val = OS_REG_READ(ah, AR_PCICFG);
    252 	switch (state) {
    253 	case HAL_LED_INIT:
    254 		val &= ~(AR_PCICFG_LED_PEND | AR_PCICFG_LED_ACT);
    255 		break;
    256 	case HAL_LED_RUN:
    257 		/* normal blink when connected */
    258 		val &= ~AR_PCICFG_LED_PEND;
    259 		val |= AR_PCICFG_LED_ACT;
    260 		break;
    261 	default:
    262 		val |= AR_PCICFG_LED_PEND;
    263 		val &= ~AR_PCICFG_LED_ACT;
    264 		break;
    265 	}
    266 	OS_REG_WRITE(ah, AR_PCICFG, val);
    267 }
    268 
    269 /*
    270  * Return 1 or 2 for the corresponding antenna that is in use
    271  */
    272 u_int
    273 ar5210GetDefAntenna(struct ath_hal *ah)
    274 {
    275 	uint32_t val = OS_REG_READ(ah, AR_STA_ID1);
    276 	return (val & AR_STA_ID1_DEFAULT_ANTENNA ?  2 : 1);
    277 }
    278 
    279 void
    280 ar5210SetDefAntenna(struct ath_hal *ah, u_int antenna)
    281 {
    282 	uint32_t val = OS_REG_READ(ah, AR_STA_ID1);
    283 
    284 	if (antenna != (val & AR_STA_ID1_DEFAULT_ANTENNA ?  2 : 1)) {
    285 		/*
    286 		 * Antenna change requested, force a toggle of the default.
    287 		 */
    288 		OS_REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_DEFAULT_ANTENNA);
    289 	}
    290 }
    291 
    292 HAL_ANT_SETTING
    293 ar5210GetAntennaSwitch(struct ath_hal *ah)
    294 {
    295 	return HAL_ANT_VARIABLE;
    296 }
    297 
    298 HAL_BOOL
    299 ar5210SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings)
    300 {
    301 	/* XXX not sure how to fix antenna */
    302 	return (settings == HAL_ANT_VARIABLE);
    303 }
    304 
    305 /*
    306  * Change association related fields programmed into the hardware.
    307  * Writing a valid BSSID to the hardware effectively enables the hardware
    308  * to synchronize its TSF to the correct beacons and receive frames coming
    309  * from that BSSID. It is called by the SME JOIN operation.
    310  */
    311 void
    312 ar5210WriteAssocid(struct ath_hal *ah, const uint8_t *bssid, uint16_t assocId)
    313 {
    314 	struct ath_hal_5210 *ahp = AH5210(ah);
    315 
    316 	/* XXX save bssid for possible re-use on reset */
    317 	OS_MEMCPY(ahp->ah_bssid, bssid, IEEE80211_ADDR_LEN);
    318 	OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid));
    319 	OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid+4) |
    320 				     ((assocId & 0x3fff)<<AR_BSS_ID1_AID_S));
    321 	if (assocId == 0)
    322 		OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_NO_PSPOLL);
    323 	else
    324 		OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_NO_PSPOLL);
    325 }
    326 
    327 /*
    328  * Get the current hardware tsf for stamlme.
    329  */
    330 uint64_t
    331 ar5210GetTsf64(struct ath_hal *ah)
    332 {
    333 	uint32_t low1, low2, u32;
    334 
    335 	/* sync multi-word read */
    336 	low1 = OS_REG_READ(ah, AR_TSF_L32);
    337 	u32 = OS_REG_READ(ah, AR_TSF_U32);
    338 	low2 = OS_REG_READ(ah, AR_TSF_L32);
    339 	if (low2 < low1) {	/* roll over */
    340 		/*
    341 		 * If we are not preempted this will work.  If we are
    342 		 * then we re-reading AR_TSF_U32 does no good as the
    343 		 * low bits will be meaningless.  Likewise reading
    344 		 * L32, U32, U32, then comparing the last two reads
    345 		 * to check for rollover doesn't help if preempted--so
    346 		 * we take this approach as it costs one less PCI
    347 		 * read which can be noticeable when doing things
    348 		 * like timestamping packets in monitor mode.
    349 		 */
    350 		u32++;
    351 	}
    352 	return (((uint64_t) u32) << 32) | ((uint64_t) low2);
    353 }
    354 
    355 /*
    356  * Get the current hardware tsf for stamlme.
    357  */
    358 uint32_t
    359 ar5210GetTsf32(struct ath_hal *ah)
    360 {
    361 	return OS_REG_READ(ah, AR_TSF_L32);
    362 }
    363 
    364 /*
    365  * Reset the current hardware tsf for stamlme
    366  */
    367 void
    368 ar5210ResetTsf(struct ath_hal *ah)
    369 {
    370 	uint32_t val = OS_REG_READ(ah, AR_BEACON);
    371 
    372 	OS_REG_WRITE(ah, AR_BEACON, val | AR_BEACON_RESET_TSF);
    373 }
    374 
    375 /*
    376  * Grab a semi-random value from hardware registers - may not
    377  * change often
    378  */
    379 uint32_t
    380 ar5210GetRandomSeed(struct ath_hal *ah)
    381 {
    382 	uint32_t nf;
    383 
    384 	nf = (OS_REG_READ(ah, AR_PHY_BASE + (25 << 2)) >> 19) & 0x1ff;
    385 	if (nf & 0x100)
    386 		nf = 0 - ((nf ^ 0x1ff) + 1);
    387 	return (OS_REG_READ(ah, AR_TSF_U32) ^
    388 		OS_REG_READ(ah, AR_TSF_L32) ^ nf);
    389 }
    390 
    391 /*
    392  * Detect if our card is present
    393  */
    394 HAL_BOOL
    395 ar5210DetectCardPresent(struct ath_hal *ah)
    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 	return (AH_PRIVATE(ah)->ah_macRev == (OS_REG_READ(ah, AR_SREV) & 0xff));
    403 }
    404 
    405 /*
    406  * Update MIB Counters
    407  */
    408 void
    409 ar5210UpdateMibCounters(struct ath_hal *ah, HAL_MIB_STATS *stats)
    410 {
    411 	stats->ackrcv_bad += OS_REG_READ(ah, AR_ACK_FAIL);
    412 	stats->rts_bad	  += OS_REG_READ(ah, AR_RTS_FAIL);
    413 	stats->fcs_bad	  += OS_REG_READ(ah, AR_FCS_FAIL);
    414 	stats->rts_good	  += OS_REG_READ(ah, AR_RTS_OK);
    415 	stats->beacons	  += OS_REG_READ(ah, AR_BEACON_CNT);
    416 }
    417 
    418 HAL_BOOL
    419 ar5210SetSifsTime(struct ath_hal *ah, u_int us)
    420 {
    421 	struct ath_hal_5210 *ahp = AH5210(ah);
    422 
    423 	if (us > ath_hal_mac_usec(ah, 0x7ff)) {
    424 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad SIFS time %u\n",
    425 		    __func__, us);
    426 		ahp->ah_sifstime = (u_int) -1;	/* restore default handling */
    427 		return AH_FALSE;
    428 	} else {
    429 		/* convert to system clocks */
    430 		OS_REG_RMW_FIELD(ah, AR_IFS0, AR_IFS0_SIFS,
    431 		    ath_hal_mac_clks(ah, us));
    432 		ahp->ah_sifstime = us;
    433 		return AH_TRUE;
    434 	}
    435 }
    436 
    437 u_int
    438 ar5210GetSifsTime(struct ath_hal *ah)
    439 {
    440 	u_int clks = OS_REG_READ(ah, AR_IFS0) & 0x7ff;
    441 	return ath_hal_mac_usec(ah, clks);	/* convert from system clocks */
    442 }
    443 
    444 HAL_BOOL
    445 ar5210SetSlotTime(struct ath_hal *ah, u_int us)
    446 {
    447 	struct ath_hal_5210 *ahp = AH5210(ah);
    448 
    449 	if (us < HAL_SLOT_TIME_9 || us > ath_hal_mac_usec(ah, 0xffff)) {
    450 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad slot time %u\n",
    451 		    __func__, us);
    452 		ahp->ah_slottime = (u_int) -1;	/* restore default handling */
    453 		return AH_FALSE;
    454 	} else {
    455 		/* convert to system clocks */
    456 		OS_REG_WRITE(ah, AR_SLOT_TIME, ath_hal_mac_clks(ah, us));
    457 		ahp->ah_slottime = us;
    458 		return AH_TRUE;
    459 	}
    460 }
    461 
    462 u_int
    463 ar5210GetSlotTime(struct ath_hal *ah)
    464 {
    465 	u_int clks = OS_REG_READ(ah, AR_SLOT_TIME) & 0xffff;
    466 	return ath_hal_mac_usec(ah, clks);	/* convert from system clocks */
    467 }
    468 
    469 HAL_BOOL
    470 ar5210SetAckTimeout(struct ath_hal *ah, u_int us)
    471 {
    472 	struct ath_hal_5210 *ahp = AH5210(ah);
    473 
    474 	if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) {
    475 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad ack timeout %u\n",
    476 		    __func__, us);
    477 		ahp->ah_acktimeout = (u_int) -1; /* restore default handling */
    478 		return AH_FALSE;
    479 	} else {
    480 		/* convert to system clocks */
    481 		OS_REG_RMW_FIELD(ah, AR_TIME_OUT,
    482 			AR_TIME_OUT_ACK, ath_hal_mac_clks(ah, us));
    483 		ahp->ah_acktimeout = us;
    484 		return AH_TRUE;
    485 	}
    486 }
    487 
    488 u_int
    489 ar5210GetAckTimeout(struct ath_hal *ah)
    490 {
    491 	u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_ACK);
    492 	return ath_hal_mac_usec(ah, clks);	/* convert from system clocks */
    493 }
    494 
    495 u_int
    496 ar5210GetAckCTSRate(struct ath_hal *ah)
    497 {
    498 	return ((AH5210(ah)->ah_staId1Defaults & AR_STA_ID1_ACKCTS_6MB) == 0);
    499 }
    500 
    501 HAL_BOOL
    502 ar5210SetAckCTSRate(struct ath_hal *ah, u_int high)
    503 {
    504 	struct ath_hal_5210 *ahp = AH5210(ah);
    505 
    506 	if (high) {
    507 		OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB);
    508 		ahp->ah_staId1Defaults &= ~AR_STA_ID1_ACKCTS_6MB;
    509 	} else {
    510 		OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB);
    511 		ahp->ah_staId1Defaults |= AR_STA_ID1_ACKCTS_6MB;
    512 	}
    513 	return AH_TRUE;
    514 }
    515 
    516 HAL_BOOL
    517 ar5210SetCTSTimeout(struct ath_hal *ah, u_int us)
    518 {
    519 	struct ath_hal_5210 *ahp = AH5210(ah);
    520 
    521 	if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) {
    522 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad cts timeout %u\n",
    523 		    __func__, us);
    524 		ahp->ah_ctstimeout = (u_int) -1; /* restore default handling */
    525 		return AH_FALSE;
    526 	} else {
    527 		/* convert to system clocks */
    528 		OS_REG_RMW_FIELD(ah, AR_TIME_OUT,
    529 			AR_TIME_OUT_CTS, ath_hal_mac_clks(ah, us));
    530 		ahp->ah_ctstimeout = us;
    531 		return AH_TRUE;
    532 	}
    533 }
    534 
    535 u_int
    536 ar5210GetCTSTimeout(struct ath_hal *ah)
    537 {
    538 	u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_CTS);
    539 	return ath_hal_mac_usec(ah, clks);	/* convert from system clocks */
    540 }
    541 
    542 HAL_BOOL
    543 ar5210SetDecompMask(struct ath_hal *ah, uint16_t keyidx, int en)
    544 {
    545 	/* nothing to do */
    546         return AH_TRUE;
    547 }
    548 
    549 void
    550 ar5210SetCoverageClass(struct ath_hal *ah, uint8_t coverageclass, int now)
    551 {
    552 }
    553 
    554 /*
    555  * Control Adaptive Noise Immunity Parameters
    556  */
    557 HAL_BOOL
    558 ar5210AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param)
    559 {
    560 	return AH_FALSE;
    561 }
    562 
    563 void
    564 ar5210AniPoll(struct ath_hal *ah, const HAL_NODE_STATS *stats, HAL_CHANNEL *chan)
    565 {
    566 }
    567 
    568 void
    569 ar5210MibEvent(struct ath_hal *ah, const HAL_NODE_STATS *stats)
    570 {
    571 }
    572 
    573 #define	AR_DIAG_SW_DIS_CRYPTO	(AR_DIAG_SW_DIS_ENC | AR_DIAG_SW_DIS_DEC)
    574 
    575 HAL_STATUS
    576 ar5210GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
    577 	uint32_t capability, uint32_t *result)
    578 {
    579 
    580 	switch (type) {
    581 	case HAL_CAP_CIPHER:		/* cipher handled in hardware */
    582 		return (capability == HAL_CIPHER_WEP ? HAL_OK : HAL_ENOTSUPP);
    583 	default:
    584 		return ath_hal_getcapability(ah, type, capability, result);
    585 	}
    586 }
    587 
    588 HAL_BOOL
    589 ar5210SetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
    590 	uint32_t capability, uint32_t setting, HAL_STATUS *status)
    591 {
    592 
    593 	switch (type) {
    594 	case HAL_CAP_DIAG:		/* hardware diagnostic support */
    595 		/*
    596 		 * NB: could split this up into virtual capabilities,
    597 		 *     (e.g. 1 => ACK, 2 => CTS, etc.) but it hardly
    598 		 *     seems worth the additional complexity.
    599 		 */
    600 #ifdef AH_DEBUG
    601 		AH_PRIVATE(ah)->ah_diagreg = setting;
    602 #else
    603 		AH_PRIVATE(ah)->ah_diagreg = setting & 0x6;	/* ACK+CTS */
    604 #endif
    605 		OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg);
    606 		return AH_TRUE;
    607 	case HAL_CAP_RXORN_FATAL:	/* HAL_INT_RXORN treated as fatal  */
    608 		return AH_FALSE;	/* NB: disallow */
    609 	default:
    610 		return ath_hal_setcapability(ah, type, capability,
    611 			setting, status);
    612 	}
    613 }
    614 
    615 HAL_BOOL
    616 ar5210GetDiagState(struct ath_hal *ah, int request,
    617 	const void *args, uint32_t argsize,
    618 	void **result, uint32_t *resultsize)
    619 {
    620 #ifdef AH_PRIVATE_DIAG
    621 	uint32_t pcicfg;
    622 	HAL_BOOL ok;
    623 
    624 	switch (request) {
    625 	case HAL_DIAG_EEPROM:
    626 		/* XXX */
    627 		break;
    628 	case HAL_DIAG_EEREAD:
    629 		if (argsize != sizeof(uint16_t))
    630 			return AH_FALSE;
    631 		pcicfg = OS_REG_READ(ah, AR_PCICFG);
    632 		OS_REG_WRITE(ah, AR_PCICFG, pcicfg | AR_PCICFG_EEPROMSEL);
    633 		ok = ath_hal_eepromRead(ah, *(const uint16_t *)args, *result);
    634 		OS_REG_WRITE(ah, AR_PCICFG, pcicfg);
    635 		if (ok)
    636 			*resultsize = sizeof(uint16_t);
    637 		return ok;
    638 	}
    639 #endif
    640 	return ath_hal_getdiagstate(ah, request,
    641 		args, argsize, result, resultsize);
    642 }
    643