1185377Ssam/*
2187831Ssam * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
3185377Ssam * Copyright (c) 2002-2004 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 *
17187831Ssam * $FreeBSD$
18185377Ssam */
19185377Ssam#include "opt_ah.h"
20185377Ssam
21185377Ssam#include "ah.h"
22185377Ssam#include "ah_internal.h"
23185377Ssam
24185377Ssam#include "ar5210/ar5210.h"
25185377Ssam#include "ar5210/ar5210reg.h"
26185377Ssam#include "ar5210/ar5210phy.h"
27185377Ssam
28185380Ssam#include "ah_eeprom_v1.h"
29185380Ssam
30185377Ssam#define	AR_NUM_GPIO	6		/* 6 GPIO bits */
31185377Ssam#define	AR_GPIOD_MASK	0x2f		/* 6-bit mask */
32185377Ssam
33185377Ssamvoid
34185377Ssamar5210GetMacAddress(struct ath_hal *ah, uint8_t *mac)
35185377Ssam{
36185377Ssam	struct ath_hal_5210 *ahp = AH5210(ah);
37185377Ssam
38185377Ssam	OS_MEMCPY(mac, ahp->ah_macaddr, IEEE80211_ADDR_LEN);
39185377Ssam}
40185377Ssam
41185377SsamHAL_BOOL
42185377Ssamar5210SetMacAddress(struct ath_hal *ah, const uint8_t *mac)
43185377Ssam{
44185377Ssam	struct ath_hal_5210 *ahp = AH5210(ah);
45185377Ssam
46185377Ssam	OS_MEMCPY(ahp->ah_macaddr, mac, IEEE80211_ADDR_LEN);
47185377Ssam	return AH_TRUE;
48185377Ssam}
49185377Ssam
50185377Ssamvoid
51185377Ssamar5210GetBssIdMask(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
59185377Ssamar5210SetBssIdMask(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
68185377Ssamar5210EepromRead(struct ath_hal *ah, u_int off, uint16_t *data)
69185377Ssam{
70185377Ssam	(void) OS_REG_READ(ah, AR_EP_AIR(off));	/* activate read op */
71185377Ssam	if (!ath_hal_wait(ah, AR_EP_STA,
72185377Ssam	    AR_EP_STA_RDCMPLT | AR_EP_STA_RDERR, AR_EP_STA_RDCMPLT)) {
73185377Ssam		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: read failed for entry 0x%x\n",
74185377Ssam		    __func__, AR_EP_AIR(off));
75185377Ssam		return AH_FALSE;
76185377Ssam	}
77185377Ssam	*data = OS_REG_READ(ah, AR_EP_RDATA) & 0xffff;
78185377Ssam	return AH_TRUE;
79185377Ssam}
80185377Ssam
81185380Ssam#ifdef AH_SUPPORT_WRITE_EEPROM
82185377Ssam/*
83185380Ssam * Write 16 bits of data to the specified EEPROM offset.
84185380Ssam */
85185380SsamHAL_BOOL
86185380Ssamar5210EepromWrite(struct ath_hal *ah, u_int off, uint16_t data)
87185380Ssam{
88185380Ssam	return AH_FALSE;
89185380Ssam}
90185380Ssam#endif /* AH_SUPPORT_WRITE_EEPROM */
91185380Ssam
92185380Ssam/*
93185380Ssam * Attempt to change the cards operating regulatory domain to the given value
94185380Ssam */
95185380SsamHAL_BOOL
96185380Ssamar5210SetRegulatoryDomain(struct ath_hal *ah,
97185380Ssam	uint16_t regDomain, HAL_STATUS *status)
98185380Ssam{
99185380Ssam	HAL_STATUS ecode;
100185380Ssam
101185380Ssam	if (AH_PRIVATE(ah)->ah_currentRD == regDomain) {
102185380Ssam		ecode = HAL_EINVAL;
103185380Ssam		goto bad;
104185380Ssam	}
105185380Ssam	/*
106185380Ssam	 * Check if EEPROM is configured to allow this; must
107185380Ssam	 * be a proper version and the protection bits must
108185380Ssam	 * permit re-writing that segment of the EEPROM.
109185380Ssam	 */
110185380Ssam	if (ath_hal_eepromGetFlag(ah, AR_EEP_WRITEPROTECT)) {
111185380Ssam		ecode = HAL_EEWRITE;
112185380Ssam		goto bad;
113185380Ssam	}
114185380Ssam	ecode = HAL_EIO;		/* disallow all writes */
115185380Ssambad:
116185380Ssam	if (status)
117185380Ssam		*status = ecode;
118185380Ssam	return AH_FALSE;
119185380Ssam}
120185380Ssam
121185380Ssam/*
122185377Ssam * Return the wireless modes (a,b,g,t) supported by hardware.
123185377Ssam *
124185377Ssam * This value is what is actually supported by the hardware
125185377Ssam * and is unaffected by regulatory/country code settings.
126185377Ssam *
127185377Ssam */
128185377Ssamu_int
129185377Ssamar5210GetWirelessModes(struct ath_hal *ah)
130185377Ssam{
131185377Ssam	/* XXX could enable turbo mode but can't do all rates */
132185377Ssam	return HAL_MODE_11A;
133185377Ssam}
134185377Ssam
135185377Ssam/*
136185377Ssam * Called if RfKill is supported (according to EEPROM).  Set the interrupt and
137185377Ssam * GPIO values so the ISR and can disable RF on a switch signal
138185377Ssam */
139185377Ssamvoid
140185377Ssamar5210EnableRfKill(struct ath_hal *ah)
141185377Ssam{
142185377Ssam	uint16_t rfsilent = AH_PRIVATE(ah)->ah_rfsilent;
143185377Ssam	int select = MS(rfsilent, AR_EEPROM_RFSILENT_GPIO_SEL);
144185377Ssam	int polarity = MS(rfsilent, AR_EEPROM_RFSILENT_POLARITY);
145185377Ssam
146185377Ssam	/*
147185377Ssam	 * If radio disable switch connection to GPIO bit 0 is enabled
148185377Ssam	 * program GPIO interrupt.
149185377Ssam	 * If rfkill bit on eeprom is 1, setupeeprommap routine has already
150185377Ssam	 * verified that it is a later version of eeprom, it has a place for
151185377Ssam	 * rfkill bit and it is set to 1, indicating that GPIO bit 0 hardware
152185377Ssam	 * connection is present.
153185377Ssam	 */
154185377Ssam	ar5210Gpio0SetIntr(ah, select, (ar5210GpioGet(ah, select) == polarity));
155185377Ssam}
156185377Ssam
157185377Ssam/*
158185377Ssam * Configure GPIO Output lines
159185377Ssam */
160185377SsamHAL_BOOL
161188974Ssamar5210GpioCfgOutput(struct ath_hal *ah, uint32_t gpio, HAL_GPIO_MUX_TYPE type)
162185377Ssam{
163185377Ssam	HALASSERT(gpio < AR_NUM_GPIO);
164185377Ssam
165185377Ssam	OS_REG_WRITE(ah, AR_GPIOCR,
166185377Ssam		  (OS_REG_READ(ah, AR_GPIOCR) &~ AR_GPIOCR_ALL(gpio))
167185377Ssam		| AR_GPIOCR_OUT1(gpio));
168185377Ssam
169185377Ssam	return AH_TRUE;
170185377Ssam}
171185377Ssam
172185377Ssam/*
173185377Ssam * Configure GPIO Input lines
174185377Ssam */
175185377SsamHAL_BOOL
176185377Ssamar5210GpioCfgInput(struct ath_hal *ah, uint32_t gpio)
177185377Ssam{
178185377Ssam	HALASSERT(gpio < AR_NUM_GPIO);
179185377Ssam
180185377Ssam	OS_REG_WRITE(ah, AR_GPIOCR,
181185377Ssam		  (OS_REG_READ(ah, AR_GPIOCR) &~ AR_GPIOCR_ALL(gpio))
182185377Ssam		| AR_GPIOCR_IN(gpio));
183185377Ssam
184185377Ssam	return AH_TRUE;
185185377Ssam}
186185377Ssam
187185377Ssam/*
188185377Ssam * Once configured for I/O - set output lines
189185377Ssam */
190185377SsamHAL_BOOL
191185377Ssamar5210GpioSet(struct ath_hal *ah, uint32_t gpio, uint32_t val)
192185377Ssam{
193185377Ssam	uint32_t reg;
194185377Ssam
195185377Ssam	HALASSERT(gpio < AR_NUM_GPIO);
196185377Ssam
197185377Ssam	reg =  OS_REG_READ(ah, AR_GPIODO);
198185377Ssam	reg &= ~(1 << gpio);
199185377Ssam	reg |= (val&1) << gpio;
200185377Ssam
201185377Ssam	OS_REG_WRITE(ah, AR_GPIODO, reg);
202185377Ssam	return AH_TRUE;
203185377Ssam}
204185377Ssam
205185377Ssam/*
206185377Ssam * Once configured for I/O - get input lines
207185377Ssam */
208185377Ssamuint32_t
209185377Ssamar5210GpioGet(struct ath_hal *ah, uint32_t gpio)
210185377Ssam{
211185377Ssam	if (gpio < AR_NUM_GPIO) {
212185377Ssam		uint32_t val = OS_REG_READ(ah, AR_GPIODI);
213185377Ssam		val = ((val & AR_GPIOD_MASK) >> gpio) & 0x1;
214185377Ssam		return val;
215185377Ssam	} else  {
216185377Ssam		return 0xffffffff;
217185377Ssam	}
218185377Ssam}
219185377Ssam
220185377Ssam/*
221185377Ssam * Set the GPIO 0 Interrupt
222185377Ssam */
223185377Ssamvoid
224185377Ssamar5210Gpio0SetIntr(struct ath_hal *ah, u_int gpio, uint32_t ilevel)
225185377Ssam{
226185377Ssam	uint32_t val = OS_REG_READ(ah, AR_GPIOCR);
227185377Ssam
228185377Ssam	/* Clear the bits that we will modify. */
229185377Ssam	val &= ~(AR_GPIOCR_INT_SEL(gpio) | AR_GPIOCR_INT_SELH | AR_GPIOCR_INT_ENA |
230185377Ssam			AR_GPIOCR_ALL(gpio));
231185377Ssam
232185377Ssam	val |= AR_GPIOCR_INT_SEL(gpio) | AR_GPIOCR_INT_ENA;
233185377Ssam	if (ilevel)
234185377Ssam		val |= AR_GPIOCR_INT_SELH;
235185377Ssam
236185377Ssam	/* Don't need to change anything for low level interrupt. */
237185377Ssam	OS_REG_WRITE(ah, AR_GPIOCR, val);
238185377Ssam
239185377Ssam	/* Change the interrupt mask. */
240185377Ssam	ar5210SetInterrupts(ah, AH5210(ah)->ah_maskReg | HAL_INT_GPIO);
241185377Ssam}
242185377Ssam
243185377Ssam/*
244185377Ssam * Change the LED blinking pattern to correspond to the connectivity
245185377Ssam */
246185377Ssamvoid
247185377Ssamar5210SetLedState(struct ath_hal *ah, HAL_LED_STATE state)
248185377Ssam{
249185377Ssam	uint32_t val;
250185377Ssam
251185377Ssam	val = OS_REG_READ(ah, AR_PCICFG);
252185377Ssam	switch (state) {
253185377Ssam	case HAL_LED_INIT:
254185377Ssam		val &= ~(AR_PCICFG_LED_PEND | AR_PCICFG_LED_ACT);
255185377Ssam		break;
256185377Ssam	case HAL_LED_RUN:
257185377Ssam		/* normal blink when connected */
258185377Ssam		val &= ~AR_PCICFG_LED_PEND;
259185377Ssam		val |= AR_PCICFG_LED_ACT;
260185377Ssam		break;
261185377Ssam	default:
262185377Ssam		val |= AR_PCICFG_LED_PEND;
263185377Ssam		val &= ~AR_PCICFG_LED_ACT;
264185377Ssam		break;
265185377Ssam	}
266185377Ssam	OS_REG_WRITE(ah, AR_PCICFG, val);
267185377Ssam}
268185377Ssam
269185377Ssam/*
270185377Ssam * Return 1 or 2 for the corresponding antenna that is in use
271185377Ssam */
272185377Ssamu_int
273185377Ssamar5210GetDefAntenna(struct ath_hal *ah)
274185377Ssam{
275185377Ssam	uint32_t val = OS_REG_READ(ah, AR_STA_ID1);
276185377Ssam	return (val & AR_STA_ID1_DEFAULT_ANTENNA ?  2 : 1);
277185377Ssam}
278185377Ssam
279185377Ssamvoid
280185377Ssamar5210SetDefAntenna(struct ath_hal *ah, u_int antenna)
281185377Ssam{
282185377Ssam	uint32_t val = OS_REG_READ(ah, AR_STA_ID1);
283185377Ssam
284185377Ssam	if (antenna != (val & AR_STA_ID1_DEFAULT_ANTENNA ?  2 : 1)) {
285185377Ssam		/*
286185377Ssam		 * Antenna change requested, force a toggle of the default.
287185377Ssam		 */
288185377Ssam		OS_REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_DEFAULT_ANTENNA);
289185377Ssam	}
290185377Ssam}
291185377Ssam
292185377SsamHAL_ANT_SETTING
293185377Ssamar5210GetAntennaSwitch(struct ath_hal *ah)
294185377Ssam{
295185377Ssam	return HAL_ANT_VARIABLE;
296185377Ssam}
297185377Ssam
298185377SsamHAL_BOOL
299185377Ssamar5210SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings)
300185377Ssam{
301185377Ssam	/* XXX not sure how to fix antenna */
302185377Ssam	return (settings == HAL_ANT_VARIABLE);
303185377Ssam}
304185377Ssam
305185377Ssam/*
306185377Ssam * Change association related fields programmed into the hardware.
307185377Ssam * Writing a valid BSSID to the hardware effectively enables the hardware
308185377Ssam * to synchronize its TSF to the correct beacons and receive frames coming
309185377Ssam * from that BSSID. It is called by the SME JOIN operation.
310185377Ssam */
311185377Ssamvoid
312185377Ssamar5210WriteAssocid(struct ath_hal *ah, const uint8_t *bssid, uint16_t assocId)
313185377Ssam{
314185377Ssam	struct ath_hal_5210 *ahp = AH5210(ah);
315185377Ssam
316185377Ssam	/* XXX save bssid for possible re-use on reset */
317185377Ssam	OS_MEMCPY(ahp->ah_bssid, bssid, IEEE80211_ADDR_LEN);
318185377Ssam	OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid));
319185377Ssam	OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid+4) |
320185377Ssam				     ((assocId & 0x3fff)<<AR_BSS_ID1_AID_S));
321185377Ssam	if (assocId == 0)
322185377Ssam		OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_NO_PSPOLL);
323185377Ssam	else
324185377Ssam		OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_NO_PSPOLL);
325185377Ssam}
326185377Ssam
327185377Ssam/*
328185377Ssam * Get the current hardware tsf for stamlme.
329185377Ssam */
330185377Ssamuint64_t
331185377Ssamar5210GetTsf64(struct ath_hal *ah)
332185377Ssam{
333185377Ssam	uint32_t low1, low2, u32;
334185377Ssam
335185377Ssam	/* sync multi-word read */
336185377Ssam	low1 = OS_REG_READ(ah, AR_TSF_L32);
337185377Ssam	u32 = OS_REG_READ(ah, AR_TSF_U32);
338185377Ssam	low2 = OS_REG_READ(ah, AR_TSF_L32);
339185377Ssam	if (low2 < low1) {	/* roll over */
340185377Ssam		/*
341185377Ssam		 * If we are not preempted this will work.  If we are
342185377Ssam		 * then we re-reading AR_TSF_U32 does no good as the
343185377Ssam		 * low bits will be meaningless.  Likewise reading
344185377Ssam		 * L32, U32, U32, then comparing the last two reads
345185380Ssam		 * to check for rollover doesn't help if preempted--so
346185380Ssam		 * we take this approach as it costs one less PCI
347185380Ssam		 * read which can be noticeable when doing things
348185380Ssam		 * like timestamping packets in monitor mode.
349185377Ssam		 */
350185377Ssam		u32++;
351185377Ssam	}
352185377Ssam	return (((uint64_t) u32) << 32) | ((uint64_t) low2);
353185377Ssam}
354185377Ssam
355185377Ssam/*
356185377Ssam * Get the current hardware tsf for stamlme.
357185377Ssam */
358185377Ssamuint32_t
359185377Ssamar5210GetTsf32(struct ath_hal *ah)
360185377Ssam{
361185377Ssam	return OS_REG_READ(ah, AR_TSF_L32);
362185377Ssam}
363185377Ssam
364185377Ssam/*
365185377Ssam * Reset the current hardware tsf for stamlme
366185377Ssam */
367185377Ssamvoid
368185377Ssamar5210ResetTsf(struct ath_hal *ah)
369185377Ssam{
370185377Ssam	uint32_t val = OS_REG_READ(ah, AR_BEACON);
371185377Ssam
372185377Ssam	OS_REG_WRITE(ah, AR_BEACON, val | AR_BEACON_RESET_TSF);
373185377Ssam}
374185377Ssam
375185377Ssam/*
376185377Ssam * Grab a semi-random value from hardware registers - may not
377185377Ssam * change often
378185377Ssam */
379185377Ssamuint32_t
380185377Ssamar5210GetRandomSeed(struct ath_hal *ah)
381185377Ssam{
382185377Ssam	uint32_t nf;
383185377Ssam
384185377Ssam	nf = (OS_REG_READ(ah, AR_PHY_BASE + (25 << 2)) >> 19) & 0x1ff;
385185377Ssam	if (nf & 0x100)
386185377Ssam		nf = 0 - ((nf ^ 0x1ff) + 1);
387185377Ssam	return (OS_REG_READ(ah, AR_TSF_U32) ^
388185377Ssam		OS_REG_READ(ah, AR_TSF_L32) ^ nf);
389185377Ssam}
390185377Ssam
391185377Ssam/*
392185377Ssam * Detect if our card is present
393185377Ssam */
394185377SsamHAL_BOOL
395185377Ssamar5210DetectCardPresent(struct ath_hal *ah)
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	return (AH_PRIVATE(ah)->ah_macRev == (OS_REG_READ(ah, AR_SREV) & 0xff));
403185377Ssam}
404185377Ssam
405185377Ssam/*
406185377Ssam * Update MIB Counters
407185377Ssam */
408185377Ssamvoid
409185377Ssamar5210UpdateMibCounters(struct ath_hal *ah, HAL_MIB_STATS *stats)
410185377Ssam{
411185377Ssam	stats->ackrcv_bad += OS_REG_READ(ah, AR_ACK_FAIL);
412185377Ssam	stats->rts_bad	  += OS_REG_READ(ah, AR_RTS_FAIL);
413185377Ssam	stats->fcs_bad	  += OS_REG_READ(ah, AR_FCS_FAIL);
414185377Ssam	stats->rts_good	  += OS_REG_READ(ah, AR_RTS_OK);
415185377Ssam	stats->beacons	  += OS_REG_READ(ah, AR_BEACON_CNT);
416185377Ssam}
417185377Ssam
418185377SsamHAL_BOOL
419185377Ssamar5210SetSifsTime(struct ath_hal *ah, u_int us)
420185377Ssam{
421185377Ssam	struct ath_hal_5210 *ahp = AH5210(ah);
422185377Ssam
423185377Ssam	if (us > ath_hal_mac_usec(ah, 0x7ff)) {
424185377Ssam		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad SIFS time %u\n",
425185377Ssam		    __func__, us);
426185377Ssam		ahp->ah_sifstime = (u_int) -1;	/* restore default handling */
427185377Ssam		return AH_FALSE;
428185377Ssam	} else {
429185377Ssam		/* convert to system clocks */
430185377Ssam		OS_REG_RMW_FIELD(ah, AR_IFS0, AR_IFS0_SIFS,
431185377Ssam		    ath_hal_mac_clks(ah, us));
432185377Ssam		ahp->ah_sifstime = us;
433185377Ssam		return AH_TRUE;
434185377Ssam	}
435185377Ssam}
436185377Ssam
437185377Ssamu_int
438185377Ssamar5210GetSifsTime(struct ath_hal *ah)
439185377Ssam{
440185377Ssam	u_int clks = OS_REG_READ(ah, AR_IFS0) & 0x7ff;
441185377Ssam	return ath_hal_mac_usec(ah, clks);	/* convert from system clocks */
442185377Ssam}
443185377Ssam
444185377SsamHAL_BOOL
445185377Ssamar5210SetSlotTime(struct ath_hal *ah, u_int us)
446185377Ssam{
447185377Ssam	struct ath_hal_5210 *ahp = AH5210(ah);
448185377Ssam
449185377Ssam	if (us < HAL_SLOT_TIME_9 || us > ath_hal_mac_usec(ah, 0xffff)) {
450185377Ssam		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad slot time %u\n",
451185377Ssam		    __func__, us);
452185377Ssam		ahp->ah_slottime = (u_int) -1;	/* restore default handling */
453185377Ssam		return AH_FALSE;
454185377Ssam	} else {
455185377Ssam		/* convert to system clocks */
456185377Ssam		OS_REG_WRITE(ah, AR_SLOT_TIME, ath_hal_mac_clks(ah, us));
457185377Ssam		ahp->ah_slottime = us;
458185377Ssam		return AH_TRUE;
459185377Ssam	}
460185377Ssam}
461185377Ssam
462185377Ssamu_int
463185377Ssamar5210GetSlotTime(struct ath_hal *ah)
464185377Ssam{
465185377Ssam	u_int clks = OS_REG_READ(ah, AR_SLOT_TIME) & 0xffff;
466185377Ssam	return ath_hal_mac_usec(ah, clks);	/* convert from system clocks */
467185377Ssam}
468185377Ssam
469185377SsamHAL_BOOL
470185377Ssamar5210SetAckTimeout(struct ath_hal *ah, u_int us)
471185377Ssam{
472185377Ssam	struct ath_hal_5210 *ahp = AH5210(ah);
473185377Ssam
474185377Ssam	if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) {
475185377Ssam		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad ack timeout %u\n",
476185377Ssam		    __func__, us);
477185377Ssam		ahp->ah_acktimeout = (u_int) -1; /* restore default handling */
478185377Ssam		return AH_FALSE;
479185377Ssam	} else {
480185377Ssam		/* convert to system clocks */
481185377Ssam		OS_REG_RMW_FIELD(ah, AR_TIME_OUT,
482185377Ssam			AR_TIME_OUT_ACK, ath_hal_mac_clks(ah, us));
483185377Ssam		ahp->ah_acktimeout = us;
484185377Ssam		return AH_TRUE;
485185377Ssam	}
486185377Ssam}
487185377Ssam
488185377Ssamu_int
489185377Ssamar5210GetAckTimeout(struct ath_hal *ah)
490185377Ssam{
491185377Ssam	u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_ACK);
492185377Ssam	return ath_hal_mac_usec(ah, clks);	/* convert from system clocks */
493185377Ssam}
494185377Ssam
495185377Ssamu_int
496185377Ssamar5210GetAckCTSRate(struct ath_hal *ah)
497185377Ssam{
498185377Ssam	return ((AH5210(ah)->ah_staId1Defaults & AR_STA_ID1_ACKCTS_6MB) == 0);
499185377Ssam}
500185377Ssam
501185377SsamHAL_BOOL
502185377Ssamar5210SetAckCTSRate(struct ath_hal *ah, u_int high)
503185377Ssam{
504185377Ssam	struct ath_hal_5210 *ahp = AH5210(ah);
505185377Ssam
506185377Ssam	if (high) {
507185377Ssam		OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB);
508185377Ssam		ahp->ah_staId1Defaults &= ~AR_STA_ID1_ACKCTS_6MB;
509185377Ssam	} else {
510185377Ssam		OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB);
511185377Ssam		ahp->ah_staId1Defaults |= AR_STA_ID1_ACKCTS_6MB;
512185377Ssam	}
513185377Ssam	return AH_TRUE;
514185377Ssam}
515185377Ssam
516185377SsamHAL_BOOL
517185377Ssamar5210SetCTSTimeout(struct ath_hal *ah, u_int us)
518185377Ssam{
519185377Ssam	struct ath_hal_5210 *ahp = AH5210(ah);
520185377Ssam
521185377Ssam	if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) {
522185377Ssam		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad cts timeout %u\n",
523185377Ssam		    __func__, us);
524185377Ssam		ahp->ah_ctstimeout = (u_int) -1; /* restore default handling */
525185377Ssam		return AH_FALSE;
526185377Ssam	} else {
527185377Ssam		/* convert to system clocks */
528185377Ssam		OS_REG_RMW_FIELD(ah, AR_TIME_OUT,
529185377Ssam			AR_TIME_OUT_CTS, ath_hal_mac_clks(ah, us));
530185377Ssam		ahp->ah_ctstimeout = us;
531185377Ssam		return AH_TRUE;
532185377Ssam	}
533185377Ssam}
534185377Ssam
535185377Ssamu_int
536185377Ssamar5210GetCTSTimeout(struct ath_hal *ah)
537185377Ssam{
538185377Ssam	u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_CTS);
539185377Ssam	return ath_hal_mac_usec(ah, clks);	/* convert from system clocks */
540185377Ssam}
541185377Ssam
542185377SsamHAL_BOOL
543185377Ssamar5210SetDecompMask(struct ath_hal *ah, uint16_t keyidx, int en)
544185377Ssam{
545185377Ssam	/* nothing to do */
546185377Ssam        return AH_TRUE;
547185377Ssam}
548185377Ssam
549185377Ssamvoid
550185377Ssamar5210SetCoverageClass(struct ath_hal *ah, uint8_t coverageclass, int now)
551185377Ssam{
552185377Ssam}
553185377Ssam
554185377Ssam/*
555185377Ssam * Control Adaptive Noise Immunity Parameters
556185377Ssam */
557185377SsamHAL_BOOL
558185377Ssamar5210AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param)
559185377Ssam{
560185377Ssam	return AH_FALSE;
561185377Ssam}
562185377Ssam
563185377Ssamvoid
564217684Sadrianar5210RxMonitor(struct ath_hal *ah, const HAL_NODE_STATS *stats,
565187831Ssam	const struct ieee80211_channel *chan)
566185377Ssam{
567185377Ssam}
568185377Ssam
569185377Ssamvoid
570217684Sadrianar5210AniPoll(struct ath_hal *ah, const struct ieee80211_channel *chan)
571217684Sadrian{
572217684Sadrian}
573217684Sadrian
574217684Sadrianvoid
575185377Ssamar5210MibEvent(struct ath_hal *ah, const HAL_NODE_STATS *stats)
576185377Ssam{
577185377Ssam}
578185377Ssam
579185377SsamHAL_STATUS
580185377Ssamar5210GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
581185377Ssam	uint32_t capability, uint32_t *result)
582185377Ssam{
583185377Ssam
584185377Ssam	switch (type) {
585185377Ssam	case HAL_CAP_CIPHER:		/* cipher handled in hardware */
586243317Sadrian#if 0
587185377Ssam		return (capability == HAL_CIPHER_WEP ? HAL_OK : HAL_ENOTSUPP);
588243317Sadrian#else
589243317Sadrian		return HAL_ENOTSUPP;
590243317Sadrian#endif
591185377Ssam	default:
592185377Ssam		return ath_hal_getcapability(ah, type, capability, result);
593185377Ssam	}
594185377Ssam}
595185377Ssam
596185377SsamHAL_BOOL
597185377Ssamar5210SetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
598185377Ssam	uint32_t capability, uint32_t setting, HAL_STATUS *status)
599185377Ssam{
600185377Ssam
601185377Ssam	switch (type) {
602185377Ssam	case HAL_CAP_DIAG:		/* hardware diagnostic support */
603185377Ssam		/*
604185377Ssam		 * NB: could split this up into virtual capabilities,
605185377Ssam		 *     (e.g. 1 => ACK, 2 => CTS, etc.) but it hardly
606185377Ssam		 *     seems worth the additional complexity.
607185377Ssam		 */
608185377Ssam#ifdef AH_DEBUG
609185377Ssam		AH_PRIVATE(ah)->ah_diagreg = setting;
610185377Ssam#else
611185377Ssam		AH_PRIVATE(ah)->ah_diagreg = setting & 0x6;	/* ACK+CTS */
612185377Ssam#endif
613243317Sadrian		ar5210UpdateDiagReg(ah, AH_PRIVATE(ah)->ah_diagreg);
614185377Ssam		return AH_TRUE;
615185377Ssam	case HAL_CAP_RXORN_FATAL:	/* HAL_INT_RXORN treated as fatal  */
616185377Ssam		return AH_FALSE;	/* NB: disallow */
617185377Ssam	default:
618185377Ssam		return ath_hal_setcapability(ah, type, capability,
619185377Ssam			setting, status);
620185377Ssam	}
621185377Ssam}
622185377Ssam
623185377SsamHAL_BOOL
624185377Ssamar5210GetDiagState(struct ath_hal *ah, int request,
625185377Ssam	const void *args, uint32_t argsize,
626185377Ssam	void **result, uint32_t *resultsize)
627185377Ssam{
628185377Ssam#ifdef AH_PRIVATE_DIAG
629185377Ssam	uint32_t pcicfg;
630185377Ssam	HAL_BOOL ok;
631185377Ssam
632185377Ssam	switch (request) {
633185377Ssam	case HAL_DIAG_EEPROM:
634185377Ssam		/* XXX */
635185377Ssam		break;
636185377Ssam	case HAL_DIAG_EEREAD:
637185377Ssam		if (argsize != sizeof(uint16_t))
638185377Ssam			return AH_FALSE;
639185377Ssam		pcicfg = OS_REG_READ(ah, AR_PCICFG);
640185377Ssam		OS_REG_WRITE(ah, AR_PCICFG, pcicfg | AR_PCICFG_EEPROMSEL);
641185377Ssam		ok = ath_hal_eepromRead(ah, *(const uint16_t *)args, *result);
642185377Ssam		OS_REG_WRITE(ah, AR_PCICFG, pcicfg);
643185377Ssam		if (ok)
644185377Ssam			*resultsize = sizeof(uint16_t);
645185377Ssam		return ok;
646185377Ssam	}
647185377Ssam#endif
648185377Ssam	return ath_hal_getdiagstate(ah, request,
649185377Ssam		args, argsize, result, resultsize);
650185377Ssam}
651234873Sadrian
652234873Sadrian/*
653234873Sadrian * Return what percentage of the extension channel is busy.
654234873Sadrian * This is always disabled for AR5210 series NICs.
655234873Sadrian */
656234873Sadrianuint32_t
657234873Sadrianar5210Get11nExtBusy(struct ath_hal *ah)
658234873Sadrian{
659234873Sadrian
660234873Sadrian	return (0);
661234873Sadrian}
662234873Sadrian
663234873Sadrian/*
664234873Sadrian * There's no channel survey support for the AR5210.
665234873Sadrian */
666234873SadrianHAL_BOOL
667234873Sadrianar5210GetMibCycleCounts(struct ath_hal *ah, HAL_SURVEY_SAMPLE *hsample)
668234873Sadrian{
669234873Sadrian
670234873Sadrian	return (AH_FALSE);
671234873Sadrian}
672235206Sadrian
673235206Sadrianvoid
674247286Sadrianar5210SetChainMasks(struct ath_hal *ah, uint32_t txchainmask,
675247286Sadrian    uint32_t rxchainmask)
676247286Sadrian{
677247286Sadrian}
678247286Sadrian
679247286Sadrianvoid
680235206Sadrianar5210EnableDfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe)
681235206Sadrian{
682235206Sadrian}
683235206Sadrian
684235206Sadrianvoid
685235206Sadrianar5210GetDfsThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe)
686235206Sadrian{
687235206Sadrian}
688243317Sadrian
689243317Sadrian/*
690243317Sadrian * Update the diagnostic register.
691243317Sadrian *
692243317Sadrian * This merges in the diagnostic register setting with the default
693243317Sadrian * value, which may or may not involve disabling hardware encryption.
694243317Sadrian */
695243317Sadrianvoid
696243317Sadrianar5210UpdateDiagReg(struct ath_hal *ah, uint32_t val)
697243317Sadrian{
698243317Sadrian
699243317Sadrian	/* Disable all hardware encryption */
700243317Sadrian	val |= AR_DIAG_SW_DIS_CRYPTO;
701243317Sadrian	OS_REG_WRITE(ah, AR_DIAG_SW, val);
702243317Sadrian}
703