ar5211_attach.c revision 235972
1/*
2 * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
3 * Copyright (c) 2002-2006 Atheros Communications, Inc.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 *
17 * $FreeBSD: head/sys/dev/ath/ath_hal/ar5211/ar5211_attach.c 235972 2012-05-25 05:01:27Z adrian $
18 */
19#include "opt_ah.h"
20
21#include "ah.h"
22#include "ah_internal.h"
23#include "ah_devid.h"
24
25#include "ar5211/ar5211.h"
26#include "ar5211/ar5211reg.h"
27#include "ar5211/ar5211phy.h"
28
29#include "ah_eeprom_v3.h"
30
31static HAL_BOOL ar5211GetChannelEdges(struct ath_hal *ah,
32		uint16_t flags, uint16_t *low, uint16_t *high);
33static HAL_BOOL ar5211GetChipPowerLimits(struct ath_hal *ah,
34		struct ieee80211_channel *chan);
35
36static void ar5211ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore,
37		HAL_BOOL power_off);
38static void ar5211DisablePCIE(struct ath_hal *ah);
39
40static const struct ath_hal_private ar5211hal = {{
41	.ah_magic			= AR5211_MAGIC,
42
43	.ah_getRateTable		= ar5211GetRateTable,
44	.ah_detach			= ar5211Detach,
45
46	/* Reset Functions */
47	.ah_reset			= ar5211Reset,
48	.ah_phyDisable			= ar5211PhyDisable,
49	.ah_disable			= ar5211Disable,
50	.ah_configPCIE			= ar5211ConfigPCIE,
51	.ah_disablePCIE			= ar5211DisablePCIE,
52	.ah_setPCUConfig		= ar5211SetPCUConfig,
53	.ah_perCalibration		= ar5211PerCalibration,
54	.ah_perCalibrationN		= ar5211PerCalibrationN,
55	.ah_resetCalValid		= ar5211ResetCalValid,
56	.ah_setTxPowerLimit		= ar5211SetTxPowerLimit,
57	.ah_getChanNoise		= ath_hal_getChanNoise,
58
59	/* Transmit functions */
60	.ah_updateTxTrigLevel		= ar5211UpdateTxTrigLevel,
61	.ah_setupTxQueue		= ar5211SetupTxQueue,
62	.ah_setTxQueueProps             = ar5211SetTxQueueProps,
63	.ah_getTxQueueProps             = ar5211GetTxQueueProps,
64	.ah_releaseTxQueue		= ar5211ReleaseTxQueue,
65	.ah_resetTxQueue		= ar5211ResetTxQueue,
66	.ah_getTxDP			= ar5211GetTxDP,
67	.ah_setTxDP			= ar5211SetTxDP,
68	.ah_numTxPending		= ar5211NumTxPending,
69	.ah_startTxDma			= ar5211StartTxDma,
70	.ah_stopTxDma			= ar5211StopTxDma,
71	.ah_setupTxDesc			= ar5211SetupTxDesc,
72	.ah_setupXTxDesc		= ar5211SetupXTxDesc,
73	.ah_fillTxDesc			= ar5211FillTxDesc,
74	.ah_procTxDesc			= ar5211ProcTxDesc,
75	.ah_getTxIntrQueue		= ar5211GetTxIntrQueue,
76	.ah_reqTxIntrDesc 		= ar5211IntrReqTxDesc,
77	.ah_getTxCompletionRates	= ar5211GetTxCompletionRates,
78
79	/* RX Functions */
80	.ah_getRxDP			= ar5211GetRxDP,
81	.ah_setRxDP			= ar5211SetRxDP,
82	.ah_enableReceive		= ar5211EnableReceive,
83	.ah_stopDmaReceive		= ar5211StopDmaReceive,
84	.ah_startPcuReceive		= ar5211StartPcuReceive,
85	.ah_stopPcuReceive		= ar5211StopPcuReceive,
86	.ah_setMulticastFilter		= ar5211SetMulticastFilter,
87	.ah_setMulticastFilterIndex	= ar5211SetMulticastFilterIndex,
88	.ah_clrMulticastFilterIndex	= ar5211ClrMulticastFilterIndex,
89	.ah_getRxFilter			= ar5211GetRxFilter,
90	.ah_setRxFilter			= ar5211SetRxFilter,
91	.ah_setupRxDesc			= ar5211SetupRxDesc,
92	.ah_procRxDesc			= ar5211ProcRxDesc,
93	.ah_rxMonitor			= ar5211RxMonitor,
94	.ah_aniPoll			= ar5211AniPoll,
95	.ah_procMibEvent		= ar5211MibEvent,
96
97	/* Misc Functions */
98	.ah_getCapability		= ar5211GetCapability,
99	.ah_setCapability		= ar5211SetCapability,
100	.ah_getDiagState		= ar5211GetDiagState,
101	.ah_getMacAddress		= ar5211GetMacAddress,
102	.ah_setMacAddress		= ar5211SetMacAddress,
103	.ah_getBssIdMask		= ar5211GetBssIdMask,
104	.ah_setBssIdMask		= ar5211SetBssIdMask,
105	.ah_setRegulatoryDomain		= ar5211SetRegulatoryDomain,
106	.ah_setLedState			= ar5211SetLedState,
107	.ah_writeAssocid		= ar5211WriteAssocid,
108	.ah_gpioCfgInput		= ar5211GpioCfgInput,
109	.ah_gpioCfgOutput		= ar5211GpioCfgOutput,
110	.ah_gpioGet			= ar5211GpioGet,
111	.ah_gpioSet			= ar5211GpioSet,
112	.ah_gpioSetIntr			= ar5211GpioSetIntr,
113	.ah_getTsf32			= ar5211GetTsf32,
114	.ah_getTsf64			= ar5211GetTsf64,
115	.ah_resetTsf			= ar5211ResetTsf,
116	.ah_detectCardPresent		= ar5211DetectCardPresent,
117	.ah_updateMibCounters		= ar5211UpdateMibCounters,
118	.ah_getRfGain			= ar5211GetRfgain,
119	.ah_getDefAntenna		= ar5211GetDefAntenna,
120	.ah_setDefAntenna		= ar5211SetDefAntenna,
121	.ah_getAntennaSwitch		= ar5211GetAntennaSwitch,
122	.ah_setAntennaSwitch		= ar5211SetAntennaSwitch,
123	.ah_setSifsTime			= ar5211SetSifsTime,
124	.ah_getSifsTime			= ar5211GetSifsTime,
125	.ah_setSlotTime			= ar5211SetSlotTime,
126	.ah_getSlotTime			= ar5211GetSlotTime,
127	.ah_setAckTimeout		= ar5211SetAckTimeout,
128	.ah_getAckTimeout		= ar5211GetAckTimeout,
129	.ah_setAckCTSRate		= ar5211SetAckCTSRate,
130	.ah_getAckCTSRate		= ar5211GetAckCTSRate,
131	.ah_setCTSTimeout		= ar5211SetCTSTimeout,
132	.ah_getCTSTimeout		= ar5211GetCTSTimeout,
133	.ah_setDecompMask		= ar5211SetDecompMask,
134	.ah_setCoverageClass		= ar5211SetCoverageClass,
135	.ah_get11nExtBusy		= ar5211Get11nExtBusy,
136	.ah_getMibCycleCounts		= ar5211GetMibCycleCounts,
137	.ah_enableDfs			= ar5211EnableDfs,
138	.ah_getDfsThresh		= ar5211GetDfsThresh,
139	/* XXX procRadarEvent */
140	/* XXX isFastClockEnabled */
141
142	/* Key Cache Functions */
143	.ah_getKeyCacheSize		= ar5211GetKeyCacheSize,
144	.ah_resetKeyCacheEntry		= ar5211ResetKeyCacheEntry,
145	.ah_isKeyCacheEntryValid	= ar5211IsKeyCacheEntryValid,
146	.ah_setKeyCacheEntry		= ar5211SetKeyCacheEntry,
147	.ah_setKeyCacheEntryMac		= ar5211SetKeyCacheEntryMac,
148
149	/* Power Management Functions */
150	.ah_setPowerMode		= ar5211SetPowerMode,
151	.ah_getPowerMode		= ar5211GetPowerMode,
152
153	/* Beacon Functions */
154	.ah_setBeaconTimers		= ar5211SetBeaconTimers,
155	.ah_beaconInit			= ar5211BeaconInit,
156	.ah_setStationBeaconTimers	= ar5211SetStaBeaconTimers,
157	.ah_resetStationBeaconTimers	= ar5211ResetStaBeaconTimers,
158	.ah_getNextTBTT			= ar5211GetNextTBTT,
159
160	/* Interrupt Functions */
161	.ah_isInterruptPending		= ar5211IsInterruptPending,
162	.ah_getPendingInterrupts	= ar5211GetPendingInterrupts,
163	.ah_getInterrupts		= ar5211GetInterrupts,
164	.ah_setInterrupts		= ar5211SetInterrupts },
165
166	.ah_getChannelEdges		= ar5211GetChannelEdges,
167	.ah_getWirelessModes		= ar5211GetWirelessModes,
168	.ah_eepromRead			= ar5211EepromRead,
169#ifdef AH_SUPPORT_WRITE_EEPROM
170	.ah_eepromWrite			= ar5211EepromWrite,
171#endif
172	.ah_getChipPowerLimits		= ar5211GetChipPowerLimits,
173};
174
175static HAL_BOOL ar5211ChipTest(struct ath_hal *);
176static HAL_BOOL ar5211FillCapabilityInfo(struct ath_hal *ah);
177
178/*
179 * Return the revsion id for the radio chip.  This
180 * fetched via the PHY.
181 */
182static uint32_t
183ar5211GetRadioRev(struct ath_hal *ah)
184{
185	uint32_t val;
186	int i;
187
188	OS_REG_WRITE(ah, (AR_PHY_BASE + (0x34 << 2)), 0x00001c16);
189	for (i = 0; i < 8; i++)
190		OS_REG_WRITE(ah, (AR_PHY_BASE + (0x20 << 2)), 0x00010000);
191	val = (OS_REG_READ(ah, AR_PHY_BASE + (256 << 2)) >> 24) & 0xff;
192	val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4);
193	return ath_hal_reverseBits(val, 8);
194}
195
196/*
197 * Attach for an AR5211 part.
198 */
199static struct ath_hal *
200ar5211Attach(uint16_t devid, HAL_SOFTC sc,
201	HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata,
202	HAL_STATUS *status)
203{
204#define	N(a)	(sizeof(a)/sizeof(a[0]))
205	struct ath_hal_5211 *ahp;
206	struct ath_hal *ah;
207	uint32_t val;
208	uint16_t eeval;
209	HAL_STATUS ecode;
210
211	HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n",
212	    __func__, sc, (void*) st, (void*) sh);
213
214	/* NB: memory is returned zero'd */
215	ahp = ath_hal_malloc(sizeof (struct ath_hal_5211));
216	if (ahp == AH_NULL) {
217		HALDEBUG(AH_NULL, HAL_DEBUG_ANY,
218		    "%s: cannot allocate memory for state block\n", __func__);
219		ecode = HAL_ENOMEM;
220		goto bad;
221	}
222	ah = &ahp->ah_priv.h;
223	/* set initial values */
224	OS_MEMCPY(&ahp->ah_priv, &ar5211hal, sizeof(struct ath_hal_private));
225	ah->ah_sc = sc;
226	ah->ah_st = st;
227	ah->ah_sh = sh;
228
229	ah->ah_devid = devid;			/* NB: for AH_DEBUG_ALQ */
230	AH_PRIVATE(ah)->ah_devid = devid;
231	AH_PRIVATE(ah)->ah_subvendorid = 0;	/* XXX */
232
233	AH_PRIVATE(ah)->ah_powerLimit = MAX_RATE_POWER;
234	AH_PRIVATE(ah)->ah_tpScale = HAL_TP_SCALE_MAX;	/* no scaling */
235
236	ahp->ah_diversityControl = HAL_ANT_VARIABLE;
237	ahp->ah_staId1Defaults = 0;
238	ahp->ah_rssiThr = INIT_RSSI_THR;
239	ahp->ah_sifstime = (u_int) -1;
240	ahp->ah_slottime = (u_int) -1;
241	ahp->ah_acktimeout = (u_int) -1;
242	ahp->ah_ctstimeout = (u_int) -1;
243
244	if (!ar5211ChipReset(ah, AH_NULL)) {	/* reset chip */
245		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__);
246		ecode = HAL_EIO;
247		goto bad;
248	}
249	if (AH_PRIVATE(ah)->ah_devid == AR5211_FPGA11B) {
250		/* set it back to OFDM mode to be able to read analog rev id */
251		OS_REG_WRITE(ah, AR5211_PHY_MODE, AR5211_PHY_MODE_OFDM);
252		OS_REG_WRITE(ah, AR_PHY_PLL_CTL, AR_PHY_PLL_CTL_44);
253		OS_DELAY(1000);
254	}
255
256	/* Read Revisions from Chips */
257	val = OS_REG_READ(ah, AR_SREV) & AR_SREV_ID_M;
258	AH_PRIVATE(ah)->ah_macVersion = val >> AR_SREV_ID_S;
259	AH_PRIVATE(ah)->ah_macRev = val & AR_SREV_REVISION_M;
260
261	if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_MAUI_2 ||
262	    AH_PRIVATE(ah)->ah_macVersion > AR_SREV_VERSION_OAHU) {
263		HALDEBUG(ah, HAL_DEBUG_ANY,
264		    "%s: Mac Chip Rev 0x%x is not supported by this driver\n",
265		    __func__, AH_PRIVATE(ah)->ah_macVersion);
266		ecode = HAL_ENOTSUPP;
267		goto bad;
268	}
269
270	AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID);
271
272	if (!ar5211ChipTest(ah)) {
273		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n",
274		    __func__);
275		ecode = HAL_ESELFTEST;
276		goto bad;
277	}
278
279	/* Set correct Baseband to analog shift setting to access analog chips. */
280	if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_OAHU) {
281		OS_REG_WRITE(ah, AR_PHY_BASE, 0x00000007);
282	} else {
283		OS_REG_WRITE(ah, AR_PHY_BASE, 0x00000047);
284	}
285	OS_DELAY(2000);
286
287	/* Read Radio Chip Rev Extract */
288	AH_PRIVATE(ah)->ah_analog5GhzRev = ar5211GetRadioRev(ah);
289	if ((AH_PRIVATE(ah)->ah_analog5GhzRev & 0xf0) != RAD5_SREV_MAJOR) {
290		HALDEBUG(ah, HAL_DEBUG_ANY,
291		    "%s: 5G Radio Chip Rev 0x%02X is not supported by this "
292		    "driver\n", __func__, AH_PRIVATE(ah)->ah_analog5GhzRev);
293		ecode = HAL_ENOTSUPP;
294		goto bad;
295	}
296
297	val = (OS_REG_READ(ah, AR_PCICFG) & AR_PCICFG_EEPROM_SIZE_M) >>
298               AR_PCICFG_EEPROM_SIZE_S;
299	if (val != AR_PCICFG_EEPROM_SIZE_16K) {
300		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unsupported EEPROM size "
301		    "%u (0x%x) found\n", __func__, val, val);
302		ecode = HAL_EESIZE;
303		goto bad;
304	}
305	ecode = ath_hal_legacyEepromAttach(ah);
306	if (ecode != HAL_OK) {
307		goto bad;
308	}
309
310        /* If Bmode and AR5211, verify 2.4 analog exists */
311	if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_OAHU &&
312	    ath_hal_eepromGetFlag(ah, AR_EEP_BMODE)) {
313		/* Set correct Baseband to analog shift setting to access analog chips. */
314		OS_REG_WRITE(ah, AR_PHY_BASE, 0x00004007);
315		OS_DELAY(2000);
316		AH_PRIVATE(ah)->ah_analog2GhzRev = ar5211GetRadioRev(ah);
317
318		/* Set baseband for 5GHz chip */
319		OS_REG_WRITE(ah, AR_PHY_BASE, 0x00000007);
320		OS_DELAY(2000);
321		if ((AH_PRIVATE(ah)->ah_analog2GhzRev & 0xF0) != RAD2_SREV_MAJOR) {
322			HALDEBUG(ah, HAL_DEBUG_ANY,
323			    "%s: 2G Radio Chip Rev 0x%x is not supported by "
324			    "this driver\n", __func__,
325			    AH_PRIVATE(ah)->ah_analog2GhzRev);
326			ecode = HAL_ENOTSUPP;
327			goto bad;
328		}
329	} else {
330		ath_hal_eepromSet(ah, AR_EEP_BMODE, AH_FALSE);
331        }
332
333	ecode = ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, &eeval);
334	if (ecode != HAL_OK) {
335		HALDEBUG(ah, HAL_DEBUG_ANY,
336		    "%s: cannot read regulatory domain from EEPROM\n",
337		    __func__);
338		goto bad;
339        }
340	AH_PRIVATE(ah)->ah_currentRD = eeval;
341	AH_PRIVATE(ah)->ah_getNfAdjust = ar5211GetNfAdjust;
342
343	/*
344	 * Got everything we need now to setup the capabilities.
345	 */
346	(void) ar5211FillCapabilityInfo(ah);
347
348	/* Initialize gain ladder thermal calibration structure */
349	ar5211InitializeGainValues(ah);
350
351	ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr);
352	if (ecode != HAL_OK) {
353		HALDEBUG(ah, HAL_DEBUG_ANY,
354		    "%s: error getting mac address from EEPROM\n", __func__);
355		goto bad;
356        }
357
358	HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__);
359
360	return ah;
361bad:
362	if (ahp)
363		ar5211Detach((struct ath_hal *) ahp);
364	if (status)
365		*status = ecode;
366	return AH_NULL;
367#undef N
368}
369
370void
371ar5211Detach(struct ath_hal *ah)
372{
373	HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s:\n", __func__);
374
375	HALASSERT(ah != AH_NULL);
376	HALASSERT(ah->ah_magic == AR5211_MAGIC);
377
378	ath_hal_eepromDetach(ah);
379	ath_hal_free(ah);
380}
381
382static HAL_BOOL
383ar5211ChipTest(struct ath_hal *ah)
384{
385	uint32_t regAddr[2] = { AR_STA_ID0, AR_PHY_BASE+(8 << 2) };
386	uint32_t regHold[2];
387	uint32_t patternData[4] =
388	    { 0x55555555, 0xaaaaaaaa, 0x66666666, 0x99999999 };
389	int i, j;
390
391	/* Test PHY & MAC registers */
392	for (i = 0; i < 2; i++) {
393		uint32_t addr = regAddr[i];
394		uint32_t wrData, rdData;
395
396		regHold[i] = OS_REG_READ(ah, addr);
397		for (j = 0; j < 0x100; j++) {
398			wrData = (j << 16) | j;
399			OS_REG_WRITE(ah, addr, wrData);
400			rdData = OS_REG_READ(ah, addr);
401			if (rdData != wrData) {
402				HALDEBUG(ah, HAL_DEBUG_ANY,
403"%s: address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",
404				__func__, addr, wrData, rdData);
405				return AH_FALSE;
406			}
407		}
408		for (j = 0; j < 4; j++) {
409			wrData = patternData[j];
410			OS_REG_WRITE(ah, addr, wrData);
411			rdData = OS_REG_READ(ah, addr);
412			if (wrData != rdData) {
413				HALDEBUG(ah, HAL_DEBUG_ANY,
414"%s: address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",
415					__func__, addr, wrData, rdData);
416				return AH_FALSE;
417			}
418		}
419		OS_REG_WRITE(ah, regAddr[i], regHold[i]);
420	}
421	OS_DELAY(100);
422	return AH_TRUE;
423}
424
425/*
426 * Store the channel edges for the requested operational mode
427 */
428static HAL_BOOL
429ar5211GetChannelEdges(struct ath_hal *ah,
430	uint16_t flags, uint16_t *low, uint16_t *high)
431{
432	if (flags & IEEE80211_CHAN_5GHZ) {
433		*low = 4920;
434		*high = 6100;
435		return AH_TRUE;
436	}
437	if (flags & IEEE80211_CHAN_2GHZ &&
438	    ath_hal_eepromGetFlag(ah, AR_EEP_BMODE)) {
439		*low = 2312;
440		*high = 2732;
441		return AH_TRUE;
442	}
443	return AH_FALSE;
444}
445
446static HAL_BOOL
447ar5211GetChipPowerLimits(struct ath_hal *ah, struct ieee80211_channel *chan)
448{
449	/* XXX fill in, this is just a placeholder */
450	HALDEBUG(ah, HAL_DEBUG_ATTACH,
451	    "%s: no min/max power for %u/0x%x\n",
452	    __func__, chan->ic_freq, chan->ic_flags);
453	chan->ic_maxpower = MAX_RATE_POWER;
454	chan->ic_minpower = 0;
455	return AH_TRUE;
456}
457
458static void
459ar5211ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore, HAL_BOOL power_off)
460{
461}
462
463static void
464ar5211DisablePCIE(struct ath_hal *ah)
465{
466}
467
468/*
469 * Fill all software cached or static hardware state information.
470 */
471static HAL_BOOL
472ar5211FillCapabilityInfo(struct ath_hal *ah)
473{
474	struct ath_hal_private *ahpriv = AH_PRIVATE(ah);
475	HAL_CAPABILITIES *pCap = &ahpriv->ah_caps;
476
477	/* Construct wireless mode from EEPROM */
478	pCap->halWirelessModes = 0;
479	if (ath_hal_eepromGetFlag(ah, AR_EEP_AMODE)) {
480		pCap->halWirelessModes |= HAL_MODE_11A;
481		if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO5DISABLE))
482			pCap->halWirelessModes |= HAL_MODE_TURBO;
483	}
484	if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE))
485		pCap->halWirelessModes |= HAL_MODE_11B;
486
487	pCap->halLow2GhzChan = 2312;
488	pCap->halHigh2GhzChan = 2732;
489	pCap->halLow5GhzChan = 4920;
490	pCap->halHigh5GhzChan = 6100;
491
492	pCap->halChanSpreadSupport = AH_TRUE;
493	pCap->halSleepAfterBeaconBroken = AH_TRUE;
494	pCap->halPSPollBroken = AH_TRUE;
495	pCap->halVEOLSupport = AH_TRUE;
496
497	pCap->halTotalQueues = HAL_NUM_TX_QUEUES;
498	pCap->halKeyCacheSize = 128;
499
500	/* XXX not needed */
501	pCap->halChanHalfRate = AH_FALSE;
502	pCap->halChanQuarterRate = AH_FALSE;
503
504	/*
505	 * RSSI uses the combined field; some 11n NICs may use
506	 * the control chain RSSI.
507	 */
508	pCap->halUseCombinedRadarRssi = AH_TRUE;
509
510	if (ath_hal_eepromGetFlag(ah, AR_EEP_RFKILL) &&
511	    ath_hal_eepromGet(ah, AR_EEP_RFSILENT, &ahpriv->ah_rfsilent) == HAL_OK) {
512		/* NB: enabled by default */
513		ahpriv->ah_rfkillEnabled = AH_TRUE;
514		pCap->halRfSilentSupport = AH_TRUE;
515	}
516
517	pCap->halTstampPrecision = 13;
518	pCap->halIntrMask = HAL_INT_COMMON
519			| HAL_INT_RX
520			| HAL_INT_TX
521			| HAL_INT_FATAL
522			| HAL_INT_BNR
523			| HAL_INT_TIM
524			;
525
526	pCap->hal4kbSplitTransSupport = AH_TRUE;
527	pCap->halHasRxSelfLinkedTail = AH_TRUE;
528
529	/* XXX might be ok w/ some chip revs */
530	ahpriv->ah_rxornIsFatal = AH_TRUE;
531	return AH_TRUE;
532}
533
534static const char*
535ar5211Probe(uint16_t vendorid, uint16_t devid)
536{
537	if (vendorid == ATHEROS_VENDOR_ID) {
538		if (devid == AR5211_DEVID || devid == AR5311_DEVID ||
539		    devid == AR5211_DEFAULT)
540			return "Atheros 5211";
541		if (devid == AR5211_FPGA11B)
542			return "Atheros 5211 (FPGA)";
543	}
544	return AH_NULL;
545}
546AH_CHIP(AR5211, ar5211Probe, ar5211Attach);
547