ar5210_misc.c revision 217684
1132718Skan/*
2132718Skan * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
3132718Skan * Copyright (c) 2002-2004 Atheros Communications, Inc.
4169689Skan *
5132718Skan * Permission to use, copy, modify, and/or distribute this software for any
6132718Skan * purpose with or without fee is hereby granted, provided that the above
7132718Skan * copyright notice and this permission notice appear in all copies.
8132718Skan *
9132718Skan * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10132718Skan * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11132718Skan * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12132718Skan * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13132718Skan * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14132718Skan * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15132718Skan * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16132718Skan *
17132718Skan * $FreeBSD: head/sys/dev/ath/ath_hal/ar5210/ar5210_misc.c 217684 2011-01-21 05:21:00Z adrian $
18132718Skan */
19132718Skan#include "opt_ah.h"
20132718Skan
21169689Skan#include "ah.h"
22169689Skan#include "ah_internal.h"
23132718Skan
24132718Skan#include "ar5210/ar5210.h"
25132718Skan#include "ar5210/ar5210reg.h"
26132718Skan#include "ar5210/ar5210phy.h"
27132718Skan
28169689Skan#include "ah_eeprom_v1.h"
29132718Skan
30132718Skan#define	AR_NUM_GPIO	6		/* 6 GPIO bits */
31132718Skan#define	AR_GPIOD_MASK	0x2f		/* 6-bit mask */
32132718Skan
33169689Skanvoid
34169689Skanar5210GetMacAddress(struct ath_hal *ah, uint8_t *mac)
35132718Skan{
36132718Skan	struct ath_hal_5210 *ahp = AH5210(ah);
37132718Skan
38132718Skan	OS_MEMCPY(mac, ahp->ah_macaddr, IEEE80211_ADDR_LEN);
39132718Skan}
40132718Skan
41169689SkanHAL_BOOL
42132718Skanar5210SetMacAddress(struct ath_hal *ah, const uint8_t *mac)
43132718Skan{
44132718Skan	struct ath_hal_5210 *ahp = AH5210(ah);
45132718Skan
46132718Skan	OS_MEMCPY(ahp->ah_macaddr, mac, IEEE80211_ADDR_LEN);
47132718Skan	return AH_TRUE;
48132718Skan}
49132718Skan
50132718Skanvoid
51132718Skanar5210GetBssIdMask(struct ath_hal *ah, uint8_t *mask)
52132718Skan{
53132718Skan	static const uint8_t ones[IEEE80211_ADDR_LEN] =
54132718Skan		{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
55132718Skan	OS_MEMCPY(mask, ones, IEEE80211_ADDR_LEN);
56132718Skan}
57132718Skan
58132718SkanHAL_BOOL
59132718Skanar5210SetBssIdMask(struct ath_hal *ah, const uint8_t *mask)
60132718Skan{
61132718Skan	return AH_FALSE;
62132718Skan}
63132718Skan
64132718Skan/*
65132718Skan * Read 16 bits of data from the specified EEPROM offset.
66132718Skan */
67132718SkanHAL_BOOL
68132718Skanar5210EepromRead(struct ath_hal *ah, u_int off, uint16_t *data)
69132718Skan{
70132718Skan	(void) OS_REG_READ(ah, AR_EP_AIR(off));	/* activate read op */
71132718Skan	if (!ath_hal_wait(ah, AR_EP_STA,
72132718Skan	    AR_EP_STA_RDCMPLT | AR_EP_STA_RDERR, AR_EP_STA_RDCMPLT)) {
73132718Skan		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: read failed for entry 0x%x\n",
74132718Skan		    __func__, AR_EP_AIR(off));
75132718Skan		return AH_FALSE;
76132718Skan	}
77132718Skan	*data = OS_REG_READ(ah, AR_EP_RDATA) & 0xffff;
78132718Skan	return AH_TRUE;
79132718Skan}
80132718Skan
81132718Skan#ifdef AH_SUPPORT_WRITE_EEPROM
82132718Skan/*
83132718Skan * Write 16 bits of data to the specified EEPROM offset.
84132718Skan */
85132718SkanHAL_BOOL
86132718Skanar5210EepromWrite(struct ath_hal *ah, u_int off, uint16_t data)
87132718Skan{
88132718Skan	return AH_FALSE;
89132718Skan}
90132718Skan#endif /* AH_SUPPORT_WRITE_EEPROM */
91132718Skan
92132718Skan/*
93132718Skan * Attempt to change the cards operating regulatory domain to the given value
94132718Skan */
95132718SkanHAL_BOOL
96132718Skanar5210SetRegulatoryDomain(struct ath_hal *ah,
97132718Skan	uint16_t regDomain, HAL_STATUS *status)
98132718Skan{
99132718Skan	HAL_STATUS ecode;
100132718Skan
101132718Skan	if (AH_PRIVATE(ah)->ah_currentRD == regDomain) {
102132718Skan		ecode = HAL_EINVAL;
103132718Skan		goto bad;
104132718Skan	}
105132718Skan	/*
106132718Skan	 * Check if EEPROM is configured to allow this; must
107132718Skan	 * be a proper version and the protection bits must
108132718Skan	 * permit re-writing that segment of the EEPROM.
109132718Skan	 */
110132718Skan	if (ath_hal_eepromGetFlag(ah, AR_EEP_WRITEPROTECT)) {
111132718Skan		ecode = HAL_EEWRITE;
112132718Skan		goto bad;
113132718Skan	}
114132718Skan	ecode = HAL_EIO;		/* disallow all writes */
115132718Skanbad:
116132718Skan	if (status)
117132718Skan		*status = ecode;
118132718Skan	return AH_FALSE;
119132718Skan}
120132718Skan
121132718Skan/*
122132718Skan * Return the wireless modes (a,b,g,t) supported by hardware.
123132718Skan *
124132718Skan * This value is what is actually supported by the hardware
125132718Skan * and is unaffected by regulatory/country code settings.
126132718Skan *
127132718Skan */
128132718Skanu_int
129132718Skanar5210GetWirelessModes(struct ath_hal *ah)
130132718Skan{
131132718Skan	/* XXX could enable turbo mode but can't do all rates */
132132718Skan	return HAL_MODE_11A;
133132718Skan}
134132718Skan
135169689Skan/*
136132718Skan * Called if RfKill is supported (according to EEPROM).  Set the interrupt and
137132718Skan * GPIO values so the ISR and can disable RF on a switch signal
138132718Skan */
139132718Skanvoid
140169689Skanar5210EnableRfKill(struct ath_hal *ah)
141169689Skan{
142169689Skan	uint16_t rfsilent = AH_PRIVATE(ah)->ah_rfsilent;
143169689Skan	int select = MS(rfsilent, AR_EEPROM_RFSILENT_GPIO_SEL);
144132718Skan	int polarity = MS(rfsilent, AR_EEPROM_RFSILENT_POLARITY);
145169689Skan
146132718Skan	/*
147132718Skan	 * If radio disable switch connection to GPIO bit 0 is enabled
148132718Skan	 * program GPIO interrupt.
149132718Skan	 * If rfkill bit on eeprom is 1, setupeeprommap routine has already
150132718Skan	 * verified that it is a later version of eeprom, it has a place for
151132718Skan	 * rfkill bit and it is set to 1, indicating that GPIO bit 0 hardware
152132718Skan	 * connection is present.
153132718Skan	 */
154132718Skan	ar5210Gpio0SetIntr(ah, select, (ar5210GpioGet(ah, select) == polarity));
155132718Skan}
156132718Skan
157132718Skan/*
158132718Skan * Configure GPIO Output lines
159132718Skan */
160132718SkanHAL_BOOL
161132718Skanar5210GpioCfgOutput(struct ath_hal *ah, uint32_t gpio, HAL_GPIO_MUX_TYPE type)
162132718Skan{
163132718Skan	HALASSERT(gpio < AR_NUM_GPIO);
164132718Skan
165132718Skan	OS_REG_WRITE(ah, AR_GPIOCR,
166132718Skan		  (OS_REG_READ(ah, AR_GPIOCR) &~ AR_GPIOCR_ALL(gpio))
167132718Skan		| AR_GPIOCR_OUT1(gpio));
168132718Skan
169132718Skan	return AH_TRUE;
170132718Skan}
171132718Skan
172132718Skan/*
173132718Skan * Configure GPIO Input lines
174132718Skan */
175132718SkanHAL_BOOL
176132718Skanar5210GpioCfgInput(struct ath_hal *ah, uint32_t gpio)
177132718Skan{
178132718Skan	HALASSERT(gpio < AR_NUM_GPIO);
179132718Skan
180132718Skan	OS_REG_WRITE(ah, AR_GPIOCR,
181132718Skan		  (OS_REG_READ(ah, AR_GPIOCR) &~ AR_GPIOCR_ALL(gpio))
182132718Skan		| AR_GPIOCR_IN(gpio));
183132718Skan
184132718Skan	return AH_TRUE;
185132718Skan}
186132718Skan
187132718Skan/*
188132718Skan * Once configured for I/O - set output lines
189132718Skan */
190132718SkanHAL_BOOL
191132718Skanar5210GpioSet(struct ath_hal *ah, uint32_t gpio, uint32_t val)
192132718Skan{
193132718Skan	uint32_t reg;
194132718Skan
195132718Skan	HALASSERT(gpio < AR_NUM_GPIO);
196132718Skan
197132718Skan	reg =  OS_REG_READ(ah, AR_GPIODO);
198132718Skan	reg &= ~(1 << gpio);
199132718Skan	reg |= (val&1) << gpio;
200132718Skan
201169689Skan	OS_REG_WRITE(ah, AR_GPIODO, reg);
202132718Skan	return AH_TRUE;
203132718Skan}
204132718Skan
205132718Skan/*
206132718Skan * Once configured for I/O - get input lines
207132718Skan */
208132718Skanuint32_t
209132718Skanar5210GpioGet(struct ath_hal *ah, uint32_t gpio)
210132718Skan{
211132718Skan	if (gpio < AR_NUM_GPIO) {
212132718Skan		uint32_t val = OS_REG_READ(ah, AR_GPIODI);
213132718Skan		val = ((val & AR_GPIOD_MASK) >> gpio) & 0x1;
214132718Skan		return val;
215132718Skan	} else  {
216132718Skan		return 0xffffffff;
217132718Skan	}
218132718Skan}
219132718Skan
220169689Skan/*
221169689Skan * Set the GPIO 0 Interrupt
222169689Skan */
223169689Skanvoid
224169689Skanar5210Gpio0SetIntr(struct ath_hal *ah, u_int gpio, uint32_t ilevel)
225169689Skan{
226132718Skan	uint32_t val = OS_REG_READ(ah, AR_GPIOCR);
227132718Skan
228132718Skan	/* Clear the bits that we will modify. */
229132718Skan	val &= ~(AR_GPIOCR_INT_SEL(gpio) | AR_GPIOCR_INT_SELH | AR_GPIOCR_INT_ENA |
230132718Skan			AR_GPIOCR_ALL(gpio));
231132718Skan
232132718Skan	val |= AR_GPIOCR_INT_SEL(gpio) | AR_GPIOCR_INT_ENA;
233132718Skan	if (ilevel)
234132718Skan		val |= AR_GPIOCR_INT_SELH;
235132718Skan
236132718Skan	/* Don't need to change anything for low level interrupt. */
237132718Skan	OS_REG_WRITE(ah, AR_GPIOCR, val);
238132718Skan
239132718Skan	/* Change the interrupt mask. */
240132718Skan	ar5210SetInterrupts(ah, AH5210(ah)->ah_maskReg | HAL_INT_GPIO);
241169689Skan}
242132718Skan
243132718Skan/*
244132718Skan * Change the LED blinking pattern to correspond to the connectivity
245132718Skan */
246132718Skanvoid
247132718Skanar5210SetLedState(struct ath_hal *ah, HAL_LED_STATE state)
248132718Skan{
249132718Skan	uint32_t val;
250132718Skan
251132718Skan	val = OS_REG_READ(ah, AR_PCICFG);
252132718Skan	switch (state) {
253132718Skan	case HAL_LED_INIT:
254132718Skan		val &= ~(AR_PCICFG_LED_PEND | AR_PCICFG_LED_ACT);
255132718Skan		break;
256132718Skan	case HAL_LED_RUN:
257132718Skan		/* normal blink when connected */
258132718Skan		val &= ~AR_PCICFG_LED_PEND;
259132718Skan		val |= AR_PCICFG_LED_ACT;
260132718Skan		break;
261132718Skan	default:
262132718Skan		val |= AR_PCICFG_LED_PEND;
263132718Skan		val &= ~AR_PCICFG_LED_ACT;
264132718Skan		break;
265132718Skan	}
266132718Skan	OS_REG_WRITE(ah, AR_PCICFG, val);
267132718Skan}
268132718Skan
269132718Skan/*
270132718Skan * Return 1 or 2 for the corresponding antenna that is in use
271132718Skan */
272132718Skanu_int
273132718Skanar5210GetDefAntenna(struct ath_hal *ah)
274132718Skan{
275169689Skan	uint32_t val = OS_REG_READ(ah, AR_STA_ID1);
276132718Skan	return (val & AR_STA_ID1_DEFAULT_ANTENNA ?  2 : 1);
277132718Skan}
278132718Skan
279132718Skanvoid
280132718Skanar5210SetDefAntenna(struct ath_hal *ah, u_int antenna)
281132718Skan{
282132718Skan	uint32_t val = OS_REG_READ(ah, AR_STA_ID1);
283132718Skan
284132718Skan	if (antenna != (val & AR_STA_ID1_DEFAULT_ANTENNA ?  2 : 1)) {
285169689Skan		/*
286169689Skan		 * Antenna change requested, force a toggle of the default.
287169689Skan		 */
288169689Skan		OS_REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_DEFAULT_ANTENNA);
289169689Skan	}
290169689Skan}
291169689Skan
292169689SkanHAL_ANT_SETTING
293132718Skanar5210GetAntennaSwitch(struct ath_hal *ah)
294132718Skan{
295132718Skan	return HAL_ANT_VARIABLE;
296132718Skan}
297132718Skan
298132718SkanHAL_BOOL
299132718Skanar5210SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings)
300132718Skan{
301169689Skan	/* XXX not sure how to fix antenna */
302169689Skan	return (settings == HAL_ANT_VARIABLE);
303169689Skan}
304169689Skan
305169689Skan/*
306169689Skan * Change association related fields programmed into the hardware.
307132718Skan * Writing a valid BSSID to the hardware effectively enables the hardware
308132718Skan * to synchronize its TSF to the correct beacons and receive frames coming
309132718Skan * from that BSSID. It is called by the SME JOIN operation.
310132718Skan */
311132718Skanvoid
312169689Skanar5210WriteAssocid(struct ath_hal *ah, const uint8_t *bssid, uint16_t assocId)
313169689Skan{
314169689Skan	struct ath_hal_5210 *ahp = AH5210(ah);
315169689Skan
316169689Skan	/* XXX save bssid for possible re-use on reset */
317169689Skan	OS_MEMCPY(ahp->ah_bssid, bssid, IEEE80211_ADDR_LEN);
318169689Skan	OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid));
319169689Skan	OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid+4) |
320169689Skan				     ((assocId & 0x3fff)<<AR_BSS_ID1_AID_S));
321169689Skan	if (assocId == 0)
322169689Skan		OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_NO_PSPOLL);
323169689Skan	else
324169689Skan		OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_NO_PSPOLL);
325169689Skan}
326169689Skan
327169689Skan/*
328169689Skan * Get the current hardware tsf for stamlme.
329169689Skan */
330169689Skanuint64_t
331169689Skanar5210GetTsf64(struct ath_hal *ah)
332169689Skan{
333169689Skan	uint32_t low1, low2, u32;
334169689Skan
335169689Skan	/* sync multi-word read */
336169689Skan	low1 = OS_REG_READ(ah, AR_TSF_L32);
337169689Skan	u32 = OS_REG_READ(ah, AR_TSF_U32);
338169689Skan	low2 = OS_REG_READ(ah, AR_TSF_L32);
339169689Skan	if (low2 < low1) {	/* roll over */
340169689Skan		/*
341169689Skan		 * If we are not preempted this will work.  If we are
342169689Skan		 * then we re-reading AR_TSF_U32 does no good as the
343169689Skan		 * low bits will be meaningless.  Likewise reading
344169689Skan		 * L32, U32, U32, then comparing the last two reads
345169689Skan		 * to check for rollover doesn't help if preempted--so
346169689Skan		 * we take this approach as it costs one less PCI
347169689Skan		 * read which can be noticeable when doing things
348169689Skan		 * like timestamping packets in monitor mode.
349169689Skan		 */
350169689Skan		u32++;
351169689Skan	}
352132718Skan	return (((uint64_t) u32) << 32) | ((uint64_t) low2);
353169689Skan}
354169689Skan
355169689Skan/*
356169689Skan * Get the current hardware tsf for stamlme.
357132718Skan */
358169689Skanuint32_t
359169689Skanar5210GetTsf32(struct ath_hal *ah)
360169689Skan{
361169689Skan	return OS_REG_READ(ah, AR_TSF_L32);
362169689Skan}
363169689Skan
364169689Skan/*
365169689Skan * Reset the current hardware tsf for stamlme
366169689Skan */
367169689Skanvoid
368169689Skanar5210ResetTsf(struct ath_hal *ah)
369169689Skan{
370169689Skan	uint32_t val = OS_REG_READ(ah, AR_BEACON);
371169689Skan
372169689Skan	OS_REG_WRITE(ah, AR_BEACON, val | AR_BEACON_RESET_TSF);
373169689Skan}
374169689Skan
375169689Skan/*
376169689Skan * Grab a semi-random value from hardware registers - may not
377169689Skan * change often
378169689Skan */
379169689Skanuint32_t
380169689Skanar5210GetRandomSeed(struct ath_hal *ah)
381169689Skan{
382169689Skan	uint32_t nf;
383169689Skan
384169689Skan	nf = (OS_REG_READ(ah, AR_PHY_BASE + (25 << 2)) >> 19) & 0x1ff;
385169689Skan	if (nf & 0x100)
386169689Skan		nf = 0 - ((nf ^ 0x1ff) + 1);
387169689Skan	return (OS_REG_READ(ah, AR_TSF_U32) ^
388169689Skan		OS_REG_READ(ah, AR_TSF_L32) ^ nf);
389169689Skan}
390169689Skan
391169689Skan/*
392169689Skan * Detect if our card is present
393169689Skan */
394169689SkanHAL_BOOL
395169689Skanar5210DetectCardPresent(struct ath_hal *ah)
396169689Skan{
397169689Skan	/*
398132718Skan	 * Read the Silicon Revision register and compare that
399132718Skan	 * to what we read at attach time.  If the same, we say
400169689Skan	 * a card/device is present.
401169689Skan	 */
402169689Skan	return (AH_PRIVATE(ah)->ah_macRev == (OS_REG_READ(ah, AR_SREV) & 0xff));
403169689Skan}
404169689Skan
405169689Skan/*
406169689Skan * Update MIB Counters
407169689Skan */
408169689Skanvoid
409169689Skanar5210UpdateMibCounters(struct ath_hal *ah, HAL_MIB_STATS *stats)
410169689Skan{
411169689Skan	stats->ackrcv_bad += OS_REG_READ(ah, AR_ACK_FAIL);
412169689Skan	stats->rts_bad	  += OS_REG_READ(ah, AR_RTS_FAIL);
413169689Skan	stats->fcs_bad	  += OS_REG_READ(ah, AR_FCS_FAIL);
414169689Skan	stats->rts_good	  += OS_REG_READ(ah, AR_RTS_OK);
415169689Skan	stats->beacons	  += OS_REG_READ(ah, AR_BEACON_CNT);
416169689Skan}
417132718Skan
418132718SkanHAL_BOOL
419132718Skanar5210SetSifsTime(struct ath_hal *ah, u_int us)
420132718Skan{
421132718Skan	struct ath_hal_5210 *ahp = AH5210(ah);
422132718Skan
423132718Skan	if (us > ath_hal_mac_usec(ah, 0x7ff)) {
424132718Skan		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad SIFS time %u\n",
425132718Skan		    __func__, us);
426132718Skan		ahp->ah_sifstime = (u_int) -1;	/* restore default handling */
427169689Skan		return AH_FALSE;
428169689Skan	} else {
429169689Skan		/* convert to system clocks */
430169689Skan		OS_REG_RMW_FIELD(ah, AR_IFS0, AR_IFS0_SIFS,
431132718Skan		    ath_hal_mac_clks(ah, us));
432132718Skan		ahp->ah_sifstime = us;
433169689Skan		return AH_TRUE;
434169689Skan	}
435169689Skan}
436169689Skan
437169689Skanu_int
438169689Skanar5210GetSifsTime(struct ath_hal *ah)
439169689Skan{
440132718Skan	u_int clks = OS_REG_READ(ah, AR_IFS0) & 0x7ff;
441132718Skan	return ath_hal_mac_usec(ah, clks);	/* convert from system clocks */
442132718Skan}
443132718Skan
444132718SkanHAL_BOOL
445132718Skanar5210SetSlotTime(struct ath_hal *ah, u_int us)
446132718Skan{
447132718Skan	struct ath_hal_5210 *ahp = AH5210(ah);
448132718Skan
449132718Skan	if (us < HAL_SLOT_TIME_9 || us > ath_hal_mac_usec(ah, 0xffff)) {
450169689Skan		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad slot time %u\n",
451169689Skan		    __func__, us);
452169689Skan		ahp->ah_slottime = (u_int) -1;	/* restore default handling */
453169689Skan		return AH_FALSE;
454169689Skan	} else {
455169689Skan		/* convert to system clocks */
456169689Skan		OS_REG_WRITE(ah, AR_SLOT_TIME, ath_hal_mac_clks(ah, us));
457169689Skan		ahp->ah_slottime = us;
458169689Skan		return AH_TRUE;
459169689Skan	}
460169689Skan}
461169689Skan
462169689Skanu_int
463169689Skanar5210GetSlotTime(struct ath_hal *ah)
464169689Skan{
465132718Skan	u_int clks = OS_REG_READ(ah, AR_SLOT_TIME) & 0xffff;
466132718Skan	return ath_hal_mac_usec(ah, clks);	/* convert from system clocks */
467169689Skan}
468169689Skan
469169689SkanHAL_BOOL
470169689Skanar5210SetAckTimeout(struct ath_hal *ah, u_int us)
471169689Skan{
472169689Skan	struct ath_hal_5210 *ahp = AH5210(ah);
473169689Skan
474169689Skan	if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) {
475169689Skan		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad ack timeout %u\n",
476169689Skan		    __func__, us);
477169689Skan		ahp->ah_acktimeout = (u_int) -1; /* restore default handling */
478169689Skan		return AH_FALSE;
479169689Skan	} else {
480169689Skan		/* convert to system clocks */
481169689Skan		OS_REG_RMW_FIELD(ah, AR_TIME_OUT,
482169689Skan			AR_TIME_OUT_ACK, ath_hal_mac_clks(ah, us));
483169689Skan		ahp->ah_acktimeout = us;
484169689Skan		return AH_TRUE;
485169689Skan	}
486169689Skan}
487169689Skan
488169689Skanu_int
489169689Skanar5210GetAckTimeout(struct ath_hal *ah)
490169689Skan{
491169689Skan	u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_ACK);
492169689Skan	return ath_hal_mac_usec(ah, clks);	/* convert from system clocks */
493169689Skan}
494169689Skan
495169689Skanu_int
496169689Skanar5210GetAckCTSRate(struct ath_hal *ah)
497169689Skan{
498169689Skan	return ((AH5210(ah)->ah_staId1Defaults & AR_STA_ID1_ACKCTS_6MB) == 0);
499169689Skan}
500169689Skan
501169689SkanHAL_BOOL
502169689Skanar5210SetAckCTSRate(struct ath_hal *ah, u_int high)
503169689Skan{
504169689Skan	struct ath_hal_5210 *ahp = AH5210(ah);
505169689Skan
506169689Skan	if (high) {
507169689Skan		OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB);
508169689Skan		ahp->ah_staId1Defaults &= ~AR_STA_ID1_ACKCTS_6MB;
509169689Skan	} else {
510169689Skan		OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB);
511132718Skan		ahp->ah_staId1Defaults |= AR_STA_ID1_ACKCTS_6MB;
512132718Skan	}
513132718Skan	return AH_TRUE;
514132718Skan}
515132718Skan
516132718SkanHAL_BOOL
517132718Skanar5210SetCTSTimeout(struct ath_hal *ah, u_int us)
518132718Skan{
519169689Skan	struct ath_hal_5210 *ahp = AH5210(ah);
520169689Skan
521169689Skan	if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) {
522169689Skan		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad cts timeout %u\n",
523169689Skan		    __func__, us);
524169689Skan		ahp->ah_ctstimeout = (u_int) -1; /* restore default handling */
525169689Skan		return AH_FALSE;
526169689Skan	} else {
527169689Skan		/* convert to system clocks */
528132718Skan		OS_REG_RMW_FIELD(ah, AR_TIME_OUT,
529132718Skan			AR_TIME_OUT_CTS, ath_hal_mac_clks(ah, us));
530132718Skan		ahp->ah_ctstimeout = us;
531132718Skan		return AH_TRUE;
532169689Skan	}
533169689Skan}
534169689Skan
535169689Skanu_int
536132718Skanar5210GetCTSTimeout(struct ath_hal *ah)
537169689Skan{
538132718Skan	u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_CTS);
539132718Skan	return ath_hal_mac_usec(ah, clks);	/* convert from system clocks */
540132718Skan}
541132718Skan
542132718SkanHAL_BOOL
543132718Skanar5210SetDecompMask(struct ath_hal *ah, uint16_t keyidx, int en)
544132718Skan{
545132718Skan	/* nothing to do */
546132718Skan        return AH_TRUE;
547132718Skan}
548132718Skan
549132718Skanvoid
550132718Skanar5210SetCoverageClass(struct ath_hal *ah, uint8_t coverageclass, int now)
551132718Skan{
552132718Skan}
553132718Skan
554132718Skan/*
555132718Skan * Control Adaptive Noise Immunity Parameters
556132718Skan */
557132718SkanHAL_BOOL
558132718Skanar5210AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param)
559132718Skan{
560132718Skan	return AH_FALSE;
561132718Skan}
562132718Skan
563132718Skanvoid
564132718Skanar5210RxMonitor(struct ath_hal *ah, const HAL_NODE_STATS *stats,
565132718Skan	const struct ieee80211_channel *chan)
566132718Skan{
567132718Skan}
568132718Skan
569132718Skanvoid
570132718Skanar5210AniPoll(struct ath_hal *ah, const struct ieee80211_channel *chan)
571132718Skan{
572132718Skan}
573132718Skan
574169689Skanvoid
575132718Skanar5210MibEvent(struct ath_hal *ah, const HAL_NODE_STATS *stats)
576132718Skan{
577132718Skan}
578169689Skan
579169689Skan#define	AR_DIAG_SW_DIS_CRYPTO	(AR_DIAG_SW_DIS_ENC | AR_DIAG_SW_DIS_DEC)
580132718Skan
581132718SkanHAL_STATUS
582169689Skanar5210GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
583132718Skan	uint32_t capability, uint32_t *result)
584132718Skan{
585132718Skan
586132718Skan	switch (type) {
587169689Skan	case HAL_CAP_CIPHER:		/* cipher handled in hardware */
588169689Skan		return (capability == HAL_CIPHER_WEP ? HAL_OK : HAL_ENOTSUPP);
589132718Skan	default:
590132718Skan		return ath_hal_getcapability(ah, type, capability, result);
591169689Skan	}
592169689Skan}
593169689Skan
594132718SkanHAL_BOOL
595132718Skanar5210SetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
596132718Skan	uint32_t capability, uint32_t setting, HAL_STATUS *status)
597132718Skan{
598132718Skan
599132718Skan	switch (type) {
600132718Skan	case HAL_CAP_DIAG:		/* hardware diagnostic support */
601132718Skan		/*
602132718Skan		 * NB: could split this up into virtual capabilities,
603132718Skan		 *     (e.g. 1 => ACK, 2 => CTS, etc.) but it hardly
604132718Skan		 *     seems worth the additional complexity.
605132718Skan		 */
606132718Skan#ifdef AH_DEBUG
607132718Skan		AH_PRIVATE(ah)->ah_diagreg = setting;
608132718Skan#else
609132718Skan		AH_PRIVATE(ah)->ah_diagreg = setting & 0x6;	/* ACK+CTS */
610132718Skan#endif
611132718Skan		OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg);
612132718Skan		return AH_TRUE;
613132718Skan	case HAL_CAP_RXORN_FATAL:	/* HAL_INT_RXORN treated as fatal  */
614132718Skan		return AH_FALSE;	/* NB: disallow */
615132718Skan	default:
616132718Skan		return ath_hal_setcapability(ah, type, capability,
617132718Skan			setting, status);
618132718Skan	}
619132718Skan}
620169689Skan
621169689SkanHAL_BOOL
622169689Skanar5210GetDiagState(struct ath_hal *ah, int request,
623169689Skan	const void *args, uint32_t argsize,
624169689Skan	void **result, uint32_t *resultsize)
625169689Skan{
626169689Skan#ifdef AH_PRIVATE_DIAG
627169689Skan	uint32_t pcicfg;
628169689Skan	HAL_BOOL ok;
629132718Skan
630132718Skan	switch (request) {
631132718Skan	case HAL_DIAG_EEPROM:
632169689Skan		/* XXX */
633132718Skan		break;
634132718Skan	case HAL_DIAG_EEREAD:
635132718Skan		if (argsize != sizeof(uint16_t))
636132718Skan			return AH_FALSE;
637132718Skan		pcicfg = OS_REG_READ(ah, AR_PCICFG);
638169689Skan		OS_REG_WRITE(ah, AR_PCICFG, pcicfg | AR_PCICFG_EEPROMSEL);
639169689Skan		ok = ath_hal_eepromRead(ah, *(const uint16_t *)args, *result);
640169689Skan		OS_REG_WRITE(ah, AR_PCICFG, pcicfg);
641169689Skan		if (ok)
642169689Skan			*resultsize = sizeof(uint16_t);
643169689Skan		return ok;
644169689Skan	}
645169689Skan#endif
646169689Skan	return ath_hal_getdiagstate(ah, request,
647169689Skan		args, argsize, result, resultsize);
648169689Skan}
649169689Skan