1185377Ssam/*
2187831Ssam * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
3185377Ssam * Copyright (c) 2002-2006 Atheros Communications, Inc.
4185377Ssam *
5185377Ssam * Permission to use, copy, modify, and/or distribute this software for any
6185377Ssam * purpose with or without fee is hereby granted, provided that the above
7185377Ssam * copyright notice and this permission notice appear in all copies.
8185377Ssam *
9185377Ssam * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10185377Ssam * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11185377Ssam * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12185377Ssam * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13185377Ssam * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14185377Ssam * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15185377Ssam * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16185377Ssam *
17187510Ssam * $FreeBSD$
18185377Ssam */
19185377Ssam#include "opt_ah.h"
20185377Ssam
21185377Ssam#include "ah.h"
22185377Ssam#include "ah_internal.h"
23185377Ssam
24185377Ssam#include "ar5211/ar5211.h"
25185377Ssam#include "ar5211/ar5211reg.h"
26185377Ssam#include "ar5211/ar5211phy.h"
27185377Ssam
28185377Ssam#include "ah_eeprom_v3.h"
29185377Ssam
30185377Ssam#define	AR_NUM_GPIO	6		/* 6 GPIO bits */
31185377Ssam#define	AR_GPIOD_MASK	0x2f		/* 6-bit mask */
32185377Ssam
33185377Ssamvoid
34185377Ssamar5211GetMacAddress(struct ath_hal *ah, uint8_t *mac)
35185377Ssam{
36185377Ssam	struct ath_hal_5211 *ahp = AH5211(ah);
37185377Ssam
38185377Ssam	OS_MEMCPY(mac, ahp->ah_macaddr, IEEE80211_ADDR_LEN);
39185377Ssam}
40185377Ssam
41185377SsamHAL_BOOL
42185377Ssamar5211SetMacAddress(struct ath_hal *ah, const uint8_t *mac)
43185377Ssam{
44185377Ssam	struct ath_hal_5211 *ahp = AH5211(ah);
45185377Ssam
46185377Ssam	OS_MEMCPY(ahp->ah_macaddr, mac, IEEE80211_ADDR_LEN);
47185377Ssam	return AH_TRUE;
48185377Ssam}
49185377Ssam
50185377Ssamvoid
51185377Ssamar5211GetBssIdMask(struct ath_hal *ah, uint8_t *mask)
52185377Ssam{
53185377Ssam	static const uint8_t ones[IEEE80211_ADDR_LEN] =
54185377Ssam		{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
55185377Ssam	OS_MEMCPY(mask, ones, IEEE80211_ADDR_LEN);
56185377Ssam}
57185377Ssam
58185377SsamHAL_BOOL
59185377Ssamar5211SetBssIdMask(struct ath_hal *ah, const uint8_t *mask)
60185377Ssam{
61185377Ssam	return AH_FALSE;
62185377Ssam}
63185377Ssam
64185377Ssam/*
65185377Ssam * Read 16 bits of data from the specified EEPROM offset.
66185377Ssam */
67185377SsamHAL_BOOL
68185377Ssamar5211EepromRead(struct ath_hal *ah, u_int off, uint16_t *data)
69185377Ssam{
70185377Ssam	OS_REG_WRITE(ah, AR_EEPROM_ADDR, off);
71185377Ssam	OS_REG_WRITE(ah, AR_EEPROM_CMD, AR_EEPROM_CMD_READ);
72185377Ssam
73185377Ssam	if (!ath_hal_wait(ah, AR_EEPROM_STS,
74185377Ssam	    AR_EEPROM_STS_READ_COMPLETE | AR_EEPROM_STS_READ_ERROR,
75185377Ssam	    AR_EEPROM_STS_READ_COMPLETE)) {
76185377Ssam		HALDEBUG(ah, HAL_DEBUG_ANY,
77185377Ssam		    "%s: read failed for entry 0x%x\n", __func__, off);
78185377Ssam		return AH_FALSE;
79185377Ssam	}
80185377Ssam	*data = OS_REG_READ(ah, AR_EEPROM_DATA) & 0xffff;
81185377Ssam	return AH_TRUE;
82185377Ssam}
83185377Ssam
84185380Ssam#ifdef AH_SUPPORT_WRITE_EEPROM
85185377Ssam/*
86185380Ssam * Write 16 bits of data to the specified EEPROM offset.
87185380Ssam */
88185380SsamHAL_BOOL
89185380Ssamar5211EepromWrite(struct ath_hal *ah, u_int off, uint16_t data)
90185380Ssam{
91185380Ssam	return AH_FALSE;
92185380Ssam}
93185380Ssam#endif /* AH_SUPPORT_WRITE_EEPROM */
94185380Ssam
95185380Ssam/*
96185380Ssam * Attempt to change the cards operating regulatory domain to the given value
97185380Ssam */
98185380SsamHAL_BOOL
99185380Ssamar5211SetRegulatoryDomain(struct ath_hal *ah,
100185380Ssam	uint16_t regDomain, HAL_STATUS *status)
101185380Ssam{
102185380Ssam	HAL_STATUS ecode;
103185380Ssam
104185380Ssam	if (AH_PRIVATE(ah)->ah_currentRD == regDomain) {
105185380Ssam		ecode = HAL_EINVAL;
106185380Ssam		goto bad;
107185380Ssam	}
108185380Ssam	/*
109185380Ssam	 * Check if EEPROM is configured to allow this; must
110185380Ssam	 * be a proper version and the protection bits must
111185380Ssam	 * permit re-writing that segment of the EEPROM.
112185380Ssam	 */
113185380Ssam	if (ath_hal_eepromGetFlag(ah, AR_EEP_WRITEPROTECT)) {
114185380Ssam		ecode = HAL_EEWRITE;
115185380Ssam		goto bad;
116185380Ssam	}
117185380Ssam#ifdef AH_SUPPORT_WRITE_REGDOMAIN
118185380Ssam	if (ar5211EepromWrite(ah, AR_EEPROM_REG_DOMAIN, regDomain)) {
119185380Ssam		HALDEBUG(ah, HAL_DEBUG_ANY,
120185380Ssam		    "%s: set regulatory domain to %u (0x%x)\n",
121185380Ssam		    __func__, regDomain, regDomain);
122185380Ssam		AH_PRIVATE(ah)->ah_currentRD = regDomain;
123185380Ssam		return AH_TRUE;
124185380Ssam	}
125185380Ssam#endif
126185380Ssam	ecode = HAL_EIO;
127185380Ssambad:
128185380Ssam	if (status)
129185380Ssam		*status = ecode;
130185380Ssam	return AH_FALSE;
131185380Ssam}
132185380Ssam
133185380Ssam/*
134185377Ssam * Return the wireless modes (a,b,g,t) supported by hardware.
135185377Ssam *
136185377Ssam * This value is what is actually supported by the hardware
137185377Ssam * and is unaffected by regulatory/country code settings.
138185377Ssam *
139185377Ssam */
140185377Ssamu_int
141185377Ssamar5211GetWirelessModes(struct ath_hal *ah)
142185377Ssam{
143185377Ssam	u_int mode = 0;
144185377Ssam
145185377Ssam	if (ath_hal_eepromGetFlag(ah, AR_EEP_AMODE)) {
146185377Ssam		mode = HAL_MODE_11A;
147185377Ssam		if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO5DISABLE))
148185377Ssam			mode |= HAL_MODE_TURBO | HAL_MODE_108A;
149185377Ssam	}
150185377Ssam	if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE))
151185377Ssam		mode |= HAL_MODE_11B;
152185377Ssam	return mode;
153185377Ssam}
154185377Ssam
155185377Ssam#if 0
156185377SsamHAL_BOOL
157185377Ssamar5211GetTurboDisable(struct ath_hal *ah)
158185377Ssam{
159185377Ssam	return (AH5211(ah)->ah_turboDisable != 0);
160185377Ssam}
161185377Ssam#endif
162185377Ssam
163185377Ssam/*
164185377Ssam * Called if RfKill is supported (according to EEPROM).  Set the interrupt and
165185377Ssam * GPIO values so the ISR and can disable RF on a switch signal
166185377Ssam */
167185377Ssamvoid
168185377Ssamar5211EnableRfKill(struct ath_hal *ah)
169185377Ssam{
170185377Ssam	uint16_t rfsilent = AH_PRIVATE(ah)->ah_rfsilent;
171185377Ssam	int select = MS(rfsilent, AR_EEPROM_RFSILENT_GPIO_SEL);
172185377Ssam	int polarity = MS(rfsilent, AR_EEPROM_RFSILENT_POLARITY);
173185377Ssam
174185377Ssam	/*
175185377Ssam	 * Configure the desired GPIO port for input
176185377Ssam	 * and enable baseband rf silence.
177185377Ssam	 */
178185377Ssam	ar5211GpioCfgInput(ah, select);
179185377Ssam	OS_REG_SET_BIT(ah, AR_PHY_BASE, 0x00002000);
180185377Ssam	/*
181185377Ssam	 * If radio disable switch connection to GPIO bit x is enabled
182185377Ssam	 * program GPIO interrupt.
183185377Ssam	 * If rfkill bit on eeprom is 1, setupeeprommap routine has already
184185377Ssam	 * verified that it is a later version of eeprom, it has a place for
185185377Ssam	 * rfkill bit and it is set to 1, indicating that GPIO bit x hardware
186185377Ssam	 * connection is present.
187185377Ssam	 */
188185377Ssam	ar5211GpioSetIntr(ah, select, (ar5211GpioGet(ah, select) != polarity));
189185377Ssam}
190185377Ssam
191185377Ssam/*
192185377Ssam * Configure GPIO Output lines
193185377Ssam */
194185377SsamHAL_BOOL
195188974Ssamar5211GpioCfgOutput(struct ath_hal *ah, uint32_t gpio, HAL_GPIO_MUX_TYPE type)
196185377Ssam{
197185377Ssam	uint32_t reg;
198185377Ssam
199185377Ssam	HALASSERT(gpio < AR_NUM_GPIO);
200185377Ssam
201185377Ssam	reg =  OS_REG_READ(ah, AR_GPIOCR);
202185377Ssam	reg &= ~(AR_GPIOCR_0_CR_A << (gpio * AR_GPIOCR_CR_SHIFT));
203185377Ssam	reg |= AR_GPIOCR_0_CR_A << (gpio * AR_GPIOCR_CR_SHIFT);
204185377Ssam
205185377Ssam	OS_REG_WRITE(ah, AR_GPIOCR, reg);
206185377Ssam	return AH_TRUE;
207185377Ssam}
208185377Ssam
209185377Ssam/*
210185377Ssam * Configure GPIO Input lines
211185377Ssam */
212185377SsamHAL_BOOL
213185377Ssamar5211GpioCfgInput(struct ath_hal *ah, uint32_t gpio)
214185377Ssam{
215185377Ssam	uint32_t reg;
216185377Ssam
217185377Ssam	HALASSERT(gpio < AR_NUM_GPIO);
218185377Ssam
219185377Ssam	reg =  OS_REG_READ(ah, AR_GPIOCR);
220185377Ssam	reg &= ~(AR_GPIOCR_0_CR_A << (gpio * AR_GPIOCR_CR_SHIFT));
221185377Ssam	reg |= AR_GPIOCR_0_CR_N << (gpio * AR_GPIOCR_CR_SHIFT);
222185377Ssam
223185377Ssam	OS_REG_WRITE(ah, AR_GPIOCR, reg);
224185377Ssam	return AH_TRUE;
225185377Ssam}
226185377Ssam
227185377Ssam/*
228185377Ssam * Once configured for I/O - set output lines
229185377Ssam */
230185377SsamHAL_BOOL
231185377Ssamar5211GpioSet(struct ath_hal *ah, uint32_t gpio, uint32_t val)
232185377Ssam{
233185377Ssam	uint32_t reg;
234185377Ssam
235185377Ssam	HALASSERT(gpio < AR_NUM_GPIO);
236185377Ssam
237185377Ssam	reg =  OS_REG_READ(ah, AR_GPIODO);
238185377Ssam	reg &= ~(1 << gpio);
239185377Ssam	reg |= (val&1) << gpio;
240185377Ssam
241185377Ssam	OS_REG_WRITE(ah, AR_GPIODO, reg);
242185377Ssam	return AH_TRUE;
243185377Ssam}
244185377Ssam
245185377Ssam/*
246185377Ssam * Once configured for I/O - get input lines
247185377Ssam */
248185377Ssamuint32_t
249185377Ssamar5211GpioGet(struct ath_hal *ah, uint32_t gpio)
250185377Ssam{
251185377Ssam	if (gpio < AR_NUM_GPIO) {
252185377Ssam		uint32_t val = OS_REG_READ(ah, AR_GPIODI);
253185377Ssam		val = ((val & AR_GPIOD_MASK) >> gpio) & 0x1;
254185377Ssam		return val;
255185377Ssam	} else  {
256185377Ssam		return 0xffffffff;
257185377Ssam	}
258185377Ssam}
259185377Ssam
260185377Ssam/*
261185377Ssam * Set the GPIO 0 Interrupt (gpio is ignored)
262185377Ssam */
263185377Ssamvoid
264185377Ssamar5211GpioSetIntr(struct ath_hal *ah, u_int gpio, uint32_t ilevel)
265185377Ssam{
266185377Ssam	uint32_t val = OS_REG_READ(ah, AR_GPIOCR);
267185377Ssam
268185377Ssam	/* Clear the bits that we will modify. */
269185377Ssam	val &= ~(AR_GPIOCR_INT_SEL0 | AR_GPIOCR_INT_SELH | AR_GPIOCR_INT_ENA |
270185377Ssam			AR_GPIOCR_0_CR_A);
271185377Ssam
272185377Ssam	val |= AR_GPIOCR_INT_SEL0 | AR_GPIOCR_INT_ENA;
273185377Ssam	if (ilevel)
274185377Ssam		val |= AR_GPIOCR_INT_SELH;
275185377Ssam
276185377Ssam	/* Don't need to change anything for low level interrupt. */
277185377Ssam	OS_REG_WRITE(ah, AR_GPIOCR, val);
278185377Ssam
279185377Ssam	/* Change the interrupt mask. */
280185377Ssam	ar5211SetInterrupts(ah, AH5211(ah)->ah_maskReg | HAL_INT_GPIO);
281185377Ssam}
282185377Ssam
283185377Ssam/*
284185377Ssam * Change the LED blinking pattern to correspond to the connectivity
285185377Ssam */
286185377Ssamvoid
287185377Ssamar5211SetLedState(struct ath_hal *ah, HAL_LED_STATE state)
288185377Ssam{
289185377Ssam	static const uint32_t ledbits[8] = {
290185377Ssam		AR_PCICFG_LEDCTL_NONE|AR_PCICFG_LEDMODE_PROP, /* HAL_LED_INIT */
291185377Ssam		AR_PCICFG_LEDCTL_PEND|AR_PCICFG_LEDMODE_PROP, /* HAL_LED_SCAN */
292185377Ssam		AR_PCICFG_LEDCTL_PEND|AR_PCICFG_LEDMODE_PROP, /* HAL_LED_AUTH */
293185377Ssam		AR_PCICFG_LEDCTL_ASSOC|AR_PCICFG_LEDMODE_PROP,/* HAL_LED_ASSOC*/
294185377Ssam		AR_PCICFG_LEDCTL_ASSOC|AR_PCICFG_LEDMODE_PROP,/* HAL_LED_RUN */
295185377Ssam		AR_PCICFG_LEDCTL_NONE|AR_PCICFG_LEDMODE_RAND,
296185377Ssam		AR_PCICFG_LEDCTL_NONE|AR_PCICFG_LEDMODE_RAND,
297185377Ssam		AR_PCICFG_LEDCTL_NONE|AR_PCICFG_LEDMODE_RAND,
298185377Ssam	};
299185377Ssam	OS_REG_WRITE(ah, AR_PCICFG,
300185377Ssam		(OS_REG_READ(ah, AR_PCICFG) &~
301185377Ssam			(AR_PCICFG_LEDCTL | AR_PCICFG_LEDMODE))
302185377Ssam		| ledbits[state & 0x7]
303185377Ssam	);
304185377Ssam}
305185377Ssam
306185377Ssam/*
307185377Ssam * Change association related fields programmed into the hardware.
308185377Ssam * Writing a valid BSSID to the hardware effectively enables the hardware
309185377Ssam * to synchronize its TSF to the correct beacons and receive frames coming
310185377Ssam * from that BSSID. It is called by the SME JOIN operation.
311185377Ssam */
312185377Ssamvoid
313185377Ssamar5211WriteAssocid(struct ath_hal *ah, const uint8_t *bssid, uint16_t assocId)
314185377Ssam{
315185377Ssam	struct ath_hal_5211 *ahp = AH5211(ah);
316185377Ssam
317185377Ssam	/* XXX save bssid for possible re-use on reset */
318185377Ssam	OS_MEMCPY(ahp->ah_bssid, bssid, IEEE80211_ADDR_LEN);
319185377Ssam	OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid));
320185377Ssam	OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid+4) |
321185377Ssam				     ((assocId & 0x3fff)<<AR_BSS_ID1_AID_S));
322185377Ssam}
323185377Ssam
324185377Ssam/*
325185377Ssam * Get the current hardware tsf for stamlme.
326185377Ssam */
327185377Ssamuint64_t
328185377Ssamar5211GetTsf64(struct ath_hal *ah)
329185377Ssam{
330185377Ssam	uint32_t low1, low2, u32;
331185377Ssam
332185377Ssam	/* sync multi-word read */
333185377Ssam	low1 = OS_REG_READ(ah, AR_TSF_L32);
334185377Ssam	u32 = OS_REG_READ(ah, AR_TSF_U32);
335185377Ssam	low2 = OS_REG_READ(ah, AR_TSF_L32);
336185377Ssam	if (low2 < low1) {	/* roll over */
337185377Ssam		/*
338185377Ssam		 * If we are not preempted this will work.  If we are
339185377Ssam		 * then we re-reading AR_TSF_U32 does no good as the
340185377Ssam		 * low bits will be meaningless.  Likewise reading
341185377Ssam		 * L32, U32, U32, then comparing the last two reads
342185380Ssam		 * to check for rollover doesn't help if preempted--so
343185380Ssam		 * we take this approach as it costs one less PCI
344185380Ssam		 * read which can be noticeable when doing things
345185380Ssam		 * like timestamping packets in monitor mode.
346185377Ssam		 */
347185377Ssam		u32++;
348185377Ssam	}
349185377Ssam	return (((uint64_t) u32) << 32) | ((uint64_t) low2);
350185377Ssam}
351185377Ssam
352185377Ssam/*
353185377Ssam * Get the current hardware tsf for stamlme.
354185377Ssam */
355185377Ssamuint32_t
356185377Ssamar5211GetTsf32(struct ath_hal *ah)
357185377Ssam{
358185377Ssam	return OS_REG_READ(ah, AR_TSF_L32);
359185377Ssam}
360185377Ssam
361185377Ssam/*
362185377Ssam * Reset the current hardware tsf for stamlme
363185377Ssam */
364185377Ssamvoid
365185377Ssamar5211ResetTsf(struct ath_hal *ah)
366185377Ssam{
367185377Ssam	uint32_t val = OS_REG_READ(ah, AR_BEACON);
368185377Ssam
369185377Ssam	OS_REG_WRITE(ah, AR_BEACON, val | AR_BEACON_RESET_TSF);
370185377Ssam}
371185377Ssam
372185377Ssam/*
373185377Ssam * Grab a semi-random value from hardware registers - may not
374185377Ssam * change often
375185377Ssam */
376185377Ssamuint32_t
377185377Ssamar5211GetRandomSeed(struct ath_hal *ah)
378185377Ssam{
379185377Ssam	uint32_t nf;
380185377Ssam
381185377Ssam	nf = (OS_REG_READ(ah, AR_PHY(25)) >> 19) & 0x1ff;
382185377Ssam	if (nf & 0x100)
383185377Ssam		nf = 0 - ((nf ^ 0x1ff) + 1);
384185377Ssam	return (OS_REG_READ(ah, AR_TSF_U32) ^
385185377Ssam		OS_REG_READ(ah, AR_TSF_L32) ^ nf);
386185377Ssam}
387185377Ssam
388185377Ssam/*
389185377Ssam * Detect if our card is present
390185377Ssam */
391185377SsamHAL_BOOL
392185377Ssamar5211DetectCardPresent(struct ath_hal *ah)
393185377Ssam{
394185377Ssam	uint16_t macVersion, macRev;
395185377Ssam	uint32_t v;
396185377Ssam
397185377Ssam	/*
398185377Ssam	 * Read the Silicon Revision register and compare that
399185377Ssam	 * to what we read at attach time.  If the same, we say
400185377Ssam	 * a card/device is present.
401185377Ssam	 */
402185377Ssam	v = OS_REG_READ(ah, AR_SREV) & AR_SREV_ID_M;
403185377Ssam	macVersion = v >> AR_SREV_ID_S;
404185377Ssam	macRev = v & AR_SREV_REVISION_M;
405185377Ssam	return (AH_PRIVATE(ah)->ah_macVersion == macVersion &&
406185377Ssam		AH_PRIVATE(ah)->ah_macRev == macRev);
407185377Ssam}
408185377Ssam
409185377Ssam/*
410185377Ssam * Update MIB Counters
411185377Ssam */
412185377Ssamvoid
413185377Ssamar5211UpdateMibCounters(struct ath_hal *ah, HAL_MIB_STATS *stats)
414185377Ssam{
415185377Ssam	stats->ackrcv_bad += OS_REG_READ(ah, AR_ACK_FAIL);
416185377Ssam	stats->rts_bad	  += OS_REG_READ(ah, AR_RTS_FAIL);
417185377Ssam	stats->fcs_bad	  += OS_REG_READ(ah, AR_FCS_FAIL);
418185377Ssam	stats->rts_good	  += OS_REG_READ(ah, AR_RTS_OK);
419185377Ssam	stats->beacons	  += OS_REG_READ(ah, AR_BEACON_CNT);
420185377Ssam}
421185377Ssam
422185377SsamHAL_BOOL
423185377Ssamar5211SetSifsTime(struct ath_hal *ah, u_int us)
424185377Ssam{
425185377Ssam	struct ath_hal_5211 *ahp = AH5211(ah);
426185377Ssam
427185377Ssam	if (us > ath_hal_mac_usec(ah, 0xffff)) {
428185377Ssam		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad SIFS time %u\n",
429185377Ssam		    __func__, us);
430185377Ssam		ahp->ah_sifstime = (u_int) -1;	/* restore default handling */
431185377Ssam		return AH_FALSE;
432185377Ssam	} else {
433185377Ssam		/* convert to system clocks */
434185377Ssam		OS_REG_WRITE(ah, AR_D_GBL_IFS_SIFS, ath_hal_mac_clks(ah, us));
435187831Ssam		ahp->ah_slottime = us;
436185377Ssam		return AH_TRUE;
437185377Ssam	}
438185377Ssam}
439185377Ssam
440185377Ssamu_int
441185377Ssamar5211GetSifsTime(struct ath_hal *ah)
442185377Ssam{
443185377Ssam	u_int clks = OS_REG_READ(ah, AR_D_GBL_IFS_SIFS) & 0xffff;
444185377Ssam	return ath_hal_mac_usec(ah, clks);	/* convert from system clocks */
445185377Ssam}
446185377Ssam
447185377SsamHAL_BOOL
448185377Ssamar5211SetSlotTime(struct ath_hal *ah, u_int us)
449185377Ssam{
450185377Ssam	struct ath_hal_5211 *ahp = AH5211(ah);
451185377Ssam
452185377Ssam	if (us < HAL_SLOT_TIME_9 || us > ath_hal_mac_usec(ah, 0xffff)) {
453185377Ssam		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad slot time %u\n",
454185377Ssam		    __func__, us);
455185377Ssam		ahp->ah_slottime = us;	/* restore default handling */
456185377Ssam		return AH_FALSE;
457185377Ssam	} else {
458185377Ssam		/* convert to system clocks */
459185377Ssam		OS_REG_WRITE(ah, AR_D_GBL_IFS_SLOT, ath_hal_mac_clks(ah, us));
460185377Ssam		ahp->ah_slottime = us;
461185377Ssam		return AH_TRUE;
462185377Ssam	}
463185377Ssam}
464185377Ssam
465185377Ssamu_int
466185377Ssamar5211GetSlotTime(struct ath_hal *ah)
467185377Ssam{
468185377Ssam	u_int clks = OS_REG_READ(ah, AR_D_GBL_IFS_SLOT) & 0xffff;
469185377Ssam	return ath_hal_mac_usec(ah, clks);	/* convert from system clocks */
470185377Ssam}
471185377Ssam
472185377SsamHAL_BOOL
473185377Ssamar5211SetAckTimeout(struct ath_hal *ah, u_int us)
474185377Ssam{
475185377Ssam	struct ath_hal_5211 *ahp = AH5211(ah);
476185377Ssam
477185377Ssam	if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) {
478185377Ssam		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad ack timeout %u\n",
479185377Ssam		    __func__, us);
480185377Ssam		ahp->ah_acktimeout = (u_int) -1; /* restore default handling */
481185377Ssam		return AH_FALSE;
482185377Ssam	} else {
483185377Ssam		/* convert to system clocks */
484185377Ssam		OS_REG_RMW_FIELD(ah, AR_TIME_OUT,
485185377Ssam			AR_TIME_OUT_ACK, ath_hal_mac_clks(ah, us));
486185377Ssam		ahp->ah_acktimeout = us;
487185377Ssam		return AH_TRUE;
488185377Ssam	}
489185377Ssam}
490185377Ssam
491185377Ssamu_int
492185377Ssamar5211GetAckTimeout(struct ath_hal *ah)
493185377Ssam{
494185377Ssam	u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_ACK);
495185377Ssam	return ath_hal_mac_usec(ah, clks);	/* convert from system clocks */
496185377Ssam}
497185377Ssam
498185377Ssamu_int
499185377Ssamar5211GetAckCTSRate(struct ath_hal *ah)
500185377Ssam{
501185377Ssam	return ((AH5211(ah)->ah_staId1Defaults & AR_STA_ID1_ACKCTS_6MB) == 0);
502185377Ssam}
503185377Ssam
504185377SsamHAL_BOOL
505185377Ssamar5211SetAckCTSRate(struct ath_hal *ah, u_int high)
506185377Ssam{
507185377Ssam	struct ath_hal_5211 *ahp = AH5211(ah);
508185377Ssam
509185377Ssam	if (high) {
510185377Ssam		OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB);
511185377Ssam		ahp->ah_staId1Defaults &= ~AR_STA_ID1_ACKCTS_6MB;
512185377Ssam	} else {
513185377Ssam		OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB);
514185377Ssam		ahp->ah_staId1Defaults |= AR_STA_ID1_ACKCTS_6MB;
515185377Ssam	}
516185377Ssam	return AH_TRUE;
517185377Ssam}
518185377Ssam
519185377SsamHAL_BOOL
520185377Ssamar5211SetCTSTimeout(struct ath_hal *ah, u_int us)
521185377Ssam{
522185377Ssam	struct ath_hal_5211 *ahp = AH5211(ah);
523185377Ssam
524185377Ssam	if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) {
525185377Ssam		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad cts timeout %u\n",
526185377Ssam		    __func__, us);
527185377Ssam		ahp->ah_ctstimeout = (u_int) -1; /* restore default handling */
528185377Ssam		return AH_FALSE;
529185377Ssam	} else {
530185377Ssam		/* convert to system clocks */
531185377Ssam		OS_REG_RMW_FIELD(ah, AR_TIME_OUT,
532185377Ssam			AR_TIME_OUT_CTS, ath_hal_mac_clks(ah, us));
533185377Ssam		ahp->ah_ctstimeout = us;
534185377Ssam		return AH_TRUE;
535185377Ssam	}
536185377Ssam}
537185377Ssam
538185377Ssamu_int
539185377Ssamar5211GetCTSTimeout(struct ath_hal *ah)
540185377Ssam{
541185377Ssam	u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_CTS);
542185377Ssam	return ath_hal_mac_usec(ah, clks);	/* convert from system clocks */
543185377Ssam}
544185377Ssam
545185377SsamHAL_BOOL
546185377Ssamar5211SetDecompMask(struct ath_hal *ah, uint16_t keyidx, int en)
547185377Ssam{
548185377Ssam	/* nothing to do */
549185377Ssam        return AH_TRUE;
550185377Ssam}
551185377Ssam
552185377Ssamvoid
553185377Ssamar5211SetCoverageClass(struct ath_hal *ah, uint8_t coverageclass, int now)
554185377Ssam{
555185377Ssam}
556185377Ssam
557185377Ssam/*
558185377Ssam * Control Adaptive Noise Immunity Parameters
559185377Ssam */
560185377SsamHAL_BOOL
561185377Ssamar5211AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param)
562185377Ssam{
563185377Ssam	return AH_FALSE;
564185377Ssam}
565185377Ssam
566185377Ssamvoid
567217684Sadrianar5211AniPoll(struct ath_hal *ah, const struct ieee80211_channel *chan)
568217684Sadrian{
569217684Sadrian}
570217684Sadrian
571217684Sadrianvoid
572217684Sadrianar5211RxMonitor(struct ath_hal *ah, const HAL_NODE_STATS *stats,
573187831Ssam	const struct ieee80211_channel *chan)
574185377Ssam{
575185377Ssam}
576185377Ssam
577185377Ssamvoid
578185377Ssamar5211MibEvent(struct ath_hal *ah, const HAL_NODE_STATS *stats)
579185377Ssam{
580185377Ssam}
581185377Ssam
582185377Ssam/*
583185377Ssam * Get the rssi of frame curently being received.
584185377Ssam */
585185377Ssamuint32_t
586185377Ssamar5211GetCurRssi(struct ath_hal *ah)
587185377Ssam{
588185377Ssam	return (OS_REG_READ(ah, AR_PHY_CURRENT_RSSI) & 0xff);
589185377Ssam}
590185377Ssam
591185377Ssamu_int
592185377Ssamar5211GetDefAntenna(struct ath_hal *ah)
593185377Ssam{
594185377Ssam	return (OS_REG_READ(ah, AR_DEF_ANTENNA) & 0x7);
595185377Ssam}
596185377Ssam
597185377Ssamvoid
598185377Ssamar5211SetDefAntenna(struct ath_hal *ah, u_int antenna)
599185377Ssam{
600185377Ssam	OS_REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7));
601185377Ssam}
602185377Ssam
603185377SsamHAL_ANT_SETTING
604185377Ssamar5211GetAntennaSwitch(struct ath_hal *ah)
605185377Ssam{
606185377Ssam	return AH5211(ah)->ah_diversityControl;
607185377Ssam}
608185377Ssam
609185377SsamHAL_BOOL
610185377Ssamar5211SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings)
611185377Ssam{
612187831Ssam	const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan;
613185377Ssam
614185377Ssam	if (chan == AH_NULL) {
615185377Ssam		AH5211(ah)->ah_diversityControl = settings;
616185377Ssam		return AH_TRUE;
617185377Ssam	}
618185377Ssam	return ar5211SetAntennaSwitchInternal(ah, settings, chan);
619185377Ssam}
620185377Ssam
621185377SsamHAL_STATUS
622185377Ssamar5211GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
623185377Ssam	uint32_t capability, uint32_t *result)
624185377Ssam{
625185377Ssam
626185377Ssam	switch (type) {
627185377Ssam	case HAL_CAP_CIPHER:		/* cipher handled in hardware */
628185377Ssam		switch (capability) {
629185377Ssam		case HAL_CIPHER_AES_OCB:
630185377Ssam		case HAL_CIPHER_WEP:
631185377Ssam		case HAL_CIPHER_CLR:
632185377Ssam			return HAL_OK;
633185377Ssam		default:
634185377Ssam			return HAL_ENOTSUPP;
635185377Ssam		}
636185377Ssam	default:
637185377Ssam		return ath_hal_getcapability(ah, type, capability, result);
638185377Ssam	}
639185377Ssam}
640185377Ssam
641185377SsamHAL_BOOL
642185377Ssamar5211SetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
643185377Ssam	uint32_t capability, uint32_t setting, HAL_STATUS *status)
644185377Ssam{
645185377Ssam	switch (type) {
646185377Ssam	case HAL_CAP_DIAG:		/* hardware diagnostic support */
647185377Ssam		/*
648185377Ssam		 * NB: could split this up into virtual capabilities,
649185377Ssam		 *     (e.g. 1 => ACK, 2 => CTS, etc.) but it hardly
650185377Ssam		 *     seems worth the additional complexity.
651185377Ssam		 */
652185377Ssam#ifdef AH_DEBUG
653185377Ssam		AH_PRIVATE(ah)->ah_diagreg = setting;
654185377Ssam#else
655185377Ssam		AH_PRIVATE(ah)->ah_diagreg = setting & 0x6;	/* ACK+CTS */
656185377Ssam#endif
657185377Ssam		OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg);
658185377Ssam		return AH_TRUE;
659185377Ssam	default:
660185377Ssam		return ath_hal_setcapability(ah, type, capability,
661185377Ssam			setting, status);
662185377Ssam	}
663185377Ssam}
664185377Ssam
665185377SsamHAL_BOOL
666185377Ssamar5211GetDiagState(struct ath_hal *ah, int request,
667185377Ssam	const void *args, uint32_t argsize,
668185377Ssam	void **result, uint32_t *resultsize)
669185377Ssam{
670185377Ssam	struct ath_hal_5211 *ahp = AH5211(ah);
671185377Ssam
672185377Ssam	(void) ahp;
673185377Ssam	if (ath_hal_getdiagstate(ah, request, args, argsize, result, resultsize))
674185377Ssam		return AH_TRUE;
675185377Ssam	switch (request) {
676185377Ssam	case HAL_DIAG_EEPROM:
677185377Ssam		return ath_hal_eepromDiag(ah, request,
678185377Ssam		    args, argsize, result, resultsize);
679185377Ssam	case HAL_DIAG_RFGAIN:
680185377Ssam		*result = &ahp->ah_gainValues;
681185377Ssam		*resultsize = sizeof(GAIN_VALUES);
682185377Ssam		return AH_TRUE;
683185377Ssam	case HAL_DIAG_RFGAIN_CURSTEP:
684185377Ssam		*result = __DECONST(void *, ahp->ah_gainValues.currStep);
685185377Ssam		*resultsize = (*result == AH_NULL) ?
686185377Ssam			0 : sizeof(GAIN_OPTIMIZATION_STEP);
687185377Ssam		return AH_TRUE;
688185377Ssam	}
689185377Ssam	return AH_FALSE;
690185377Ssam}
691234873Sadrian
692234873Sadrian/*
693234873Sadrian * Return what percentage of the extension channel is busy.
694234873Sadrian * This is always disabled for AR5211 series NICs.
695234873Sadrian */
696234873Sadrianuint32_t
697234873Sadrianar5211Get11nExtBusy(struct ath_hal *ah)
698234873Sadrian{
699234873Sadrian	return (0);
700234873Sadrian}
701234873Sadrian
702234873Sadrian
703234873Sadrian/*
704234873Sadrian * There's no channel survey support for the AR5211.
705234873Sadrian */
706234873SadrianHAL_BOOL
707234873Sadrianar5211GetMibCycleCounts(struct ath_hal *ah, HAL_SURVEY_SAMPLE *hsample)
708234873Sadrian{
709234873Sadrian
710234873Sadrian	return (AH_FALSE);
711234873Sadrian}
712235206Sadrian
713235206Sadrianvoid
714247286Sadrianar5211SetChainMasks(struct ath_hal *ah, uint32_t txchainmask,
715247286Sadrian    uint32_t rxchainmask)
716247286Sadrian{
717247286Sadrian}
718247286Sadrian
719247286Sadrianvoid
720235206Sadrianar5211EnableDfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe)
721235206Sadrian{
722235206Sadrian}
723235206Sadrian
724235206Sadrianvoid
725235206Sadrianar5211GetDfsThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe)
726235206Sadrian{
727235206Sadrian}
728