Remove empty DragonFly CVS IDs.
[dragonfly.git] / sys / dev / netif / ath / hal / ath_hal / ar5212 / ar5212_misc.c
1 /*
2  * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
3  * Copyright (c) 2002-2008 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/ar5212/ar5212_misc.c 188866 2009-02-20 22:06:58Z sam $
18  */
19 #include "opt_ah.h"
20
21 #include "ah.h"
22 #include "ah_internal.h"
23 #include "ah_devid.h"
24 #ifdef AH_DEBUG
25 #include "ah_desc.h"                    /* NB: for HAL_PHYERR* */
26 #endif
27
28 #include "ar5212/ar5212.h"
29 #include "ar5212/ar5212reg.h"
30 #include "ar5212/ar5212phy.h"
31
32 #include "ah_eeprom_v3.h"
33
34 #define AR_NUM_GPIO     6               /* 6 GPIO pins */
35 #define AR_GPIOD_MASK   0x0000002F      /* GPIO data reg r/w mask */
36
37 void
38 ar5212GetMacAddress(struct ath_hal *ah, uint8_t *mac)
39 {
40         struct ath_hal_5212 *ahp = AH5212(ah);
41
42         OS_MEMCPY(mac, ahp->ah_macaddr, IEEE80211_ADDR_LEN);
43 }
44
45 HAL_BOOL
46 ar5212SetMacAddress(struct ath_hal *ah, const uint8_t *mac)
47 {
48         struct ath_hal_5212 *ahp = AH5212(ah);
49
50         OS_MEMCPY(ahp->ah_macaddr, mac, IEEE80211_ADDR_LEN);
51         return AH_TRUE;
52 }
53
54 void
55 ar5212GetBssIdMask(struct ath_hal *ah, uint8_t *mask)
56 {
57         struct ath_hal_5212 *ahp = AH5212(ah);
58
59         OS_MEMCPY(mask, ahp->ah_bssidmask, IEEE80211_ADDR_LEN);
60 }
61
62 HAL_BOOL
63 ar5212SetBssIdMask(struct ath_hal *ah, const uint8_t *mask)
64 {
65         struct ath_hal_5212 *ahp = AH5212(ah);
66
67         /* save it since it must be rewritten on reset */
68         OS_MEMCPY(ahp->ah_bssidmask, mask, IEEE80211_ADDR_LEN);
69
70         OS_REG_WRITE(ah, AR_BSSMSKL, LE_READ_4(ahp->ah_bssidmask));
71         OS_REG_WRITE(ah, AR_BSSMSKU, LE_READ_2(ahp->ah_bssidmask + 4));
72         return AH_TRUE;
73 }
74
75 /*
76  * Attempt to change the cards operating regulatory domain to the given value
77  */
78 HAL_BOOL
79 ar5212SetRegulatoryDomain(struct ath_hal *ah,
80         uint16_t regDomain, HAL_STATUS *status)
81 {
82         HAL_STATUS ecode;
83
84         if (AH_PRIVATE(ah)->ah_currentRD == regDomain) {
85                 ecode = HAL_EINVAL;
86                 goto bad;
87         }
88         if (ath_hal_eepromGetFlag(ah, AR_EEP_WRITEPROTECT)) {
89                 ecode = HAL_EEWRITE;
90                 goto bad;
91         }
92 #ifdef AH_SUPPORT_WRITE_REGDOMAIN
93         if (ath_hal_eepromWrite(ah, AR_EEPROM_REG_DOMAIN, regDomain)) {
94                 HALDEBUG(ah, HAL_DEBUG_ANY,
95                     "%s: set regulatory domain to %u (0x%x)\n",
96                     __func__, regDomain, regDomain);
97                 AH_PRIVATE(ah)->ah_currentRD = regDomain;
98                 return AH_TRUE;
99         }
100 #endif
101         ecode = HAL_EIO;
102 bad:
103         if (status)
104                 *status = ecode;
105         return AH_FALSE;
106 }
107
108 /*
109  * Return the wireless modes (a,b,g,t) supported by hardware.
110  *
111  * This value is what is actually supported by the hardware
112  * and is unaffected by regulatory/country code settings.
113  */
114 u_int
115 ar5212GetWirelessModes(struct ath_hal *ah)
116 {
117         u_int mode = 0;
118
119         if (ath_hal_eepromGetFlag(ah, AR_EEP_AMODE)) {
120                 mode = HAL_MODE_11A;
121                 if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO5DISABLE))
122                         mode |= HAL_MODE_TURBO | HAL_MODE_108A;
123                 if (AH_PRIVATE(ah)->ah_caps.halChanHalfRate)
124                         mode |= HAL_MODE_11A_HALF_RATE;
125                 if (AH_PRIVATE(ah)->ah_caps.halChanQuarterRate)
126                         mode |= HAL_MODE_11A_QUARTER_RATE;
127         }
128         if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE))
129                 mode |= HAL_MODE_11B;
130         if (ath_hal_eepromGetFlag(ah, AR_EEP_GMODE) &&
131             AH_PRIVATE(ah)->ah_subvendorid != AR_SUBVENDOR_ID_NOG) {
132                 mode |= HAL_MODE_11G;
133                 if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO2DISABLE))
134                         mode |= HAL_MODE_108G;
135                 if (AH_PRIVATE(ah)->ah_caps.halChanHalfRate)
136                         mode |= HAL_MODE_11G_HALF_RATE;
137                 if (AH_PRIVATE(ah)->ah_caps.halChanQuarterRate)
138                         mode |= HAL_MODE_11G_QUARTER_RATE;
139         }
140         return mode;
141 }
142
143 /*
144  * Set the interrupt and GPIO values so the ISR can disable RF
145  * on a switch signal.  Assumes GPIO port and interrupt polarity
146  * are set prior to call.
147  */
148 void
149 ar5212EnableRfKill(struct ath_hal *ah)
150 {
151         uint16_t rfsilent = AH_PRIVATE(ah)->ah_rfsilent;
152         int select = MS(rfsilent, AR_EEPROM_RFSILENT_GPIO_SEL);
153         int polarity = MS(rfsilent, AR_EEPROM_RFSILENT_POLARITY);
154
155         /*
156          * Configure the desired GPIO port for input
157          * and enable baseband rf silence.
158          */
159         ath_hal_gpioCfgInput(ah, select);
160         OS_REG_SET_BIT(ah, AR_PHY(0), 0x00002000);
161         /*
162          * If radio disable switch connection to GPIO bit x is enabled
163          * program GPIO interrupt.
164          * If rfkill bit on eeprom is 1, setupeeprommap routine has already
165          * verified that it is a later version of eeprom, it has a place for
166          * rfkill bit and it is set to 1, indicating that GPIO bit x hardware
167          * connection is present.
168          */
169         ath_hal_gpioSetIntr(ah, select,
170             (ath_hal_gpioGet(ah, select) == polarity ? !polarity : polarity));
171 }
172
173 /*
174  * Change the LED blinking pattern to correspond to the connectivity
175  */
176 void
177 ar5212SetLedState(struct ath_hal *ah, HAL_LED_STATE state)
178 {
179         static const uint32_t ledbits[8] = {
180                 AR_PCICFG_LEDCTL_NONE,  /* HAL_LED_INIT */
181                 AR_PCICFG_LEDCTL_PEND,  /* HAL_LED_SCAN */
182                 AR_PCICFG_LEDCTL_PEND,  /* HAL_LED_AUTH */
183                 AR_PCICFG_LEDCTL_ASSOC, /* HAL_LED_ASSOC*/
184                 AR_PCICFG_LEDCTL_ASSOC, /* HAL_LED_RUN */
185                 AR_PCICFG_LEDCTL_NONE,
186                 AR_PCICFG_LEDCTL_NONE,
187                 AR_PCICFG_LEDCTL_NONE,
188         };
189         uint32_t bits;
190
191         bits = OS_REG_READ(ah, AR_PCICFG);
192         if (IS_2417(ah)) {
193                 /*
194                  * Enable LED for Nala. There is a bit marked reserved
195                  * that must be set and we also turn on the power led.
196                  * Because we mark s/w LED control setting the control
197                  * status bits below is meangless (the driver must flash
198                  * the LED(s) using the GPIO lines).
199                  */
200                 bits = (bits &~ AR_PCICFG_LEDMODE)
201                      | SM(AR_PCICFG_LEDMODE_POWON, AR_PCICFG_LEDMODE)
202 #if 0
203                      | SM(AR_PCICFG_LEDMODE_NETON, AR_PCICFG_LEDMODE)
204 #endif
205                      | 0x08000000;
206         }
207         bits = (bits &~ AR_PCICFG_LEDCTL)
208              | SM(ledbits[state & 0x7], AR_PCICFG_LEDCTL);
209         OS_REG_WRITE(ah, AR_PCICFG, bits);
210 }
211
212 /*
213  * Change association related fields programmed into the hardware.
214  * Writing a valid BSSID to the hardware effectively enables the hardware
215  * to synchronize its TSF to the correct beacons and receive frames coming
216  * from that BSSID. It is called by the SME JOIN operation.
217  */
218 void
219 ar5212WriteAssocid(struct ath_hal *ah, const uint8_t *bssid, uint16_t assocId)
220 {
221         struct ath_hal_5212 *ahp = AH5212(ah);
222
223         /* XXX save bssid for possible re-use on reset */
224         OS_MEMCPY(ahp->ah_bssid, bssid, IEEE80211_ADDR_LEN);
225         OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid));
226         OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid+4) |
227                                      ((assocId & 0x3fff)<<AR_BSS_ID1_AID_S));
228 }
229
230 /*
231  * Get the current hardware tsf for stamlme
232  */
233 uint64_t
234 ar5212GetTsf64(struct ath_hal *ah)
235 {
236         uint32_t low1, low2, u32;
237
238         /* sync multi-word read */
239         low1 = OS_REG_READ(ah, AR_TSF_L32);
240         u32 = OS_REG_READ(ah, AR_TSF_U32);
241         low2 = OS_REG_READ(ah, AR_TSF_L32);
242         if (low2 < low1) {      /* roll over */
243                 /*
244                  * If we are not preempted this will work.  If we are
245                  * then we re-reading AR_TSF_U32 does no good as the
246                  * low bits will be meaningless.  Likewise reading
247                  * L32, U32, U32, then comparing the last two reads
248                  * to check for rollover doesn't help if preempted--so
249                  * we take this approach as it costs one less PCI read
250                  * which can be noticeable when doing things like
251                  * timestamping packets in monitor mode.
252                  */
253                 u32++;
254         }
255         return (((uint64_t) u32) << 32) | ((uint64_t) low2);
256 }
257
258 /*
259  * Get the current hardware tsf for stamlme
260  */
261 uint32_t
262 ar5212GetTsf32(struct ath_hal *ah)
263 {
264         return OS_REG_READ(ah, AR_TSF_L32);
265 }
266
267 /*
268  * Reset the current hardware tsf for stamlme.
269  */
270 void
271 ar5212ResetTsf(struct ath_hal *ah)
272 {
273
274         uint32_t val = OS_REG_READ(ah, AR_BEACON);
275
276         OS_REG_WRITE(ah, AR_BEACON, val | AR_BEACON_RESET_TSF);
277         /*
278          * When resetting the TSF, write twice to the
279          * corresponding register; each write to the RESET_TSF bit toggles
280          * the internal signal to cause a reset of the TSF - but if the signal
281          * is left high, it will reset the TSF on the next chip reset also!
282          * writing the bit an even number of times fixes this issue
283          */
284         OS_REG_WRITE(ah, AR_BEACON, val | AR_BEACON_RESET_TSF);
285 }
286
287 /*
288  * Set or clear hardware basic rate bit
289  * Set hardware basic rate set if basic rate is found
290  * and basic rate is equal or less than 2Mbps
291  */
292 void
293 ar5212SetBasicRate(struct ath_hal *ah, HAL_RATE_SET *rs)
294 {
295         const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan;
296         uint32_t reg;
297         uint8_t xset;
298         int i;
299
300         if (chan == AH_NULL || !IEEE80211_IS_CHAN_CCK(chan))
301                 return;
302         xset = 0;
303         for (i = 0; i < rs->rs_count; i++) {
304                 uint8_t rset = rs->rs_rates[i];
305                 /* Basic rate defined? */
306                 if ((rset & 0x80) && (rset &= 0x7f) >= xset)
307                         xset = rset;
308         }
309         /*
310          * Set the h/w bit to reflect whether or not the basic
311          * rate is found to be equal or less than 2Mbps.
312          */
313         reg = OS_REG_READ(ah, AR_STA_ID1);
314         if (xset && xset/2 <= 2)
315                 OS_REG_WRITE(ah, AR_STA_ID1, reg | AR_STA_ID1_BASE_RATE_11B);
316         else
317                 OS_REG_WRITE(ah, AR_STA_ID1, reg &~ AR_STA_ID1_BASE_RATE_11B);
318 }
319
320 /*
321  * Grab a semi-random value from hardware registers - may not
322  * change often
323  */
324 uint32_t
325 ar5212GetRandomSeed(struct ath_hal *ah)
326 {
327         uint32_t nf;
328
329         nf = (OS_REG_READ(ah, AR_PHY(25)) >> 19) & 0x1ff;
330         if (nf & 0x100)
331                 nf = 0 - ((nf ^ 0x1ff) + 1);
332         return (OS_REG_READ(ah, AR_TSF_U32) ^
333                 OS_REG_READ(ah, AR_TSF_L32) ^ nf);
334 }
335
336 /*
337  * Detect if our card is present
338  */
339 HAL_BOOL
340 ar5212DetectCardPresent(struct ath_hal *ah)
341 {
342         uint16_t macVersion, macRev;
343         uint32_t v;
344
345         /*
346          * Read the Silicon Revision register and compare that
347          * to what we read at attach time.  If the same, we say
348          * a card/device is present.
349          */
350         v = OS_REG_READ(ah, AR_SREV) & AR_SREV_ID;
351         macVersion = v >> AR_SREV_ID_S;
352         macRev = v & AR_SREV_REVISION;
353         return (AH_PRIVATE(ah)->ah_macVersion == macVersion &&
354                 AH_PRIVATE(ah)->ah_macRev == macRev);
355 }
356
357 void
358 ar5212EnableMibCounters(struct ath_hal *ah)
359 {
360         /* NB: this just resets the mib counter machinery */
361         OS_REG_WRITE(ah, AR_MIBC,
362             ~(AR_MIBC_COW | AR_MIBC_FMC | AR_MIBC_CMC | AR_MIBC_MCS) & 0x0f);
363 }
364
365 void 
366 ar5212DisableMibCounters(struct ath_hal *ah)
367 {
368         OS_REG_WRITE(ah, AR_MIBC,  AR_MIBC | AR_MIBC_CMC);
369 }
370
371 /*
372  * Update MIB Counters
373  */
374 void
375 ar5212UpdateMibCounters(struct ath_hal *ah, HAL_MIB_STATS* stats)
376 {
377         stats->ackrcv_bad += OS_REG_READ(ah, AR_ACK_FAIL);
378         stats->rts_bad    += OS_REG_READ(ah, AR_RTS_FAIL);
379         stats->fcs_bad    += OS_REG_READ(ah, AR_FCS_FAIL);
380         stats->rts_good   += OS_REG_READ(ah, AR_RTS_OK);
381         stats->beacons    += OS_REG_READ(ah, AR_BEACON_CNT);
382 }
383
384 /*
385  * Detect if the HW supports spreading a CCK signal on channel 14
386  */
387 HAL_BOOL
388 ar5212IsJapanChannelSpreadSupported(struct ath_hal *ah)
389 {
390         return AH_TRUE;
391 }
392
393 /*
394  * Get the rssi of frame curently being received.
395  */
396 uint32_t
397 ar5212GetCurRssi(struct ath_hal *ah)
398 {
399         return (OS_REG_READ(ah, AR_PHY_CURRENT_RSSI) & 0xff);
400 }
401
402 u_int
403 ar5212GetDefAntenna(struct ath_hal *ah)
404 {   
405         return (OS_REG_READ(ah, AR_DEF_ANTENNA) & 0x7);
406 }   
407
408 void
409 ar5212SetDefAntenna(struct ath_hal *ah, u_int antenna)
410 {
411         OS_REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7));
412 }
413
414 HAL_ANT_SETTING
415 ar5212GetAntennaSwitch(struct ath_hal *ah)
416 {
417         return AH5212(ah)->ah_antControl;
418 }
419
420 HAL_BOOL
421 ar5212SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING setting)
422 {
423         struct ath_hal_5212 *ahp = AH5212(ah);
424         const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan;
425
426         if (!ahp->ah_phyPowerOn || chan == AH_NULL) {
427                 /* PHY powered off, just stash settings */
428                 ahp->ah_antControl = setting;
429                 ahp->ah_diversity = (setting == HAL_ANT_VARIABLE);
430                 return AH_TRUE;
431         }
432         return ar5212SetAntennaSwitchInternal(ah, setting, chan);
433 }
434
435 HAL_BOOL
436 ar5212IsSleepAfterBeaconBroken(struct ath_hal *ah)
437 {
438         return AH_TRUE;
439 }
440
441 HAL_BOOL
442 ar5212SetSifsTime(struct ath_hal *ah, u_int us)
443 {
444         struct ath_hal_5212 *ahp = AH5212(ah);
445
446         if (us > ath_hal_mac_usec(ah, 0xffff)) {
447                 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad SIFS time %u\n",
448                     __func__, us);
449                 ahp->ah_sifstime = (u_int) -1;  /* restore default handling */
450                 return AH_FALSE;
451         } else {
452                 /* convert to system clocks */
453                 OS_REG_WRITE(ah, AR_D_GBL_IFS_SIFS, ath_hal_mac_clks(ah, us-2));
454                 ahp->ah_slottime = us;
455                 return AH_TRUE;
456         }
457 }
458
459 u_int
460 ar5212GetSifsTime(struct ath_hal *ah)
461 {
462         u_int clks = OS_REG_READ(ah, AR_D_GBL_IFS_SIFS) & 0xffff;
463         return ath_hal_mac_usec(ah, clks)+2;    /* convert from system clocks */
464 }
465
466 HAL_BOOL
467 ar5212SetSlotTime(struct ath_hal *ah, u_int us)
468 {
469         struct ath_hal_5212 *ahp = AH5212(ah);
470
471         if (us < HAL_SLOT_TIME_6 || us > ath_hal_mac_usec(ah, 0xffff)) {
472                 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad slot time %u\n",
473                     __func__, us);
474                 ahp->ah_slottime = (u_int) -1;  /* restore default handling */
475                 return AH_FALSE;
476         } else {
477                 /* convert to system clocks */
478                 OS_REG_WRITE(ah, AR_D_GBL_IFS_SLOT, ath_hal_mac_clks(ah, us));
479                 ahp->ah_slottime = us;
480                 return AH_TRUE;
481         }
482 }
483
484 u_int
485 ar5212GetSlotTime(struct ath_hal *ah)
486 {
487         u_int clks = OS_REG_READ(ah, AR_D_GBL_IFS_SLOT) & 0xffff;
488         return ath_hal_mac_usec(ah, clks);      /* convert from system clocks */
489 }
490
491 HAL_BOOL
492 ar5212SetAckTimeout(struct ath_hal *ah, u_int us)
493 {
494         struct ath_hal_5212 *ahp = AH5212(ah);
495
496         if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) {
497                 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad ack timeout %u\n",
498                     __func__, us);
499                 ahp->ah_acktimeout = (u_int) -1; /* restore default handling */
500                 return AH_FALSE;
501         } else {
502                 /* convert to system clocks */
503                 OS_REG_RMW_FIELD(ah, AR_TIME_OUT,
504                         AR_TIME_OUT_ACK, ath_hal_mac_clks(ah, us));
505                 ahp->ah_acktimeout = us;
506                 return AH_TRUE;
507         }
508 }
509
510 u_int
511 ar5212GetAckTimeout(struct ath_hal *ah)
512 {
513         u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_ACK);
514         return ath_hal_mac_usec(ah, clks);      /* convert from system clocks */
515 }
516
517 u_int
518 ar5212GetAckCTSRate(struct ath_hal *ah)
519 {
520         return ((AH5212(ah)->ah_staId1Defaults & AR_STA_ID1_ACKCTS_6MB) == 0);
521 }
522
523 HAL_BOOL
524 ar5212SetAckCTSRate(struct ath_hal *ah, u_int high)
525 {
526         struct ath_hal_5212 *ahp = AH5212(ah);
527
528         if (high) {
529                 OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB);
530                 ahp->ah_staId1Defaults &= ~AR_STA_ID1_ACKCTS_6MB;
531         } else {
532                 OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB);
533                 ahp->ah_staId1Defaults |= AR_STA_ID1_ACKCTS_6MB;
534         }
535         return AH_TRUE;
536 }
537
538 HAL_BOOL
539 ar5212SetCTSTimeout(struct ath_hal *ah, u_int us)
540 {
541         struct ath_hal_5212 *ahp = AH5212(ah);
542
543         if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) {
544                 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad cts timeout %u\n",
545                     __func__, us);
546                 ahp->ah_ctstimeout = (u_int) -1; /* restore default handling */
547                 return AH_FALSE;
548         } else {
549                 /* convert to system clocks */
550                 OS_REG_RMW_FIELD(ah, AR_TIME_OUT,
551                         AR_TIME_OUT_CTS, ath_hal_mac_clks(ah, us));
552                 ahp->ah_ctstimeout = us;
553                 return AH_TRUE;
554         }
555 }
556
557 u_int
558 ar5212GetCTSTimeout(struct ath_hal *ah)
559 {
560         u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_CTS);
561         return ath_hal_mac_usec(ah, clks);      /* convert from system clocks */
562 }
563
564 /* Setup decompression for given key index */
565 HAL_BOOL
566 ar5212SetDecompMask(struct ath_hal *ah, uint16_t keyidx, int en)
567 {
568         struct ath_hal_5212 *ahp = AH5212(ah);
569
570         if (keyidx >= HAL_DECOMP_MASK_SIZE)
571                 return HAL_EINVAL; 
572         OS_REG_WRITE(ah, AR_DCM_A, keyidx);
573         OS_REG_WRITE(ah, AR_DCM_D, en ? AR_DCM_D_EN : 0);
574         ahp->ah_decompMask[keyidx] = en;
575
576         return AH_TRUE;
577 }
578
579 /* Setup coverage class */
580 void
581 ar5212SetCoverageClass(struct ath_hal *ah, uint8_t coverageclass, int now)
582 {
583         uint32_t slot, timeout, eifs;
584         u_int clkRate;
585
586         AH_PRIVATE(ah)->ah_coverageClass = coverageclass;
587
588         if (now) {
589                 if (AH_PRIVATE(ah)->ah_coverageClass == 0)
590                         return;
591
592                 /* Don't apply coverage class to non A channels */
593                 if (!IEEE80211_IS_CHAN_A(AH_PRIVATE(ah)->ah_curchan))
594                         return;
595
596                 /* Get core clock rate */
597                 clkRate = ath_hal_mac_clks(ah, 1);
598
599                 /* Compute EIFS */
600                 slot = coverageclass * 3 * clkRate;
601                 eifs = coverageclass * 6 * clkRate;
602                 if (IEEE80211_IS_CHAN_HALF(AH_PRIVATE(ah)->ah_curchan)) {
603                         slot += IFS_SLOT_HALF_RATE;
604                         eifs += IFS_EIFS_HALF_RATE;
605                 } else if (IEEE80211_IS_CHAN_QUARTER(AH_PRIVATE(ah)->ah_curchan)) {
606                         slot += IFS_SLOT_QUARTER_RATE;
607                         eifs += IFS_EIFS_QUARTER_RATE;
608                 } else { /* full rate */
609                         slot += IFS_SLOT_FULL_RATE;
610                         eifs += IFS_EIFS_FULL_RATE;
611                 }
612
613                 /*
614                  * Add additional time for air propagation for ACK and CTS
615                  * timeouts. This value is in core clocks.
616                  */
617                 timeout = ACK_CTS_TIMEOUT_11A + (coverageclass * 3 * clkRate);
618         
619                 /*
620                  * Write the values: slot, eifs, ack/cts timeouts.
621                  */
622                 OS_REG_WRITE(ah, AR_D_GBL_IFS_SLOT, slot);
623                 OS_REG_WRITE(ah, AR_D_GBL_IFS_EIFS, eifs);
624                 OS_REG_WRITE(ah, AR_TIME_OUT,
625                           SM(timeout, AR_TIME_OUT_CTS)
626                         | SM(timeout, AR_TIME_OUT_ACK));
627         }
628 }
629
630 void
631 ar5212SetPCUConfig(struct ath_hal *ah)
632 {
633         ar5212SetOperatingMode(ah, AH_PRIVATE(ah)->ah_opmode);
634 }
635
636 /*
637  * Return whether an external 32KHz crystal should be used
638  * to reduce power consumption when sleeping.  We do so if
639  * the crystal is present (obtained from EEPROM) and if we
640  * are not running as an AP and are configured to use it.
641  */
642 HAL_BOOL
643 ar5212Use32KHzclock(struct ath_hal *ah, HAL_OPMODE opmode)
644 {
645         if (opmode != HAL_M_HOSTAP) {
646                 struct ath_hal_5212 *ahp = AH5212(ah);
647                 return ath_hal_eepromGetFlag(ah, AR_EEP_32KHZCRYSTAL) &&
648                        (ahp->ah_enable32kHzClock == USE_32KHZ ||
649                         ahp->ah_enable32kHzClock == AUTO_32KHZ);
650         } else
651                 return AH_FALSE;
652 }
653
654 /*
655  * If 32KHz clock exists, use it to lower power consumption during sleep
656  *
657  * Note: If clock is set to 32 KHz, delays on accessing certain
658  *       baseband registers (27-31, 124-127) are required.
659  */
660 void
661 ar5212SetupClock(struct ath_hal *ah, HAL_OPMODE opmode)
662 {
663         if (ar5212Use32KHzclock(ah, opmode)) {
664                 /*
665                  * Enable clocks to be turned OFF in BB during sleep
666                  * and also enable turning OFF 32MHz/40MHz Refclk
667                  * from A2.
668                  */
669                 OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f);
670                 OS_REG_WRITE(ah, AR_PHY_REFCLKPD,
671                     IS_RAD5112_ANY(ah) || IS_5413(ah) ? 0x14 : 0x18);
672                 OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32, 1);
673                 OS_REG_WRITE(ah, AR_TSF_PARM, 61);  /* 32 KHz TSF incr */
674                 OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_SEL, 1);
675
676                 if (IS_2413(ah) || IS_5413(ah) || IS_2417(ah)) {
677                         OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT,   0x26);
678                         OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL,        0x0d);
679                         OS_REG_WRITE(ah, AR_PHY_M_SLEEP,           0x07);
680                         OS_REG_WRITE(ah, AR_PHY_REFCLKDLY,         0x3f);
681                         /* # Set sleep clock rate to 32 KHz. */
682                         OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0x2);
683                 } else {
684                         OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT,   0x0a);
685                         OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL,        0x0c);
686                         OS_REG_WRITE(ah, AR_PHY_M_SLEEP,           0x03);
687                         OS_REG_WRITE(ah, AR_PHY_REFCLKDLY,         0x20);
688                         OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0x3);
689                 }
690         } else {
691                 OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0x0);
692                 OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_SEL, 0);
693
694                 OS_REG_WRITE(ah, AR_TSF_PARM, 1);       /* 32MHz TSF inc */
695
696                 OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f);
697                 OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT,   0x7f);
698
699                 if (IS_2417(ah))
700                         OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0a);
701                 else if (IS_HB63(ah))
702                         OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x32);
703                 else
704                         OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e);
705                 OS_REG_WRITE(ah, AR_PHY_M_SLEEP,           0x0c);
706                 OS_REG_WRITE(ah, AR_PHY_REFCLKDLY,         0xff);
707                 OS_REG_WRITE(ah, AR_PHY_REFCLKPD,
708                     IS_RAD5112_ANY(ah) || IS_5413(ah) || IS_2417(ah) ? 0x14 : 0x18);
709                 OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32,
710                     IS_RAD5112_ANY(ah) || IS_5413(ah) ? 39 : 31);
711         }
712 }
713
714 /*
715  * If 32KHz clock exists, turn it off and turn back on the 32Mhz
716  */
717 void
718 ar5212RestoreClock(struct ath_hal *ah, HAL_OPMODE opmode)
719 {
720         if (ar5212Use32KHzclock(ah, opmode)) {
721                 /* # Set sleep clock rate back to 32 MHz. */
722                 OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0);
723                 OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_SEL, 0);
724
725                 OS_REG_WRITE(ah, AR_TSF_PARM, 1);       /* 32 MHz TSF incr */
726                 OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32,
727                     IS_RAD5112_ANY(ah) || IS_5413(ah) ? 39 : 31);
728
729                 /*
730                  * Restore BB registers to power-on defaults
731                  */
732                 OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f);
733                 OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT,   0x7f);
734                 OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL,        0x0e);
735                 OS_REG_WRITE(ah, AR_PHY_M_SLEEP,           0x0c);
736                 OS_REG_WRITE(ah, AR_PHY_REFCLKDLY,         0xff);
737                 OS_REG_WRITE(ah, AR_PHY_REFCLKPD,
738                     IS_RAD5112_ANY(ah) || IS_5413(ah) ?  0x14 : 0x18);
739         }
740 }
741
742 /*
743  * Adjust NF based on statistical values for 5GHz frequencies.
744  * Default method: this may be overridden by the rf backend.
745  */
746 int16_t
747 ar5212GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c)
748 {
749         static const struct {
750                 uint16_t freqLow;
751                 int16_t   adjust;
752         } adjustDef[] = {
753                 { 5790, 11 },   /* NB: ordered high -> low */
754                 { 5730, 10 },
755                 { 5690,  9 },
756                 { 5660,  8 },
757                 { 5610,  7 },
758                 { 5530,  5 },
759                 { 5450,  4 },
760                 { 5379,  2 },
761                 { 5209,  0 },
762                 { 3000,  1 },
763                 {    0,  0 },
764         };
765         int i;
766
767         for (i = 0; c->channel <= adjustDef[i].freqLow; i++)
768                 ;
769         return adjustDef[i].adjust;
770 }
771
772 HAL_STATUS
773 ar5212GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
774         uint32_t capability, uint32_t *result)
775 {
776 #define MACVERSION(ah)  AH_PRIVATE(ah)->ah_macVersion
777         struct ath_hal_5212 *ahp = AH5212(ah);
778         const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
779         const struct ar5212AniState *ani;
780
781         switch (type) {
782         case HAL_CAP_CIPHER:            /* cipher handled in hardware */
783                 switch (capability) {
784                 case HAL_CIPHER_AES_CCM:
785                         return pCap->halCipherAesCcmSupport ?
786                                 HAL_OK : HAL_ENOTSUPP;
787                 case HAL_CIPHER_AES_OCB:
788                 case HAL_CIPHER_TKIP:
789                 case HAL_CIPHER_WEP:
790                 case HAL_CIPHER_MIC:
791                 case HAL_CIPHER_CLR:
792                         return HAL_OK;
793                 default:
794                         return HAL_ENOTSUPP;
795                 }
796         case HAL_CAP_TKIP_MIC:          /* handle TKIP MIC in hardware */
797                 switch (capability) {
798                 case 0:                 /* hardware capability */
799                         return HAL_OK;
800                 case 1:
801                         return (ahp->ah_staId1Defaults &
802                             AR_STA_ID1_CRPT_MIC_ENABLE) ?  HAL_OK : HAL_ENXIO;
803                 }
804                 return HAL_EINVAL;
805         case HAL_CAP_TKIP_SPLIT:        /* hardware TKIP uses split keys */
806                 switch (capability) {
807                 case 0:                 /* hardware capability */
808                         return pCap->halTkipMicTxRxKeySupport ?
809                                 HAL_ENXIO : HAL_OK;
810                 case 1:                 /* current setting */
811                         return (ahp->ah_miscMode &
812                             AR_MISC_MODE_MIC_NEW_LOC_ENABLE) ? HAL_ENXIO : HAL_OK;
813                 }
814                 return HAL_EINVAL;
815         case HAL_CAP_WME_TKIPMIC:       /* hardware can do TKIP MIC w/ WMM */
816                 /* XXX move to capability bit */
817                 return MACVERSION(ah) > AR_SREV_VERSION_VENICE ||
818                     (MACVERSION(ah) == AR_SREV_VERSION_VENICE &&
819                      AH_PRIVATE(ah)->ah_macRev >= 8) ? HAL_OK : HAL_ENOTSUPP;
820         case HAL_CAP_DIVERSITY:         /* hardware supports fast diversity */
821                 switch (capability) {
822                 case 0:                 /* hardware capability */
823                         return HAL_OK;
824                 case 1:                 /* current setting */
825                         return ahp->ah_diversity ? HAL_OK : HAL_ENXIO;
826                 }
827                 return HAL_EINVAL;
828         case HAL_CAP_DIAG:
829                 *result = AH_PRIVATE(ah)->ah_diagreg;
830                 return HAL_OK;
831         case HAL_CAP_TPC:
832                 switch (capability) {
833                 case 0:                 /* hardware capability */
834                         return HAL_OK;
835                 case 1:
836                         return ahp->ah_tpcEnabled ? HAL_OK : HAL_ENXIO;
837                 }
838                 return HAL_OK;
839         case HAL_CAP_PHYDIAG:           /* radar pulse detection capability */
840                 switch (capability) {
841                 case HAL_CAP_RADAR:
842                         return ath_hal_eepromGetFlag(ah, AR_EEP_AMODE) ?
843                             HAL_OK: HAL_ENXIO;
844                 case HAL_CAP_AR:
845                         return (ath_hal_eepromGetFlag(ah, AR_EEP_GMODE) ||
846                             ath_hal_eepromGetFlag(ah, AR_EEP_BMODE)) ?
847                                HAL_OK: HAL_ENXIO;
848                 }
849                 return HAL_ENXIO;
850         case HAL_CAP_MCAST_KEYSRCH:     /* multicast frame keycache search */
851                 switch (capability) {
852                 case 0:                 /* hardware capability */
853                         return HAL_OK;
854                 case 1:
855                         return (ahp->ah_staId1Defaults &
856                             AR_STA_ID1_MCAST_KSRCH) ? HAL_OK : HAL_ENXIO;
857                 }
858                 return HAL_EINVAL;
859         case HAL_CAP_TSF_ADJUST:        /* hardware has beacon tsf adjust */
860                 switch (capability) {
861                 case 0:                 /* hardware capability */
862                         return pCap->halTsfAddSupport ? HAL_OK : HAL_ENOTSUPP;
863                 case 1:
864                         return (ahp->ah_miscMode & AR_MISC_MODE_TX_ADD_TSF) ?
865                                 HAL_OK : HAL_ENXIO;
866                 }
867                 return HAL_EINVAL;
868         case HAL_CAP_TPC_ACK:
869                 *result = MS(ahp->ah_macTPC, AR_TPC_ACK);
870                 return HAL_OK;
871         case HAL_CAP_TPC_CTS:
872                 *result = MS(ahp->ah_macTPC, AR_TPC_CTS);
873                 return HAL_OK;
874         case HAL_CAP_INTMIT:            /* interference mitigation */
875                 switch (capability) {
876                 case 0:                 /* hardware capability */
877                         return HAL_OK;
878                 case 1:
879                         return (ahp->ah_procPhyErr & HAL_ANI_ENA) ?
880                                 HAL_OK : HAL_ENXIO;
881                 case 2:                 /* HAL_ANI_NOISE_IMMUNITY_LEVEL */
882                 case 3:                 /* HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION */
883                 case 4:                 /* HAL_ANI_CCK_WEAK_SIGNAL_THR */
884                 case 5:                 /* HAL_ANI_FIRSTEP_LEVEL */
885                 case 6:                 /* HAL_ANI_SPUR_IMMUNITY_LEVEL */
886                         ani = ar5212AniGetCurrentState(ah);
887                         if (ani == AH_NULL)
888                                 return HAL_ENXIO;
889                         switch (capability) {
890                         case 2: *result = ani->noiseImmunityLevel; break;
891                         case 3: *result = !ani->ofdmWeakSigDetectOff; break;
892                         case 4: *result = ani->cckWeakSigThreshold; break;
893                         case 5: *result = ani->firstepLevel; break;
894                         case 6: *result = ani->spurImmunityLevel; break;
895                         }
896                         return HAL_OK;
897                 }
898                 return HAL_EINVAL;
899         default:
900                 return ath_hal_getcapability(ah, type, capability, result);
901         }
902 #undef MACVERSION
903 }
904
905 HAL_BOOL
906 ar5212SetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
907         uint32_t capability, uint32_t setting, HAL_STATUS *status)
908 {
909         struct ath_hal_5212 *ahp = AH5212(ah);
910         const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
911         uint32_t v;
912
913         switch (type) {
914         case HAL_CAP_TKIP_MIC:          /* handle TKIP MIC in hardware */
915                 if (setting)
916                         ahp->ah_staId1Defaults |= AR_STA_ID1_CRPT_MIC_ENABLE;
917                 else
918                         ahp->ah_staId1Defaults &= ~AR_STA_ID1_CRPT_MIC_ENABLE;
919                 return AH_TRUE;
920         case HAL_CAP_TKIP_SPLIT:        /* hardware TKIP uses split keys */
921                 if (!pCap->halTkipMicTxRxKeySupport)
922                         return AH_FALSE;
923                 /* NB: true =>'s use split key cache layout */
924                 if (setting)
925                         ahp->ah_miscMode &= ~AR_MISC_MODE_MIC_NEW_LOC_ENABLE;
926                 else
927                         ahp->ah_miscMode |= AR_MISC_MODE_MIC_NEW_LOC_ENABLE;
928                 /* NB: write here so keys can be setup w/o a reset */
929                 OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode);
930                 return AH_TRUE;
931         case HAL_CAP_DIVERSITY:
932                 if (ahp->ah_phyPowerOn) {
933                         v = OS_REG_READ(ah, AR_PHY_CCK_DETECT);
934                         if (setting)
935                                 v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
936                         else
937                                 v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
938                         OS_REG_WRITE(ah, AR_PHY_CCK_DETECT, v);
939                 }
940                 ahp->ah_diversity = (setting != 0);
941                 return AH_TRUE;
942         case HAL_CAP_DIAG:              /* hardware diagnostic support */
943                 /*
944                  * NB: could split this up into virtual capabilities,
945                  *     (e.g. 1 => ACK, 2 => CTS, etc.) but it hardly
946                  *     seems worth the additional complexity.
947                  */
948                 AH_PRIVATE(ah)->ah_diagreg = setting;
949                 OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg);
950                 return AH_TRUE;
951         case HAL_CAP_TPC:
952                 ahp->ah_tpcEnabled = (setting != 0);
953                 return AH_TRUE;
954         case HAL_CAP_MCAST_KEYSRCH:     /* multicast frame keycache search */
955                 if (setting)
956                         ahp->ah_staId1Defaults |= AR_STA_ID1_MCAST_KSRCH;
957                 else
958                         ahp->ah_staId1Defaults &= ~AR_STA_ID1_MCAST_KSRCH;
959                 return AH_TRUE;
960         case HAL_CAP_TPC_ACK:
961         case HAL_CAP_TPC_CTS:
962                 setting += ahp->ah_txPowerIndexOffset;
963                 if (setting > 63)
964                         setting = 63;
965                 if (type == HAL_CAP_TPC_ACK) {
966                         ahp->ah_macTPC &= AR_TPC_ACK;
967                         ahp->ah_macTPC |= MS(setting, AR_TPC_ACK);
968                 } else {
969                         ahp->ah_macTPC &= AR_TPC_CTS;
970                         ahp->ah_macTPC |= MS(setting, AR_TPC_CTS);
971                 }
972                 OS_REG_WRITE(ah, AR_TPC, ahp->ah_macTPC);
973                 return AH_TRUE;
974         case HAL_CAP_INTMIT: {          /* interference mitigation */
975                 static const HAL_ANI_CMD cmds[] = {
976                         HAL_ANI_PRESENT,
977                         HAL_ANI_MODE,
978                         HAL_ANI_NOISE_IMMUNITY_LEVEL,
979                         HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
980                         HAL_ANI_CCK_WEAK_SIGNAL_THR,
981                         HAL_ANI_FIRSTEP_LEVEL,
982                         HAL_ANI_SPUR_IMMUNITY_LEVEL,
983                 };
984                 return capability < NELEM(cmds) ?
985                         ar5212AniControl(ah, cmds[capability], setting) :
986                         AH_FALSE;
987         }
988         case HAL_CAP_TSF_ADJUST:        /* hardware has beacon tsf adjust */
989                 if (pCap->halTsfAddSupport) {
990                         if (setting)
991                                 ahp->ah_miscMode |= AR_MISC_MODE_TX_ADD_TSF;
992                         else
993                                 ahp->ah_miscMode &= ~AR_MISC_MODE_TX_ADD_TSF;
994                         return AH_TRUE;
995                 }
996                 /* fall thru... */
997         default:
998                 return ath_hal_setcapability(ah, type, capability,
999                                 setting, status);
1000         }
1001 }
1002
1003 HAL_BOOL
1004 ar5212GetDiagState(struct ath_hal *ah, int request,
1005         const void *args, uint32_t argsize,
1006         void **result, uint32_t *resultsize)
1007 {
1008         struct ath_hal_5212 *ahp = AH5212(ah);
1009
1010         (void) ahp;
1011         if (ath_hal_getdiagstate(ah, request, args, argsize, result, resultsize))
1012                 return AH_TRUE;
1013         switch (request) {
1014         case HAL_DIAG_EEPROM:
1015         case HAL_DIAG_EEPROM_EXP_11A:
1016         case HAL_DIAG_EEPROM_EXP_11B:
1017         case HAL_DIAG_EEPROM_EXP_11G:
1018         case HAL_DIAG_RFGAIN:
1019                 return ath_hal_eepromDiag(ah, request,
1020                     args, argsize, result, resultsize);
1021         case HAL_DIAG_RFGAIN_CURSTEP:
1022                 *result = __DECONST(void *, ahp->ah_gainValues.currStep);
1023                 *resultsize = (*result == AH_NULL) ?
1024                         0 : sizeof(GAIN_OPTIMIZATION_STEP);
1025                 return AH_TRUE;
1026         case HAL_DIAG_PCDAC:
1027                 *result = ahp->ah_pcdacTable;
1028                 *resultsize = ahp->ah_pcdacTableSize;
1029                 return AH_TRUE;
1030         case HAL_DIAG_TXRATES:
1031                 *result = &ahp->ah_ratesArray[0];
1032                 *resultsize = sizeof(ahp->ah_ratesArray);
1033                 return AH_TRUE;
1034         case HAL_DIAG_ANI_CURRENT:
1035                 *result = ar5212AniGetCurrentState(ah);
1036                 *resultsize = (*result == AH_NULL) ?
1037                         0 : sizeof(struct ar5212AniState);
1038                 return AH_TRUE;
1039         case HAL_DIAG_ANI_STATS:
1040                 *result = ar5212AniGetCurrentStats(ah);
1041                 *resultsize = (*result == AH_NULL) ?
1042                         0 : sizeof(struct ar5212Stats);
1043                 return AH_TRUE;
1044         case HAL_DIAG_ANI_CMD:
1045                 if (argsize != 2*sizeof(uint32_t))
1046                         return AH_FALSE;
1047                 ar5212AniControl(ah, ((const uint32_t *)args)[0],
1048                         ((const uint32_t *)args)[1]);
1049                 return AH_TRUE;
1050         case HAL_DIAG_ANI_PARAMS:
1051                 /*
1052                  * NB: We assume struct ar5212AniParams is identical
1053                  * to HAL_ANI_PARAMS; if they diverge then we'll need
1054                  * to handle it here
1055                  */
1056                 if (argsize == 0 && args == AH_NULL) {
1057                         struct ar5212AniState *aniState =
1058                             ar5212AniGetCurrentState(ah);
1059                         if (aniState == AH_NULL)
1060                                 return AH_FALSE;
1061                         *result = __DECONST(void *, aniState->params);
1062                         *resultsize = sizeof(struct ar5212AniParams);
1063                         return AH_TRUE;
1064                 } else {
1065                         if (argsize != sizeof(struct ar5212AniParams))
1066                                 return AH_FALSE;
1067                         return ar5212AniSetParams(ah, args, args);
1068                 }
1069         }
1070         return AH_FALSE;
1071 }
1072
1073 /*
1074  * Check whether there's an in-progress NF completion.
1075  *
1076  * Returns AH_TRUE if there's a in-progress NF calibration, AH_FALSE
1077  * otherwise.
1078  */
1079 HAL_BOOL
1080 ar5212IsNFCalInProgress(struct ath_hal *ah)
1081 {
1082         if (OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF)
1083                 return AH_TRUE;
1084         return AH_FALSE;
1085 }
1086
1087 /*
1088  * Wait for an in-progress NF calibration to complete.
1089  *
1090  * The completion function waits "i" times 10uS.
1091  * It returns AH_TRUE if the NF calibration completed (or was never
1092  * in progress); AH_FALSE if it was still in progress after "i" checks.
1093  */
1094 HAL_BOOL
1095 ar5212WaitNFCalComplete(struct ath_hal *ah, int i)
1096 {
1097         int j;
1098         if (i <= 0)
1099                 i = 1;    /* it should run at least once */
1100         for (j = 0; j < i; j++) {
1101                 if (! ar5212IsNFCalInProgress(ah))
1102                         return AH_TRUE;
1103                 OS_DELAY(10);
1104         }
1105         return AH_FALSE;
1106 }