1190747Snwhitehorn/*
2190747Snwhitehorn * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
3190747Snwhitehorn * Copyright (c) 2002-2006 Atheros Communications, Inc.
4190747Snwhitehorn *
5190747Snwhitehorn * Permission to use, copy, modify, and/or distribute this software for any
6190747Snwhitehorn * purpose with or without fee is hereby granted, provided that the above
7190747Snwhitehorn * copyright notice and this permission notice appear in all copies.
8190747Snwhitehorn *
9190747Snwhitehorn * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10190747Snwhitehorn * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11190747Snwhitehorn * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12190747Snwhitehorn * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13190747Snwhitehorn * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14190747Snwhitehorn * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15190747Snwhitehorn * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16190747Snwhitehorn *
17190747Snwhitehorn * $FreeBSD$
18190747Snwhitehorn */
19190747Snwhitehorn#include "opt_ah.h"
20190747Snwhitehorn
21190747Snwhitehorn#include "ah.h"
22190747Snwhitehorn#include "ah_internal.h"
23190747Snwhitehorn
24190747Snwhitehorn#include "ar5211/ar5211.h"
25190747Snwhitehorn#include "ar5211/ar5211reg.h"
26190747Snwhitehorn#include "ar5211/ar5211phy.h"
27190747Snwhitehorn
28190747Snwhitehorn#include "ah_eeprom_v3.h"
29190747Snwhitehorn
30190747Snwhitehorn#define	AR_NUM_GPIO	6		/* 6 GPIO bits */
31190747Snwhitehorn#define	AR_GPIOD_MASK	0x2f		/* 6-bit mask */
32190747Snwhitehorn
33190747Snwhitehornvoid
34190747Snwhitehornar5211GetMacAddress(struct ath_hal *ah, uint8_t *mac)
35190747Snwhitehorn{
36190747Snwhitehorn	struct ath_hal_5211 *ahp = AH5211(ah);
37190747Snwhitehorn
38190747Snwhitehorn	OS_MEMCPY(mac, ahp->ah_macaddr, IEEE80211_ADDR_LEN);
39190747Snwhitehorn}
40190747Snwhitehorn
41190747SnwhitehornHAL_BOOL
42190747Snwhitehornar5211SetMacAddress(struct ath_hal *ah, const uint8_t *mac)
43190747Snwhitehorn{
44190747Snwhitehorn	struct ath_hal_5211 *ahp = AH5211(ah);
45190747Snwhitehorn
46190747Snwhitehorn	OS_MEMCPY(ahp->ah_macaddr, mac, IEEE80211_ADDR_LEN);
47190747Snwhitehorn	return AH_TRUE;
48190747Snwhitehorn}
49190747Snwhitehorn
50190747Snwhitehornvoid
51190747Snwhitehornar5211GetBssIdMask(struct ath_hal *ah, uint8_t *mask)
52190747Snwhitehorn{
53190747Snwhitehorn	static const uint8_t ones[IEEE80211_ADDR_LEN] =
54190747Snwhitehorn		{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
55190747Snwhitehorn	OS_MEMCPY(mask, ones, IEEE80211_ADDR_LEN);
56190747Snwhitehorn}
57190747Snwhitehorn
58190747SnwhitehornHAL_BOOL
59190747Snwhitehornar5211SetBssIdMask(struct ath_hal *ah, const uint8_t *mask)
60190747Snwhitehorn{
61190747Snwhitehorn	return AH_FALSE;
62190747Snwhitehorn}
63190747Snwhitehorn
64190747Snwhitehorn/*
65190747Snwhitehorn * Read 16 bits of data from the specified EEPROM offset.
66190747Snwhitehorn */
67190747SnwhitehornHAL_BOOL
68209803Snwhitehornar5211EepromRead(struct ath_hal *ah, u_int off, uint16_t *data)
69190747Snwhitehorn{
70190747Snwhitehorn	OS_REG_WRITE(ah, AR_EEPROM_ADDR, off);
71190747Snwhitehorn	OS_REG_WRITE(ah, AR_EEPROM_CMD, AR_EEPROM_CMD_READ);
72209803Snwhitehorn
73209803Snwhitehorn	if (!ath_hal_wait(ah, AR_EEPROM_STS,
74190747Snwhitehorn	    AR_EEPROM_STS_READ_COMPLETE | AR_EEPROM_STS_READ_ERROR,
75209803Snwhitehorn	    AR_EEPROM_STS_READ_COMPLETE)) {
76190747Snwhitehorn		HALDEBUG(ah, HAL_DEBUG_ANY,
77190747Snwhitehorn		    "%s: read failed for entry 0x%x\n", __func__, off);
78190747Snwhitehorn		return AH_FALSE;
79190747Snwhitehorn	}
80190747Snwhitehorn	*data = OS_REG_READ(ah, AR_EEPROM_DATA) & 0xffff;
81208614Sraj	return AH_TRUE;
82190747Snwhitehorn}
83190747Snwhitehorn
84190747Snwhitehorn#ifdef AH_SUPPORT_WRITE_EEPROM
85190747Snwhitehorn/*
86190747Snwhitehorn * Write 16 bits of data to the specified EEPROM offset.
87190747Snwhitehorn */
88190747SnwhitehornHAL_BOOL
89190747Snwhitehornar5211EepromWrite(struct ath_hal *ah, u_int off, uint16_t data)
90190747Snwhitehorn{
91190747Snwhitehorn	return AH_FALSE;
92190747Snwhitehorn}
93194025Savg#endif /* AH_SUPPORT_WRITE_EEPROM */
94194025Savg
95190747Snwhitehorn/*
96190747Snwhitehorn * Attempt to change the cards operating regulatory domain to the given value
97190747Snwhitehorn */
98190747SnwhitehornHAL_BOOL
99190747Snwhitehornar5211SetRegulatoryDomain(struct ath_hal *ah,
100190747Snwhitehorn	uint16_t regDomain, HAL_STATUS *status)
101190747Snwhitehorn{
102209801Snwhitehorn	HAL_STATUS ecode;
103209803Snwhitehorn
104209803Snwhitehorn	if (AH_PRIVATE(ah)->ah_currentRD == regDomain) {
105190747Snwhitehorn		ecode = HAL_EINVAL;
106190747Snwhitehorn		goto bad;
107190747Snwhitehorn	}
108190747Snwhitehorn	/*
109190747Snwhitehorn	 * Check if EEPROM is configured to allow this; must
110190747Snwhitehorn	 * be a proper version and the protection bits must
111190747Snwhitehorn	 * permit re-writing that segment of the EEPROM.
112190747Snwhitehorn	 */
113190747Snwhitehorn	if (ath_hal_eepromGetFlag(ah, AR_EEP_WRITEPROTECT)) {
114190747Snwhitehorn		ecode = HAL_EEWRITE;
115190747Snwhitehorn		goto bad;
116190747Snwhitehorn	}
117190747Snwhitehorn#ifdef AH_SUPPORT_WRITE_REGDOMAIN
118190747Snwhitehorn	if (ar5211EepromWrite(ah, AR_EEPROM_REG_DOMAIN, regDomain)) {
119190747Snwhitehorn		HALDEBUG(ah, HAL_DEBUG_ANY,
120190747Snwhitehorn		    "%s: set regulatory domain to %u (0x%x)\n",
121190747Snwhitehorn		    __func__, regDomain, regDomain);
122190747Snwhitehorn		AH_PRIVATE(ah)->ah_currentRD = regDomain;
123190747Snwhitehorn		return AH_TRUE;
124190747Snwhitehorn	}
125190747Snwhitehorn#endif
126190747Snwhitehorn	ecode = HAL_EIO;
127190747Snwhitehornbad:
128190747Snwhitehorn	if (status)
129190747Snwhitehorn		*status = ecode;
130190747Snwhitehorn	return AH_FALSE;
131190747Snwhitehorn}
132190747Snwhitehorn
133209803Snwhitehorn/*
134190747Snwhitehorn * Return the wireless modes (a,b,g,t) supported by hardware.
135190747Snwhitehorn *
136190747Snwhitehorn * This value is what is actually supported by the hardware
137190747Snwhitehorn * and is unaffected by regulatory/country code settings.
138190747Snwhitehorn *
139190747Snwhitehorn */
140190747Snwhitehornu_int
141190747Snwhitehornar5211GetWirelessModes(struct ath_hal *ah)
142190747Snwhitehorn{
143190747Snwhitehorn	u_int mode = 0;
144190747Snwhitehorn
145190747Snwhitehorn	if (ath_hal_eepromGetFlag(ah, AR_EEP_AMODE)) {
146190747Snwhitehorn		mode = HAL_MODE_11A;
147190747Snwhitehorn		if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO5DISABLE))
148190747Snwhitehorn			mode |= HAL_MODE_TURBO | HAL_MODE_108A;
149190747Snwhitehorn	}
150190747Snwhitehorn	if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE))
151190747Snwhitehorn		mode |= HAL_MODE_11B;
152190747Snwhitehorn	return mode;
153190747Snwhitehorn}
154209803Snwhitehorn
155209803Snwhitehorn#if 0
156209803SnwhitehornHAL_BOOL
157209803Snwhitehornar5211GetTurboDisable(struct ath_hal *ah)
158209803Snwhitehorn{
159209803Snwhitehorn	return (AH5211(ah)->ah_turboDisable != 0);
160209803Snwhitehorn}
161190747Snwhitehorn#endif
162190747Snwhitehorn
163190747Snwhitehorn/*
164190747Snwhitehorn * Called if RfKill is supported (according to EEPROM).  Set the interrupt and
165190747Snwhitehorn * GPIO values so the ISR and can disable RF on a switch signal
166190747Snwhitehorn */
167190747Snwhitehornvoid
168190747Snwhitehornar5211EnableRfKill(struct ath_hal *ah)
169190747Snwhitehorn{
170190747Snwhitehorn	uint16_t rfsilent = AH_PRIVATE(ah)->ah_rfsilent;
171209803Snwhitehorn	int select = MS(rfsilent, AR_EEPROM_RFSILENT_GPIO_SEL);
172209803Snwhitehorn	int polarity = MS(rfsilent, AR_EEPROM_RFSILENT_POLARITY);
173209803Snwhitehorn
174190747Snwhitehorn	/*
175190747Snwhitehorn	 * Configure the desired GPIO port for input
176190747Snwhitehorn	 * and enable baseband rf silence.
177190747Snwhitehorn	 */
178190747Snwhitehorn	ar5211GpioCfgInput(ah, select);
179190747Snwhitehorn	OS_REG_SET_BIT(ah, AR_PHY_BASE, 0x00002000);
180209803Snwhitehorn	/*
181190747Snwhitehorn	 * If radio disable switch connection to GPIO bit x is enabled
182190747Snwhitehorn	 * program GPIO interrupt.
183190747Snwhitehorn	 * If rfkill bit on eeprom is 1, setupeeprommap routine has already
184190747Snwhitehorn	 * verified that it is a later version of eeprom, it has a place for
185190747Snwhitehorn	 * rfkill bit and it is set to 1, indicating that GPIO bit x hardware
186190747Snwhitehorn	 * connection is present.
187190747Snwhitehorn	 */
188190747Snwhitehorn	ar5211GpioSetIntr(ah, select, (ar5211GpioGet(ah, select) != polarity));
189190747Snwhitehorn}
190190747Snwhitehorn
191190747Snwhitehorn/*
192190747Snwhitehorn * Configure GPIO Output lines
193190747Snwhitehorn */
194190747SnwhitehornHAL_BOOL
195190747Snwhitehornar5211GpioCfgOutput(struct ath_hal *ah, uint32_t gpio, HAL_GPIO_MUX_TYPE type)
196190747Snwhitehorn{
197190747Snwhitehorn	uint32_t reg;
198190747Snwhitehorn
199190747Snwhitehorn	HALASSERT(gpio < AR_NUM_GPIO);
200190747Snwhitehorn
201190747Snwhitehorn	reg =  OS_REG_READ(ah, AR_GPIOCR);
202190747Snwhitehorn	reg &= ~(AR_GPIOCR_0_CR_A << (gpio * AR_GPIOCR_CR_SHIFT));
203190747Snwhitehorn	reg |= AR_GPIOCR_0_CR_A << (gpio * AR_GPIOCR_CR_SHIFT);
204190747Snwhitehorn
205190747Snwhitehorn	OS_REG_WRITE(ah, AR_GPIOCR, reg);
206190747Snwhitehorn	return AH_TRUE;
207190747Snwhitehorn}
208190747Snwhitehorn
209190747Snwhitehorn/*
210190747Snwhitehorn * Configure GPIO Input lines
211190747Snwhitehorn */
212190747SnwhitehornHAL_BOOL
213190747Snwhitehornar5211GpioCfgInput(struct ath_hal *ah, uint32_t gpio)
214190747Snwhitehorn{
215209803Snwhitehorn	uint32_t reg;
216190747Snwhitehorn
217190747Snwhitehorn	HALASSERT(gpio < AR_NUM_GPIO);
218190747Snwhitehorn
219209803Snwhitehorn	reg =  OS_REG_READ(ah, AR_GPIOCR);
220209803Snwhitehorn	reg &= ~(AR_GPIOCR_0_CR_A << (gpio * AR_GPIOCR_CR_SHIFT));
221209803Snwhitehorn	reg |= AR_GPIOCR_0_CR_N << (gpio * AR_GPIOCR_CR_SHIFT);
222209803Snwhitehorn
223209803Snwhitehorn	OS_REG_WRITE(ah, AR_GPIOCR, reg);
224209803Snwhitehorn	return AH_TRUE;
225209803Snwhitehorn}
226209803Snwhitehorn
227190747Snwhitehorn/*
228190747Snwhitehorn * Once configured for I/O - set output lines
229190747Snwhitehorn */
230190747SnwhitehornHAL_BOOL
231190747Snwhitehornar5211GpioSet(struct ath_hal *ah, uint32_t gpio, uint32_t val)
232190747Snwhitehorn{
233209803Snwhitehorn	uint32_t reg;
234190747Snwhitehorn
235190747Snwhitehorn	HALASSERT(gpio < AR_NUM_GPIO);
236190747Snwhitehorn
237190747Snwhitehorn	reg =  OS_REG_READ(ah, AR_GPIODO);
238190747Snwhitehorn	reg &= ~(1 << gpio);
239209803Snwhitehorn	reg |= (val&1) << gpio;
240209803Snwhitehorn
241209803Snwhitehorn	OS_REG_WRITE(ah, AR_GPIODO, reg);
242209803Snwhitehorn	return AH_TRUE;
243209803Snwhitehorn}
244190747Snwhitehorn
245209803Snwhitehorn/*
246190747Snwhitehorn * Once configured for I/O - get input lines
247190747Snwhitehorn */
248190747Snwhitehornuint32_t
249190747Snwhitehornar5211GpioGet(struct ath_hal *ah, uint32_t gpio)
250190747Snwhitehorn{
251209803Snwhitehorn	if (gpio < AR_NUM_GPIO) {
252190747Snwhitehorn		uint32_t val = OS_REG_READ(ah, AR_GPIODI);
253209803Snwhitehorn		val = ((val & AR_GPIOD_MASK) >> gpio) & 0x1;
254209803Snwhitehorn		return val;
255209803Snwhitehorn	} else  {
256190747Snwhitehorn		return 0xffffffff;
257190747Snwhitehorn	}
258190747Snwhitehorn}
259190747Snwhitehorn
260190747Snwhitehorn/*
261190747Snwhitehorn * Set the GPIO 0 Interrupt (gpio is ignored)
262209803Snwhitehorn */
263190747Snwhitehornvoid
264190747Snwhitehornar5211GpioSetIntr(struct ath_hal *ah, u_int gpio, uint32_t ilevel)
265190747Snwhitehorn{
266190747Snwhitehorn	uint32_t val = OS_REG_READ(ah, AR_GPIOCR);
267190747Snwhitehorn
268190747Snwhitehorn	/* Clear the bits that we will modify. */
269190747Snwhitehorn	val &= ~(AR_GPIOCR_INT_SEL0 | AR_GPIOCR_INT_SELH | AR_GPIOCR_INT_ENA |
270190747Snwhitehorn			AR_GPIOCR_0_CR_A);
271190747Snwhitehorn
272190747Snwhitehorn	val |= AR_GPIOCR_INT_SEL0 | AR_GPIOCR_INT_ENA;
273190747Snwhitehorn	if (ilevel)
274209803Snwhitehorn		val |= AR_GPIOCR_INT_SELH;
275190747Snwhitehorn
276190747Snwhitehorn	/* Don't need to change anything for low level interrupt. */
277190747Snwhitehorn	OS_REG_WRITE(ah, AR_GPIOCR, val);
278190747Snwhitehorn
279190747Snwhitehorn	/* Change the interrupt mask. */
280190747Snwhitehorn	ar5211SetInterrupts(ah, AH5211(ah)->ah_maskReg | HAL_INT_GPIO);
281190747Snwhitehorn}
282190747Snwhitehorn
283190747Snwhitehorn/*
284190747Snwhitehorn * Change the LED blinking pattern to correspond to the connectivity
285190747Snwhitehorn */
286190747Snwhitehornvoid
287190747Snwhitehornar5211SetLedState(struct ath_hal *ah, HAL_LED_STATE state)
288190747Snwhitehorn{
289190747Snwhitehorn	static const uint32_t ledbits[8] = {
290208614Sraj		AR_PCICFG_LEDCTL_NONE|AR_PCICFG_LEDMODE_PROP, /* HAL_LED_INIT */
291190747Snwhitehorn		AR_PCICFG_LEDCTL_PEND|AR_PCICFG_LEDMODE_PROP, /* HAL_LED_SCAN */
292190747Snwhitehorn		AR_PCICFG_LEDCTL_PEND|AR_PCICFG_LEDMODE_PROP, /* HAL_LED_AUTH */
293190747Snwhitehorn		AR_PCICFG_LEDCTL_ASSOC|AR_PCICFG_LEDMODE_PROP,/* HAL_LED_ASSOC*/
294190747Snwhitehorn		AR_PCICFG_LEDCTL_ASSOC|AR_PCICFG_LEDMODE_PROP,/* HAL_LED_RUN */
295190747Snwhitehorn		AR_PCICFG_LEDCTL_NONE|AR_PCICFG_LEDMODE_RAND,
296190747Snwhitehorn		AR_PCICFG_LEDCTL_NONE|AR_PCICFG_LEDMODE_RAND,
297208614Sraj		AR_PCICFG_LEDCTL_NONE|AR_PCICFG_LEDMODE_RAND,
298190747Snwhitehorn	};
299190747Snwhitehorn	OS_REG_WRITE(ah, AR_PCICFG,
300190747Snwhitehorn		(OS_REG_READ(ah, AR_PCICFG) &~
301190747Snwhitehorn			(AR_PCICFG_LEDCTL | AR_PCICFG_LEDMODE))
302190747Snwhitehorn		| ledbits[state & 0x7]
303190747Snwhitehorn	);
304190747Snwhitehorn}
305190747Snwhitehorn
306190747Snwhitehorn/*
307190747Snwhitehorn * Change association related fields programmed into the hardware.
308209803Snwhitehorn * Writing a valid BSSID to the hardware effectively enables the hardware
309205496Snwhitehorn * to synchronize its TSF to the correct beacons and receive frames coming
310190747Snwhitehorn * from that BSSID. It is called by the SME JOIN operation.
311190747Snwhitehorn */
312190747Snwhitehornvoid
313190747Snwhitehornar5211WriteAssocid(struct ath_hal *ah, const uint8_t *bssid, uint16_t assocId)
314190747Snwhitehorn{
315209803Snwhitehorn	struct ath_hal_5211 *ahp = AH5211(ah);
316190747Snwhitehorn
317209803Snwhitehorn	/* XXX save bssid for possible re-use on reset */
318209803Snwhitehorn	OS_MEMCPY(ahp->ah_bssid, bssid, IEEE80211_ADDR_LEN);
319209803Snwhitehorn	OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid));
320209803Snwhitehorn	OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid+4) |
321190747Snwhitehorn				     ((assocId & 0x3fff)<<AR_BSS_ID1_AID_S));
322190747Snwhitehorn}
323190747Snwhitehorn
324209803Snwhitehorn/*
325209803Snwhitehorn * Get the current hardware tsf for stamlme.
326190747Snwhitehorn */
327190747Snwhitehornuint64_t
328190747Snwhitehornar5211GetTsf64(struct ath_hal *ah)
329209803Snwhitehorn{
330190747Snwhitehorn	uint32_t low1, low2, u32;
331190747Snwhitehorn
332190747Snwhitehorn	/* sync multi-word read */
333190747Snwhitehorn	low1 = OS_REG_READ(ah, AR_TSF_L32);
334190747Snwhitehorn	u32 = OS_REG_READ(ah, AR_TSF_U32);
335190747Snwhitehorn	low2 = OS_REG_READ(ah, AR_TSF_L32);
336190747Snwhitehorn	if (low2 < low1) {	/* roll over */
337190747Snwhitehorn		/*
338190747Snwhitehorn		 * If we are not preempted this will work.  If we are
339190747Snwhitehorn		 * then we re-reading AR_TSF_U32 does no good as the
340190747Snwhitehorn		 * low bits will be meaningless.  Likewise reading
341190747Snwhitehorn		 * L32, U32, U32, then comparing the last two reads
342209803Snwhitehorn		 * to check for rollover doesn't help if preempted--so
343205496Snwhitehorn		 * we take this approach as it costs one less PCI
344190747Snwhitehorn		 * read which can be noticeable when doing things
345190747Snwhitehorn		 * like timestamping packets in monitor mode.
346190747Snwhitehorn		 */
347190747Snwhitehorn		u32++;
348190747Snwhitehorn	}
349209803Snwhitehorn	return (((uint64_t) u32) << 32) | ((uint64_t) low2);
350190747Snwhitehorn}
351209803Snwhitehorn
352209803Snwhitehorn/*
353209803Snwhitehorn * Get the current hardware tsf for stamlme.
354209803Snwhitehorn */
355190747Snwhitehornuint32_t
356209803Snwhitehornar5211GetTsf32(struct ath_hal *ah)
357209803Snwhitehorn{
358209803Snwhitehorn	return OS_REG_READ(ah, AR_TSF_L32);
359209803Snwhitehorn}
360190747Snwhitehorn
361209803Snwhitehorn/*
362209803Snwhitehorn * Reset the current hardware tsf for stamlme
363209803Snwhitehorn */
364190747Snwhitehornvoid
365190747Snwhitehornar5211ResetTsf(struct ath_hal *ah)
366190747Snwhitehorn{
367190747Snwhitehorn	uint32_t val = OS_REG_READ(ah, AR_BEACON);
368190747Snwhitehorn
369190747Snwhitehorn	OS_REG_WRITE(ah, AR_BEACON, val | AR_BEACON_RESET_TSF);
370190747Snwhitehorn}
371209803Snwhitehorn
372205496Snwhitehorn/*
373190747Snwhitehorn * Grab a semi-random value from hardware registers - may not
374190747Snwhitehorn * change often
375190747Snwhitehorn */
376190747Snwhitehornuint32_t
377190747Snwhitehornar5211GetRandomSeed(struct ath_hal *ah)
378209803Snwhitehorn{
379190747Snwhitehorn	uint32_t nf;
380209803Snwhitehorn
381209803Snwhitehorn	nf = (OS_REG_READ(ah, AR_PHY(25)) >> 19) & 0x1ff;
382209803Snwhitehorn	if (nf & 0x100)
383209803Snwhitehorn		nf = 0 - ((nf ^ 0x1ff) + 1);
384190747Snwhitehorn	return (OS_REG_READ(ah, AR_TSF_U32) ^
385209803Snwhitehorn		OS_REG_READ(ah, AR_TSF_L32) ^ nf);
386209803Snwhitehorn}
387209803Snwhitehorn
388209803Snwhitehorn/*
389190747Snwhitehorn * Detect if our card is present
390209803Snwhitehorn */
391209803SnwhitehornHAL_BOOL
392209803Snwhitehornar5211DetectCardPresent(struct ath_hal *ah)
393190747Snwhitehorn{
394190747Snwhitehorn	uint16_t macVersion, macRev;
395190747Snwhitehorn	uint32_t v;
396190747Snwhitehorn
397190747Snwhitehorn	/*
398190747Snwhitehorn	 * Read the Silicon Revision register and compare that
399190747Snwhitehorn	 * to what we read at attach time.  If the same, we say
400209803Snwhitehorn	 * a card/device is present.
401205496Snwhitehorn	 */
402190747Snwhitehorn	v = OS_REG_READ(ah, AR_SREV) & AR_SREV_ID_M;
403190747Snwhitehorn	macVersion = v >> AR_SREV_ID_S;
404190747Snwhitehorn	macRev = v & AR_SREV_REVISION_M;
405190747Snwhitehorn	return (AH_PRIVATE(ah)->ah_macVersion == macVersion &&
406190747Snwhitehorn		AH_PRIVATE(ah)->ah_macRev == macRev);
407209803Snwhitehorn}
408190747Snwhitehorn
409209803Snwhitehorn/*
410209803Snwhitehorn * Update MIB Counters
411209803Snwhitehorn */
412209803Snwhitehornvoid
413190747Snwhitehornar5211UpdateMibCounters(struct ath_hal *ah, HAL_MIB_STATS *stats)
414209803Snwhitehorn{
415209803Snwhitehorn	stats->ackrcv_bad += OS_REG_READ(ah, AR_ACK_FAIL);
416209803Snwhitehorn	stats->rts_bad	  += OS_REG_READ(ah, AR_RTS_FAIL);
417209803Snwhitehorn	stats->fcs_bad	  += OS_REG_READ(ah, AR_FCS_FAIL);
418190747Snwhitehorn	stats->rts_good	  += OS_REG_READ(ah, AR_RTS_OK);
419209803Snwhitehorn	stats->beacons	  += OS_REG_READ(ah, AR_BEACON_CNT);
420209803Snwhitehorn}
421209803Snwhitehorn
422190747SnwhitehornHAL_BOOL
423190747Snwhitehornar5211SetSifsTime(struct ath_hal *ah, u_int us)
424190747Snwhitehorn{
425190747Snwhitehorn	struct ath_hal_5211 *ahp = AH5211(ah);
426190747Snwhitehorn
427190747Snwhitehorn	if (us > ath_hal_mac_usec(ah, 0xffff)) {
428190747Snwhitehorn		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad SIFS time %u\n",
429209803Snwhitehorn		    __func__, us);
430205496Snwhitehorn		ahp->ah_sifstime = (u_int) -1;	/* restore default handling */
431190747Snwhitehorn		return AH_FALSE;
432190747Snwhitehorn	} else {
433190747Snwhitehorn		/* convert to system clocks */
434190747Snwhitehorn		OS_REG_WRITE(ah, AR_D_GBL_IFS_SIFS, ath_hal_mac_clks(ah, us));
435190747Snwhitehorn		ahp->ah_slottime = us;
436209803Snwhitehorn		return AH_TRUE;
437190747Snwhitehorn	}
438209803Snwhitehorn}
439209803Snwhitehorn
440209803Snwhitehornu_int
441209803Snwhitehornar5211GetSifsTime(struct ath_hal *ah)
442190747Snwhitehorn{
443209803Snwhitehorn	u_int clks = OS_REG_READ(ah, AR_D_GBL_IFS_SIFS) & 0xffff;
444209803Snwhitehorn	return ath_hal_mac_usec(ah, clks);	/* convert from system clocks */
445209803Snwhitehorn}
446209803Snwhitehorn
447190747SnwhitehornHAL_BOOL
448209803Snwhitehornar5211SetSlotTime(struct ath_hal *ah, u_int us)
449209803Snwhitehorn{
450209803Snwhitehorn	struct ath_hal_5211 *ahp = AH5211(ah);
451190747Snwhitehorn
452190747Snwhitehorn	if (us < HAL_SLOT_TIME_9 || us > ath_hal_mac_usec(ah, 0xffff)) {
453190747Snwhitehorn		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad slot time %u\n",
454190747Snwhitehorn		    __func__, us);
455190747Snwhitehorn		ahp->ah_slottime = us;	/* restore default handling */
456190747Snwhitehorn		return AH_FALSE;
457190747Snwhitehorn	} else {
458209803Snwhitehorn		/* convert to system clocks */
459205496Snwhitehorn		OS_REG_WRITE(ah, AR_D_GBL_IFS_SLOT, ath_hal_mac_clks(ah, us));
460190747Snwhitehorn		ahp->ah_slottime = us;
461190747Snwhitehorn		return AH_TRUE;
462190747Snwhitehorn	}
463190747Snwhitehorn}
464190747Snwhitehorn
465209803Snwhitehornu_int
466209803Snwhitehornar5211GetSlotTime(struct ath_hal *ah)
467190747Snwhitehorn{
468209803Snwhitehorn	u_int clks = OS_REG_READ(ah, AR_D_GBL_IFS_SLOT) & 0xffff;
469209803Snwhitehorn	return ath_hal_mac_usec(ah, clks);	/* convert from system clocks */
470209803Snwhitehorn}
471209803Snwhitehorn
472190747SnwhitehornHAL_BOOL
473190747Snwhitehornar5211SetAckTimeout(struct ath_hal *ah, u_int us)
474190747Snwhitehorn{
475190747Snwhitehorn	struct ath_hal_5211 *ahp = AH5211(ah);
476209803Snwhitehorn
477209803Snwhitehorn	if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) {
478190747Snwhitehorn		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad ack timeout %u\n",
479190747Snwhitehorn		    __func__, us);
480190747Snwhitehorn		ahp->ah_acktimeout = (u_int) -1; /* restore default handling */
481209803Snwhitehorn		return AH_FALSE;
482190747Snwhitehorn	} else {
483190747Snwhitehorn		/* convert to system clocks */
484190747Snwhitehorn		OS_REG_RMW_FIELD(ah, AR_TIME_OUT,
485190747Snwhitehorn			AR_TIME_OUT_ACK, ath_hal_mac_clks(ah, us));
486190747Snwhitehorn		ahp->ah_acktimeout = us;
487190747Snwhitehorn		return AH_TRUE;
488190747Snwhitehorn	}
489190747Snwhitehorn}
490190747Snwhitehorn
491209803Snwhitehornu_int
492205496Snwhitehornar5211GetAckTimeout(struct ath_hal *ah)
493190747Snwhitehorn{
494190747Snwhitehorn	u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_ACK);
495190747Snwhitehorn	return ath_hal_mac_usec(ah, clks);	/* convert from system clocks */
496190747Snwhitehorn}
497190747Snwhitehorn
498190747Snwhitehornu_int
499190747Snwhitehornar5211GetAckCTSRate(struct ath_hal *ah)
500209803Snwhitehorn{
501209803Snwhitehorn	return ((AH5211(ah)->ah_staId1Defaults & AR_STA_ID1_ACKCTS_6MB) == 0);
502190747Snwhitehorn}
503209803Snwhitehorn
504209803SnwhitehornHAL_BOOL
505209803Snwhitehornar5211SetAckCTSRate(struct ath_hal *ah, u_int high)
506209803Snwhitehorn{
507190747Snwhitehorn	struct ath_hal_5211 *ahp = AH5211(ah);
508190747Snwhitehorn
509190747Snwhitehorn	if (high) {
510190747Snwhitehorn		OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB);
511190747Snwhitehorn		ahp->ah_staId1Defaults &= ~AR_STA_ID1_ACKCTS_6MB;
512190747Snwhitehorn	} else {
513209803Snwhitehorn		OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB);
514209803Snwhitehorn		ahp->ah_staId1Defaults |= AR_STA_ID1_ACKCTS_6MB;
515209803Snwhitehorn	}
516190747Snwhitehorn	return AH_TRUE;
517190747Snwhitehorn}
518190747Snwhitehorn
519209803SnwhitehornHAL_BOOL
520190747Snwhitehornar5211SetCTSTimeout(struct ath_hal *ah, u_int us)
521190747Snwhitehorn{
522190747Snwhitehorn	struct ath_hal_5211 *ahp = AH5211(ah);
523190747Snwhitehorn
524190747Snwhitehorn	if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) {
525190747Snwhitehorn		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad cts timeout %u\n",
526190747Snwhitehorn		    __func__, us);
527190747Snwhitehorn		ahp->ah_ctstimeout = (u_int) -1; /* restore default handling */
528190747Snwhitehorn		return AH_FALSE;
529190747Snwhitehorn	} else {
530190747Snwhitehorn		/* convert to system clocks */
531209803Snwhitehorn		OS_REG_RMW_FIELD(ah, AR_TIME_OUT,
532205496Snwhitehorn			AR_TIME_OUT_CTS, ath_hal_mac_clks(ah, us));
533190747Snwhitehorn		ahp->ah_ctstimeout = us;
534190747Snwhitehorn		return AH_TRUE;
535190747Snwhitehorn	}
536190747Snwhitehorn}
537190747Snwhitehorn
538190747Snwhitehornu_int
539190747Snwhitehornar5211GetCTSTimeout(struct ath_hal *ah)
540209803Snwhitehorn{
541190747Snwhitehorn	u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_CTS);
542209803Snwhitehorn	return ath_hal_mac_usec(ah, clks);	/* convert from system clocks */
543209803Snwhitehorn}
544209803Snwhitehorn
545209803SnwhitehornHAL_BOOL
546190747Snwhitehornar5211SetDecompMask(struct ath_hal *ah, uint16_t keyidx, int en)
547190747Snwhitehorn{
548190747Snwhitehorn	/* nothing to do */
549190747Snwhitehorn        return AH_TRUE;
550190747Snwhitehorn}
551209803Snwhitehorn
552209803Snwhitehornvoid
553209803Snwhitehornar5211SetCoverageClass(struct ath_hal *ah, uint8_t coverageclass, int now)
554190747Snwhitehorn{
555190747Snwhitehorn}
556190747Snwhitehorn
557209803Snwhitehorn/*
558190747Snwhitehorn * Control Adaptive Noise Immunity Parameters
559190747Snwhitehorn */
560190747SnwhitehornHAL_BOOL
561190747Snwhitehornar5211AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param)
562190747Snwhitehorn{
563190747Snwhitehorn	return AH_FALSE;
564190747Snwhitehorn}
565190747Snwhitehorn
566190747Snwhitehornvoid
567194025Savgar5211AniPoll(struct ath_hal *ah, const struct ieee80211_channel *chan)
568194025Savg{
569190747Snwhitehorn}
570209803Snwhitehorn
571205496Snwhitehornvoid
572190747Snwhitehornar5211RxMonitor(struct ath_hal *ah, const HAL_NODE_STATS *stats,
573190747Snwhitehorn	const struct ieee80211_channel *chan)
574190747Snwhitehorn{
575190747Snwhitehorn}
576190747Snwhitehorn
577190747Snwhitehornvoid
578190747Snwhitehornar5211MibEvent(struct ath_hal *ah, const HAL_NODE_STATS *stats)
579190747Snwhitehorn{
580209803Snwhitehorn}
581190747Snwhitehorn
582209803Snwhitehorn/*
583209803Snwhitehorn * Get the rssi of frame curently being received.
584209803Snwhitehorn */
585209803Snwhitehornuint32_t
586190747Snwhitehornar5211GetCurRssi(struct ath_hal *ah)
587190747Snwhitehorn{
588190747Snwhitehorn	return (OS_REG_READ(ah, AR_PHY_CURRENT_RSSI) & 0xff);
589190747Snwhitehorn}
590190747Snwhitehorn
591190747Snwhitehornu_int
592209803Snwhitehornar5211GetDefAntenna(struct ath_hal *ah)
593209803Snwhitehorn{
594209803Snwhitehorn	return (OS_REG_READ(ah, AR_DEF_ANTENNA) & 0x7);
595190747Snwhitehorn}
596190747Snwhitehorn
597190747Snwhitehornvoid
598209803Snwhitehornar5211SetDefAntenna(struct ath_hal *ah, u_int antenna)
599190747Snwhitehorn{
600190747Snwhitehorn	OS_REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7));
601190747Snwhitehorn}
602190747Snwhitehorn
603190747SnwhitehornHAL_ANT_SETTING
604190747Snwhitehornar5211GetAntennaSwitch(struct ath_hal *ah)
605190747Snwhitehorn{
606190747Snwhitehorn	return AH5211(ah)->ah_diversityControl;
607209803Snwhitehorn}
608205496Snwhitehorn
609190747SnwhitehornHAL_BOOL
610190747Snwhitehornar5211SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings)
611190747Snwhitehorn{
612190747Snwhitehorn	const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan;
613190747Snwhitehorn
614190747Snwhitehorn	if (chan == AH_NULL) {
615209803Snwhitehorn		AH5211(ah)->ah_diversityControl = settings;
616209803Snwhitehorn		return AH_TRUE;
617190747Snwhitehorn	}
618209803Snwhitehorn	return ar5211SetAntennaSwitchInternal(ah, settings, chan);
619209803Snwhitehorn}
620209803Snwhitehorn
621209803SnwhitehornHAL_STATUS
622190747Snwhitehornar5211GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
623190747Snwhitehorn	uint32_t capability, uint32_t *result)
624190747Snwhitehorn{
625190747Snwhitehorn
626190747Snwhitehorn	switch (type) {
627209803Snwhitehorn	case HAL_CAP_CIPHER:		/* cipher handled in hardware */
628209803Snwhitehorn		switch (capability) {
629209803Snwhitehorn		case HAL_CIPHER_AES_OCB:
630190747Snwhitehorn		case HAL_CIPHER_WEP:
631190747Snwhitehorn		case HAL_CIPHER_CLR:
632190747Snwhitehorn			return HAL_OK;
633209803Snwhitehorn		default:
634190747Snwhitehorn			return HAL_ENOTSUPP;
635190747Snwhitehorn		}
636190747Snwhitehorn	default:
637190747Snwhitehorn		return ath_hal_getcapability(ah, type, capability, result);
638190747Snwhitehorn	}
639190747Snwhitehorn}
640190747Snwhitehorn
641190747SnwhitehornHAL_BOOL
642190747Snwhitehornar5211SetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
643190747Snwhitehorn	uint32_t capability, uint32_t setting, HAL_STATUS *status)
644209803Snwhitehorn{
645205496Snwhitehorn	switch (type) {
646190747Snwhitehorn	case HAL_CAP_DIAG:		/* hardware diagnostic support */
647190747Snwhitehorn		/*
648190747Snwhitehorn		 * NB: could split this up into virtual capabilities,
649190747Snwhitehorn		 *     (e.g. 1 => ACK, 2 => CTS, etc.) but it hardly
650190747Snwhitehorn		 *     seems worth the additional complexity.
651209803Snwhitehorn		 */
652190747Snwhitehorn#ifdef AH_DEBUG
653209803Snwhitehorn		AH_PRIVATE(ah)->ah_diagreg = setting;
654209803Snwhitehorn#else
655209803Snwhitehorn		AH_PRIVATE(ah)->ah_diagreg = setting & 0x6;	/* ACK+CTS */
656209803Snwhitehorn#endif
657190747Snwhitehorn		OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg);
658190747Snwhitehorn		return AH_TRUE;
659190747Snwhitehorn	default:
660209803Snwhitehorn		return ath_hal_setcapability(ah, type, capability,
661209803Snwhitehorn			setting, status);
662209803Snwhitehorn	}
663190747Snwhitehorn}
664190747Snwhitehorn
665190747SnwhitehornHAL_BOOL
666209803Snwhitehornar5211GetDiagState(struct ath_hal *ah, int request,
667190747Snwhitehorn	const void *args, uint32_t argsize,
668190747Snwhitehorn	void **result, uint32_t *resultsize)
669190747Snwhitehorn{
670190747Snwhitehorn	struct ath_hal_5211 *ahp = AH5211(ah);
671190747Snwhitehorn
672190747Snwhitehorn	(void) ahp;
673190747Snwhitehorn	if (ath_hal_getdiagstate(ah, request, args, argsize, result, resultsize))
674190747Snwhitehorn		return AH_TRUE;
675209803Snwhitehorn	switch (request) {
676205496Snwhitehorn	case HAL_DIAG_EEPROM:
677190747Snwhitehorn		return ath_hal_eepromDiag(ah, request,
678190747Snwhitehorn		    args, argsize, result, resultsize);
679190747Snwhitehorn	case HAL_DIAG_RFGAIN:
680190747Snwhitehorn		*result = &ahp->ah_gainValues;
681190747Snwhitehorn		*resultsize = sizeof(GAIN_VALUES);
682190747Snwhitehorn		return AH_TRUE;
683209803Snwhitehorn	case HAL_DIAG_RFGAIN_CURSTEP:
684209803Snwhitehorn		*result = __DECONST(void *, ahp->ah_gainValues.currStep);
685190747Snwhitehorn		*resultsize = (*result == AH_NULL) ?
686209803Snwhitehorn			0 : sizeof(GAIN_OPTIMIZATION_STEP);
687209803Snwhitehorn		return AH_TRUE;
688209803Snwhitehorn	}
689209803Snwhitehorn	return AH_FALSE;
690190747Snwhitehorn}
691190747Snwhitehorn