xref: /freebsd/sys/dev/ath/ath_hal/ar5210/ar5210_misc.c (revision cd0d51baaa4509a1db83251a601d34404d20c990)
1 /*-
2  * SPDX-License-Identifier: ISC
3  *
4  * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
5  * Copyright (c) 2002-2004 Atheros Communications, Inc.
6  *
7  * Permission to use, copy, modify, and/or distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  *
19  * $FreeBSD$
20  */
21 #include "opt_ah.h"
22 
23 #include "ah.h"
24 #include "ah_internal.h"
25 
26 #include "ar5210/ar5210.h"
27 #include "ar5210/ar5210reg.h"
28 #include "ar5210/ar5210phy.h"
29 
30 #include "ah_eeprom_v1.h"
31 
32 #define	AR_NUM_GPIO	6		/* 6 GPIO bits */
33 #define	AR_GPIOD_MASK	0x2f		/* 6-bit mask */
34 
35 void
36 ar5210GetMacAddress(struct ath_hal *ah, uint8_t *mac)
37 {
38 	struct ath_hal_5210 *ahp = AH5210(ah);
39 
40 	OS_MEMCPY(mac, ahp->ah_macaddr, IEEE80211_ADDR_LEN);
41 }
42 
43 HAL_BOOL
44 ar5210SetMacAddress(struct ath_hal *ah, const uint8_t *mac)
45 {
46 	struct ath_hal_5210 *ahp = AH5210(ah);
47 
48 	OS_MEMCPY(ahp->ah_macaddr, mac, IEEE80211_ADDR_LEN);
49 	return AH_TRUE;
50 }
51 
52 void
53 ar5210GetBssIdMask(struct ath_hal *ah, uint8_t *mask)
54 {
55 	static const uint8_t ones[IEEE80211_ADDR_LEN] =
56 		{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
57 	OS_MEMCPY(mask, ones, IEEE80211_ADDR_LEN);
58 }
59 
60 HAL_BOOL
61 ar5210SetBssIdMask(struct ath_hal *ah, const uint8_t *mask)
62 {
63 	return AH_FALSE;
64 }
65 
66 /*
67  * Read 16 bits of data from the specified EEPROM offset.
68  */
69 HAL_BOOL
70 ar5210EepromRead(struct ath_hal *ah, u_int off, uint16_t *data)
71 {
72 	(void) OS_REG_READ(ah, AR_EP_AIR(off));	/* activate read op */
73 	if (!ath_hal_wait(ah, AR_EP_STA,
74 	    AR_EP_STA_RDCMPLT | AR_EP_STA_RDERR, AR_EP_STA_RDCMPLT)) {
75 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: read failed for entry 0x%x\n",
76 		    __func__, AR_EP_AIR(off));
77 		return AH_FALSE;
78 	}
79 	*data = OS_REG_READ(ah, AR_EP_RDATA) & 0xffff;
80 	return AH_TRUE;
81 }
82 
83 #ifdef AH_SUPPORT_WRITE_EEPROM
84 /*
85  * Write 16 bits of data to the specified EEPROM offset.
86  */
87 HAL_BOOL
88 ar5210EepromWrite(struct ath_hal *ah, u_int off, uint16_t data)
89 {
90 	return AH_FALSE;
91 }
92 #endif /* AH_SUPPORT_WRITE_EEPROM */
93 
94 /*
95  * Attempt to change the cards operating regulatory domain to the given value
96  */
97 HAL_BOOL
98 ar5210SetRegulatoryDomain(struct ath_hal *ah,
99 	uint16_t regDomain, HAL_STATUS *status)
100 {
101 	HAL_STATUS ecode;
102 
103 	if (AH_PRIVATE(ah)->ah_currentRD == regDomain) {
104 		ecode = HAL_EINVAL;
105 		goto bad;
106 	}
107 	/*
108 	 * Check if EEPROM is configured to allow this; must
109 	 * be a proper version and the protection bits must
110 	 * permit re-writing that segment of the EEPROM.
111 	 */
112 	if (ath_hal_eepromGetFlag(ah, AR_EEP_WRITEPROTECT)) {
113 		ecode = HAL_EEWRITE;
114 		goto bad;
115 	}
116 	ecode = HAL_EIO;		/* disallow all writes */
117 bad:
118 	if (status)
119 		*status = ecode;
120 	return AH_FALSE;
121 }
122 
123 /*
124  * Return the wireless modes (a,b,g,t) supported by hardware.
125  *
126  * This value is what is actually supported by the hardware
127  * and is unaffected by regulatory/country code settings.
128  *
129  */
130 u_int
131 ar5210GetWirelessModes(struct ath_hal *ah)
132 {
133 	/* XXX could enable turbo mode but can't do all rates */
134 	return HAL_MODE_11A;
135 }
136 
137 /*
138  * Called if RfKill is supported (according to EEPROM).  Set the interrupt and
139  * GPIO values so the ISR and can disable RF on a switch signal
140  */
141 void
142 ar5210EnableRfKill(struct ath_hal *ah)
143 {
144 	uint16_t rfsilent = AH_PRIVATE(ah)->ah_rfsilent;
145 	int select = MS(rfsilent, AR_EEPROM_RFSILENT_GPIO_SEL);
146 	int polarity = MS(rfsilent, AR_EEPROM_RFSILENT_POLARITY);
147 
148 	/*
149 	 * If radio disable switch connection to GPIO bit 0 is enabled
150 	 * program GPIO interrupt.
151 	 * If rfkill bit on eeprom is 1, setupeeprommap routine has already
152 	 * verified that it is a later version of eeprom, it has a place for
153 	 * rfkill bit and it is set to 1, indicating that GPIO bit 0 hardware
154 	 * connection is present.
155 	 */
156 	ar5210Gpio0SetIntr(ah, select, (ar5210GpioGet(ah, select) == polarity));
157 }
158 
159 /*
160  * Configure GPIO Output lines
161  */
162 HAL_BOOL
163 ar5210GpioCfgOutput(struct ath_hal *ah, uint32_t gpio, HAL_GPIO_MUX_TYPE type)
164 {
165 	HALASSERT(gpio < AR_NUM_GPIO);
166 
167 	OS_REG_WRITE(ah, AR_GPIOCR,
168 		  (OS_REG_READ(ah, AR_GPIOCR) &~ AR_GPIOCR_ALL(gpio))
169 		| AR_GPIOCR_OUT1(gpio));
170 
171 	return AH_TRUE;
172 }
173 
174 /*
175  * Configure GPIO Input lines
176  */
177 HAL_BOOL
178 ar5210GpioCfgInput(struct ath_hal *ah, uint32_t gpio)
179 {
180 	HALASSERT(gpio < AR_NUM_GPIO);
181 
182 	OS_REG_WRITE(ah, AR_GPIOCR,
183 		  (OS_REG_READ(ah, AR_GPIOCR) &~ AR_GPIOCR_ALL(gpio))
184 		| AR_GPIOCR_IN(gpio));
185 
186 	return AH_TRUE;
187 }
188 
189 /*
190  * Once configured for I/O - set output lines
191  */
192 HAL_BOOL
193 ar5210GpioSet(struct ath_hal *ah, uint32_t gpio, uint32_t val)
194 {
195 	uint32_t reg;
196 
197 	HALASSERT(gpio < AR_NUM_GPIO);
198 
199 	reg =  OS_REG_READ(ah, AR_GPIODO);
200 	reg &= ~(1 << gpio);
201 	reg |= (val&1) << gpio;
202 
203 	OS_REG_WRITE(ah, AR_GPIODO, reg);
204 	return AH_TRUE;
205 }
206 
207 /*
208  * Once configured for I/O - get input lines
209  */
210 uint32_t
211 ar5210GpioGet(struct ath_hal *ah, uint32_t gpio)
212 {
213 	if (gpio < AR_NUM_GPIO) {
214 		uint32_t val = OS_REG_READ(ah, AR_GPIODI);
215 		val = ((val & AR_GPIOD_MASK) >> gpio) & 0x1;
216 		return val;
217 	} else  {
218 		return 0xffffffff;
219 	}
220 }
221 
222 /*
223  * Set the GPIO 0 Interrupt
224  */
225 void
226 ar5210Gpio0SetIntr(struct ath_hal *ah, u_int gpio, uint32_t ilevel)
227 {
228 	uint32_t val = OS_REG_READ(ah, AR_GPIOCR);
229 
230 	/* Clear the bits that we will modify. */
231 	val &= ~(AR_GPIOCR_INT_SEL(gpio) | AR_GPIOCR_INT_SELH | AR_GPIOCR_INT_ENA |
232 			AR_GPIOCR_ALL(gpio));
233 
234 	val |= AR_GPIOCR_INT_SEL(gpio) | AR_GPIOCR_INT_ENA;
235 	if (ilevel)
236 		val |= AR_GPIOCR_INT_SELH;
237 
238 	/* Don't need to change anything for low level interrupt. */
239 	OS_REG_WRITE(ah, AR_GPIOCR, val);
240 
241 	/* Change the interrupt mask. */
242 	ar5210SetInterrupts(ah, AH5210(ah)->ah_maskReg | HAL_INT_GPIO);
243 }
244 
245 /*
246  * Change the LED blinking pattern to correspond to the connectivity
247  */
248 void
249 ar5210SetLedState(struct ath_hal *ah, HAL_LED_STATE state)
250 {
251 	uint32_t val;
252 
253 	val = OS_REG_READ(ah, AR_PCICFG);
254 	switch (state) {
255 	case HAL_LED_INIT:
256 		val &= ~(AR_PCICFG_LED_PEND | AR_PCICFG_LED_ACT);
257 		break;
258 	case HAL_LED_RUN:
259 		/* normal blink when connected */
260 		val &= ~AR_PCICFG_LED_PEND;
261 		val |= AR_PCICFG_LED_ACT;
262 		break;
263 	default:
264 		val |= AR_PCICFG_LED_PEND;
265 		val &= ~AR_PCICFG_LED_ACT;
266 		break;
267 	}
268 	OS_REG_WRITE(ah, AR_PCICFG, val);
269 }
270 
271 /*
272  * Return 1 or 2 for the corresponding antenna that is in use
273  */
274 u_int
275 ar5210GetDefAntenna(struct ath_hal *ah)
276 {
277 	uint32_t val = OS_REG_READ(ah, AR_STA_ID1);
278 	return (val & AR_STA_ID1_DEFAULT_ANTENNA ?  2 : 1);
279 }
280 
281 void
282 ar5210SetDefAntenna(struct ath_hal *ah, u_int antenna)
283 {
284 	uint32_t val = OS_REG_READ(ah, AR_STA_ID1);
285 
286 	if (antenna != (val & AR_STA_ID1_DEFAULT_ANTENNA ?  2 : 1)) {
287 		/*
288 		 * Antenna change requested, force a toggle of the default.
289 		 */
290 		OS_REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_DEFAULT_ANTENNA);
291 	}
292 }
293 
294 HAL_ANT_SETTING
295 ar5210GetAntennaSwitch(struct ath_hal *ah)
296 {
297 	return HAL_ANT_VARIABLE;
298 }
299 
300 HAL_BOOL
301 ar5210SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings)
302 {
303 	/* XXX not sure how to fix antenna */
304 	return (settings == HAL_ANT_VARIABLE);
305 }
306 
307 /*
308  * Change association related fields programmed into the hardware.
309  * Writing a valid BSSID to the hardware effectively enables the hardware
310  * to synchronize its TSF to the correct beacons and receive frames coming
311  * from that BSSID. It is called by the SME JOIN operation.
312  */
313 void
314 ar5210WriteAssocid(struct ath_hal *ah, const uint8_t *bssid, uint16_t assocId)
315 {
316 	struct ath_hal_5210 *ahp = AH5210(ah);
317 
318 	/* XXX save bssid for possible re-use on reset */
319 	OS_MEMCPY(ahp->ah_bssid, bssid, IEEE80211_ADDR_LEN);
320 	ahp->ah_associd = assocId;
321 	OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid));
322 	OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid+4) |
323 				     ((assocId & 0x3fff)<<AR_BSS_ID1_AID_S));
324 	if (assocId == 0)
325 		OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_NO_PSPOLL);
326 	else
327 		OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_NO_PSPOLL);
328 }
329 
330 /*
331  * Get the current hardware tsf for stamlme.
332  */
333 uint64_t
334 ar5210GetTsf64(struct ath_hal *ah)
335 {
336 	uint32_t low1, low2, u32;
337 
338 	/* sync multi-word read */
339 	low1 = OS_REG_READ(ah, AR_TSF_L32);
340 	u32 = OS_REG_READ(ah, AR_TSF_U32);
341 	low2 = OS_REG_READ(ah, AR_TSF_L32);
342 	if (low2 < low1) {	/* roll over */
343 		/*
344 		 * If we are not preempted this will work.  If we are
345 		 * then we re-reading AR_TSF_U32 does no good as the
346 		 * low bits will be meaningless.  Likewise reading
347 		 * L32, U32, U32, then comparing the last two reads
348 		 * to check for rollover doesn't help if preempted--so
349 		 * we take this approach as it costs one less PCI
350 		 * read which can be noticeable when doing things
351 		 * like timestamping packets in monitor mode.
352 		 */
353 		u32++;
354 	}
355 	return (((uint64_t) u32) << 32) | ((uint64_t) low2);
356 }
357 
358 /*
359  * Get the current hardware tsf for stamlme.
360  */
361 uint32_t
362 ar5210GetTsf32(struct ath_hal *ah)
363 {
364 	return OS_REG_READ(ah, AR_TSF_L32);
365 }
366 
367 /*
368  * Reset the current hardware tsf for stamlme
369  */
370 void
371 ar5210ResetTsf(struct ath_hal *ah)
372 {
373 	uint32_t val = OS_REG_READ(ah, AR_BEACON);
374 
375 	OS_REG_WRITE(ah, AR_BEACON, val | AR_BEACON_RESET_TSF);
376 }
377 
378 /*
379  * Grab a semi-random value from hardware registers - may not
380  * change often
381  */
382 uint32_t
383 ar5210GetRandomSeed(struct ath_hal *ah)
384 {
385 	uint32_t nf;
386 
387 	nf = (OS_REG_READ(ah, AR_PHY_BASE + (25 << 2)) >> 19) & 0x1ff;
388 	if (nf & 0x100)
389 		nf = 0 - ((nf ^ 0x1ff) + 1);
390 	return (OS_REG_READ(ah, AR_TSF_U32) ^
391 		OS_REG_READ(ah, AR_TSF_L32) ^ nf);
392 }
393 
394 /*
395  * Detect if our card is present
396  */
397 HAL_BOOL
398 ar5210DetectCardPresent(struct ath_hal *ah)
399 {
400 	/*
401 	 * Read the Silicon Revision register and compare that
402 	 * to what we read at attach time.  If the same, we say
403 	 * a card/device is present.
404 	 */
405 	return (AH_PRIVATE(ah)->ah_macRev == (OS_REG_READ(ah, AR_SREV) & 0xff));
406 }
407 
408 /*
409  * Update MIB Counters
410  */
411 void
412 ar5210UpdateMibCounters(struct ath_hal *ah, HAL_MIB_STATS *stats)
413 {
414 	stats->ackrcv_bad += OS_REG_READ(ah, AR_ACK_FAIL);
415 	stats->rts_bad	  += OS_REG_READ(ah, AR_RTS_FAIL);
416 	stats->fcs_bad	  += OS_REG_READ(ah, AR_FCS_FAIL);
417 	stats->rts_good	  += OS_REG_READ(ah, AR_RTS_OK);
418 	stats->beacons	  += OS_REG_READ(ah, AR_BEACON_CNT);
419 }
420 
421 HAL_BOOL
422 ar5210SetSifsTime(struct ath_hal *ah, u_int us)
423 {
424 	struct ath_hal_5210 *ahp = AH5210(ah);
425 
426 	if (us > ath_hal_mac_usec(ah, 0x7ff)) {
427 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad SIFS time %u\n",
428 		    __func__, us);
429 		ahp->ah_sifstime = (u_int) -1;	/* restore default handling */
430 		return AH_FALSE;
431 	} else {
432 		/* convert to system clocks */
433 		OS_REG_RMW_FIELD(ah, AR_IFS0, AR_IFS0_SIFS,
434 		    ath_hal_mac_clks(ah, us));
435 		ahp->ah_sifstime = us;
436 		return AH_TRUE;
437 	}
438 }
439 
440 u_int
441 ar5210GetSifsTime(struct ath_hal *ah)
442 {
443 	u_int clks = OS_REG_READ(ah, AR_IFS0) & 0x7ff;
444 	return ath_hal_mac_usec(ah, clks);	/* convert from system clocks */
445 }
446 
447 HAL_BOOL
448 ar5210SetSlotTime(struct ath_hal *ah, u_int us)
449 {
450 	struct ath_hal_5210 *ahp = AH5210(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 = (u_int) -1;	/* restore default handling */
456 		return AH_FALSE;
457 	} else {
458 		/* convert to system clocks */
459 		OS_REG_WRITE(ah, AR_SLOT_TIME, ath_hal_mac_clks(ah, us));
460 		ahp->ah_slottime = us;
461 		return AH_TRUE;
462 	}
463 }
464 
465 u_int
466 ar5210GetSlotTime(struct ath_hal *ah)
467 {
468 	u_int clks = OS_REG_READ(ah, AR_SLOT_TIME) & 0xffff;
469 	return ath_hal_mac_usec(ah, clks);	/* convert from system clocks */
470 }
471 
472 HAL_BOOL
473 ar5210SetAckTimeout(struct ath_hal *ah, u_int us)
474 {
475 	struct ath_hal_5210 *ahp = AH5210(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 ar5210GetAckTimeout(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 ar5210GetAckCTSRate(struct ath_hal *ah)
500 {
501 	return ((AH5210(ah)->ah_staId1Defaults & AR_STA_ID1_ACKCTS_6MB) == 0);
502 }
503 
504 HAL_BOOL
505 ar5210SetAckCTSRate(struct ath_hal *ah, u_int high)
506 {
507 	struct ath_hal_5210 *ahp = AH5210(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 ar5210SetCTSTimeout(struct ath_hal *ah, u_int us)
521 {
522 	struct ath_hal_5210 *ahp = AH5210(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 ar5210GetCTSTimeout(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 ar5210SetDecompMask(struct ath_hal *ah, uint16_t keyidx, int en)
547 {
548 	/* nothing to do */
549         return AH_TRUE;
550 }
551 
552 void
553 ar5210SetCoverageClass(struct ath_hal *ah, uint8_t coverageclass, int now)
554 {
555 }
556 
557 HAL_STATUS
558 ar5210SetQuiet(struct ath_hal *ah, uint32_t period, uint32_t duration,
559     uint32_t next_start, HAL_QUIET_FLAG flags)
560 {
561 	return HAL_OK;
562 }
563 
564 /*
565  * Control Adaptive Noise Immunity Parameters
566  */
567 HAL_BOOL
568 ar5210AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param)
569 {
570 	return AH_FALSE;
571 }
572 
573 void
574 ar5210RxMonitor(struct ath_hal *ah, const HAL_NODE_STATS *stats,
575 	const struct ieee80211_channel *chan)
576 {
577 }
578 
579 void
580 ar5210AniPoll(struct ath_hal *ah, const struct ieee80211_channel *chan)
581 {
582 }
583 
584 void
585 ar5210MibEvent(struct ath_hal *ah, const HAL_NODE_STATS *stats)
586 {
587 }
588 
589 HAL_STATUS
590 ar5210GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
591 	uint32_t capability, uint32_t *result)
592 {
593 
594 	switch (type) {
595 	case HAL_CAP_CIPHER:		/* cipher handled in hardware */
596 #if 0
597 		return (capability == HAL_CIPHER_WEP ? HAL_OK : HAL_ENOTSUPP);
598 #else
599 		return HAL_ENOTSUPP;
600 #endif
601 	default:
602 		return ath_hal_getcapability(ah, type, capability, result);
603 	}
604 }
605 
606 HAL_BOOL
607 ar5210SetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
608 	uint32_t capability, uint32_t setting, HAL_STATUS *status)
609 {
610 
611 	switch (type) {
612 	case HAL_CAP_DIAG:		/* hardware diagnostic support */
613 		/*
614 		 * NB: could split this up into virtual capabilities,
615 		 *     (e.g. 1 => ACK, 2 => CTS, etc.) but it hardly
616 		 *     seems worth the additional complexity.
617 		 */
618 #ifdef AH_DEBUG
619 		AH_PRIVATE(ah)->ah_diagreg = setting;
620 #else
621 		AH_PRIVATE(ah)->ah_diagreg = setting & 0x6;	/* ACK+CTS */
622 #endif
623 		ar5210UpdateDiagReg(ah, AH_PRIVATE(ah)->ah_diagreg);
624 		return AH_TRUE;
625 	case HAL_CAP_RXORN_FATAL:	/* HAL_INT_RXORN treated as fatal  */
626 		return AH_FALSE;	/* NB: disallow */
627 	default:
628 		return ath_hal_setcapability(ah, type, capability,
629 			setting, status);
630 	}
631 }
632 
633 HAL_BOOL
634 ar5210GetDiagState(struct ath_hal *ah, int request,
635 	const void *args, uint32_t argsize,
636 	void **result, uint32_t *resultsize)
637 {
638 #ifdef AH_PRIVATE_DIAG
639 	uint32_t pcicfg;
640 	HAL_BOOL ok;
641 
642 	switch (request) {
643 	case HAL_DIAG_EEPROM:
644 		/* XXX */
645 		break;
646 	case HAL_DIAG_EEREAD:
647 		if (argsize != sizeof(uint16_t))
648 			return AH_FALSE;
649 		pcicfg = OS_REG_READ(ah, AR_PCICFG);
650 		OS_REG_WRITE(ah, AR_PCICFG, pcicfg | AR_PCICFG_EEPROMSEL);
651 		ok = ath_hal_eepromRead(ah, *(const uint16_t *)args, *result);
652 		OS_REG_WRITE(ah, AR_PCICFG, pcicfg);
653 		if (ok)
654 			*resultsize = sizeof(uint16_t);
655 		return ok;
656 	}
657 #endif
658 	return ath_hal_getdiagstate(ah, request,
659 		args, argsize, result, resultsize);
660 }
661 
662 /*
663  * Return what percentage of the extension channel is busy.
664  * This is always disabled for AR5210 series NICs.
665  */
666 uint32_t
667 ar5210Get11nExtBusy(struct ath_hal *ah)
668 {
669 
670 	return (0);
671 }
672 
673 /*
674  * There's no channel survey support for the AR5210.
675  */
676 HAL_BOOL
677 ar5210GetMibCycleCounts(struct ath_hal *ah, HAL_SURVEY_SAMPLE *hsample)
678 {
679 
680 	return (AH_FALSE);
681 }
682 
683 void
684 ar5210SetChainMasks(struct ath_hal *ah, uint32_t txchainmask,
685     uint32_t rxchainmask)
686 {
687 }
688 
689 void
690 ar5210EnableDfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe)
691 {
692 }
693 
694 void
695 ar5210GetDfsThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe)
696 {
697 }
698 
699 /*
700  * Update the diagnostic register.
701  *
702  * This merges in the diagnostic register setting with the default
703  * value, which may or may not involve disabling hardware encryption.
704  */
705 void
706 ar5210UpdateDiagReg(struct ath_hal *ah, uint32_t val)
707 {
708 
709 	/* Disable all hardware encryption */
710 	val |= AR_DIAG_SW_DIS_CRYPTO;
711 	OS_REG_WRITE(ah, AR_DIAG_SW, val);
712 }
713