]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/dev/ath/ath_hal/ar5212/ar5212_misc.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / dev / ath / 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$
18  */
19 #include "opt_ah.h"
20
21 #include "ah.h"
22 #include "ah_internal.h"
23 #include "ah_devid.h"
24 #include "ah_desc.h"                    /* NB: for HAL_PHYERR* */
25
26 #include "ar5212/ar5212.h"
27 #include "ar5212/ar5212reg.h"
28 #include "ar5212/ar5212phy.h"
29
30 #include "ah_eeprom_v3.h"
31
32 #define AR_NUM_GPIO     6               /* 6 GPIO pins */
33 #define AR_GPIOD_MASK   0x0000002F      /* GPIO data reg r/w mask */
34
35 void
36 ar5212GetMacAddress(struct ath_hal *ah, uint8_t *mac)
37 {
38         struct ath_hal_5212 *ahp = AH5212(ah);
39
40         OS_MEMCPY(mac, ahp->ah_macaddr, IEEE80211_ADDR_LEN);
41 }
42
43 HAL_BOOL
44 ar5212SetMacAddress(struct ath_hal *ah, const uint8_t *mac)
45 {
46         struct ath_hal_5212 *ahp = AH5212(ah);
47
48         OS_MEMCPY(ahp->ah_macaddr, mac, IEEE80211_ADDR_LEN);
49         return AH_TRUE;
50 }
51
52 void
53 ar5212GetBssIdMask(struct ath_hal *ah, uint8_t *mask)
54 {
55         struct ath_hal_5212 *ahp = AH5212(ah);
56
57         OS_MEMCPY(mask, ahp->ah_bssidmask, IEEE80211_ADDR_LEN);
58 }
59
60 HAL_BOOL
61 ar5212SetBssIdMask(struct ath_hal *ah, const uint8_t *mask)
62 {
63         struct ath_hal_5212 *ahp = AH5212(ah);
64
65         /* save it since it must be rewritten on reset */
66         OS_MEMCPY(ahp->ah_bssidmask, mask, IEEE80211_ADDR_LEN);
67
68         OS_REG_WRITE(ah, AR_BSSMSKL, LE_READ_4(ahp->ah_bssidmask));
69         OS_REG_WRITE(ah, AR_BSSMSKU, LE_READ_2(ahp->ah_bssidmask + 4));
70         return AH_TRUE;
71 }
72
73 /*
74  * Attempt to change the cards operating regulatory domain to the given value
75  */
76 HAL_BOOL
77 ar5212SetRegulatoryDomain(struct ath_hal *ah,
78         uint16_t regDomain, HAL_STATUS *status)
79 {
80         HAL_STATUS ecode;
81
82         if (AH_PRIVATE(ah)->ah_currentRD == regDomain) {
83                 ecode = HAL_EINVAL;
84                 goto bad;
85         }
86         if (ath_hal_eepromGetFlag(ah, AR_EEP_WRITEPROTECT)) {
87                 ecode = HAL_EEWRITE;
88                 goto bad;
89         }
90 #ifdef AH_SUPPORT_WRITE_REGDOMAIN
91         if (ath_hal_eepromWrite(ah, AR_EEPROM_REG_DOMAIN, regDomain)) {
92                 HALDEBUG(ah, HAL_DEBUG_ANY,
93                     "%s: set regulatory domain to %u (0x%x)\n",
94                     __func__, regDomain, regDomain);
95                 AH_PRIVATE(ah)->ah_currentRD = regDomain;
96                 return AH_TRUE;
97         }
98 #endif
99         ecode = HAL_EIO;
100 bad:
101         if (status)
102                 *status = ecode;
103         return AH_FALSE;
104 }
105
106 /*
107  * Return the wireless modes (a,b,g,t) supported by hardware.
108  *
109  * This value is what is actually supported by the hardware
110  * and is unaffected by regulatory/country code settings.
111  */
112 u_int
113 ar5212GetWirelessModes(struct ath_hal *ah)
114 {
115         u_int mode = 0;
116
117         if (ath_hal_eepromGetFlag(ah, AR_EEP_AMODE)) {
118                 mode = HAL_MODE_11A;
119                 if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO5DISABLE))
120                         mode |= HAL_MODE_TURBO | HAL_MODE_108A;
121                 if (AH_PRIVATE(ah)->ah_caps.halChanHalfRate)
122                         mode |= HAL_MODE_11A_HALF_RATE;
123                 if (AH_PRIVATE(ah)->ah_caps.halChanQuarterRate)
124                         mode |= HAL_MODE_11A_QUARTER_RATE;
125         }
126         if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE))
127                 mode |= HAL_MODE_11B;
128         if (ath_hal_eepromGetFlag(ah, AR_EEP_GMODE) &&
129             AH_PRIVATE(ah)->ah_subvendorid != AR_SUBVENDOR_ID_NOG) {
130                 mode |= HAL_MODE_11G;
131                 if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO2DISABLE))
132                         mode |= HAL_MODE_108G;
133                 if (AH_PRIVATE(ah)->ah_caps.halChanHalfRate)
134                         mode |= HAL_MODE_11G_HALF_RATE;
135                 if (AH_PRIVATE(ah)->ah_caps.halChanQuarterRate)
136                         mode |= HAL_MODE_11G_QUARTER_RATE;
137         }
138         return mode;
139 }
140
141 /*
142  * Set the interrupt and GPIO values so the ISR can disable RF
143  * on a switch signal.  Assumes GPIO port and interrupt polarity
144  * are set prior to call.
145  */
146 void
147 ar5212EnableRfKill(struct ath_hal *ah)
148 {
149         uint16_t rfsilent = AH_PRIVATE(ah)->ah_rfsilent;
150         int select = MS(rfsilent, AR_EEPROM_RFSILENT_GPIO_SEL);
151         int polarity = MS(rfsilent, AR_EEPROM_RFSILENT_POLARITY);
152
153         /*
154          * Configure the desired GPIO port for input
155          * and enable baseband rf silence.
156          */
157         ath_hal_gpioCfgInput(ah, select);
158         OS_REG_SET_BIT(ah, AR_PHY(0), 0x00002000);
159         /*
160          * If radio disable switch connection to GPIO bit x is enabled
161          * program GPIO interrupt.
162          * If rfkill bit on eeprom is 1, setupeeprommap routine has already
163          * verified that it is a later version of eeprom, it has a place for
164          * rfkill bit and it is set to 1, indicating that GPIO bit x hardware
165          * connection is present.
166          */
167         ath_hal_gpioSetIntr(ah, select,
168             (ath_hal_gpioGet(ah, select) == polarity ? !polarity : polarity));
169 }
170
171 /*
172  * Change the LED blinking pattern to correspond to the connectivity
173  */
174 void
175 ar5212SetLedState(struct ath_hal *ah, HAL_LED_STATE state)
176 {
177         static const uint32_t ledbits[8] = {
178                 AR_PCICFG_LEDCTL_NONE,  /* HAL_LED_INIT */
179                 AR_PCICFG_LEDCTL_PEND,  /* HAL_LED_SCAN */
180                 AR_PCICFG_LEDCTL_PEND,  /* HAL_LED_AUTH */
181                 AR_PCICFG_LEDCTL_ASSOC, /* HAL_LED_ASSOC*/
182                 AR_PCICFG_LEDCTL_ASSOC, /* HAL_LED_RUN */
183                 AR_PCICFG_LEDCTL_NONE,
184                 AR_PCICFG_LEDCTL_NONE,
185                 AR_PCICFG_LEDCTL_NONE,
186         };
187         uint32_t bits;
188
189         bits = OS_REG_READ(ah, AR_PCICFG);
190         if (IS_2417(ah)) {
191                 /*
192                  * Enable LED for Nala. There is a bit marked reserved
193                  * that must be set and we also turn on the power led.
194                  * Because we mark s/w LED control setting the control
195                  * status bits below is meangless (the driver must flash
196                  * the LED(s) using the GPIO lines).
197                  */
198                 bits = (bits &~ AR_PCICFG_LEDMODE)
199                      | SM(AR_PCICFG_LEDMODE_POWON, AR_PCICFG_LEDMODE)
200 #if 0
201                      | SM(AR_PCICFG_LEDMODE_NETON, AR_PCICFG_LEDMODE)
202 #endif
203                      | 0x08000000;
204         }
205         bits = (bits &~ AR_PCICFG_LEDCTL)
206              | SM(ledbits[state & 0x7], AR_PCICFG_LEDCTL);
207         OS_REG_WRITE(ah, AR_PCICFG, bits);
208 }
209
210 /*
211  * Change association related fields programmed into the hardware.
212  * Writing a valid BSSID to the hardware effectively enables the hardware
213  * to synchronize its TSF to the correct beacons and receive frames coming
214  * from that BSSID. It is called by the SME JOIN operation.
215  */
216 void
217 ar5212WriteAssocid(struct ath_hal *ah, const uint8_t *bssid, uint16_t assocId)
218 {
219         struct ath_hal_5212 *ahp = AH5212(ah);
220
221         /* save bssid for possible re-use on reset */
222         OS_MEMCPY(ahp->ah_bssid, bssid, IEEE80211_ADDR_LEN);
223         ahp->ah_assocId = assocId;
224         OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid));
225         OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid+4) |
226                                      ((assocId & 0x3fff)<<AR_BSS_ID1_AID_S));
227 }
228
229 /*
230  * Get the current hardware tsf for stamlme
231  */
232 uint64_t
233 ar5212GetTsf64(struct ath_hal *ah)
234 {
235         uint32_t low1, low2, u32;
236
237         /* sync multi-word read */
238         low1 = OS_REG_READ(ah, AR_TSF_L32);
239         u32 = OS_REG_READ(ah, AR_TSF_U32);
240         low2 = OS_REG_READ(ah, AR_TSF_L32);
241         if (low2 < low1) {      /* roll over */
242                 /*
243                  * If we are not preempted this will work.  If we are
244                  * then we re-reading AR_TSF_U32 does no good as the
245                  * low bits will be meaningless.  Likewise reading
246                  * L32, U32, U32, then comparing the last two reads
247                  * to check for rollover doesn't help if preempted--so
248                  * we take this approach as it costs one less PCI read
249                  * which can be noticeable when doing things like
250                  * timestamping packets in monitor mode.
251                  */
252                 u32++;
253         }
254         return (((uint64_t) u32) << 32) | ((uint64_t) low2);
255 }
256
257 /*
258  * Get the current hardware tsf for stamlme
259  */
260 uint32_t
261 ar5212GetTsf32(struct ath_hal *ah)
262 {
263         return OS_REG_READ(ah, AR_TSF_L32);
264 }
265
266 void
267 ar5212SetTsf64(struct ath_hal *ah, uint64_t tsf64)
268 {
269         OS_REG_WRITE(ah, AR_TSF_L32, tsf64 & 0xffffffff);
270         OS_REG_WRITE(ah, AR_TSF_U32, (tsf64 >> 32) & 0xffffffff);
271 }
272
273 /*
274  * Reset the current hardware tsf for stamlme.
275  */
276 void
277 ar5212ResetTsf(struct ath_hal *ah)
278 {
279
280         uint32_t val = OS_REG_READ(ah, AR_BEACON);
281
282         OS_REG_WRITE(ah, AR_BEACON, val | AR_BEACON_RESET_TSF);
283         /*
284          * When resetting the TSF, write twice to the
285          * corresponding register; each write to the RESET_TSF bit toggles
286          * the internal signal to cause a reset of the TSF - but if the signal
287          * is left high, it will reset the TSF on the next chip reset also!
288          * writing the bit an even number of times fixes this issue
289          */
290         OS_REG_WRITE(ah, AR_BEACON, val | AR_BEACON_RESET_TSF);
291 }
292
293 /*
294  * Set or clear hardware basic rate bit
295  * Set hardware basic rate set if basic rate is found
296  * and basic rate is equal or less than 2Mbps
297  */
298 void
299 ar5212SetBasicRate(struct ath_hal *ah, HAL_RATE_SET *rs)
300 {
301         const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan;
302         uint32_t reg;
303         uint8_t xset;
304         int i;
305
306         if (chan == AH_NULL || !IEEE80211_IS_CHAN_CCK(chan))
307                 return;
308         xset = 0;
309         for (i = 0; i < rs->rs_count; i++) {
310                 uint8_t rset = rs->rs_rates[i];
311                 /* Basic rate defined? */
312                 if ((rset & 0x80) && (rset &= 0x7f) >= xset)
313                         xset = rset;
314         }
315         /*
316          * Set the h/w bit to reflect whether or not the basic
317          * rate is found to be equal or less than 2Mbps.
318          */
319         reg = OS_REG_READ(ah, AR_STA_ID1);
320         if (xset && xset/2 <= 2)
321                 OS_REG_WRITE(ah, AR_STA_ID1, reg | AR_STA_ID1_BASE_RATE_11B);
322         else
323                 OS_REG_WRITE(ah, AR_STA_ID1, reg &~ AR_STA_ID1_BASE_RATE_11B);
324 }
325
326 /*
327  * Grab a semi-random value from hardware registers - may not
328  * change often
329  */
330 uint32_t
331 ar5212GetRandomSeed(struct ath_hal *ah)
332 {
333         uint32_t nf;
334
335         nf = (OS_REG_READ(ah, AR_PHY(25)) >> 19) & 0x1ff;
336         if (nf & 0x100)
337                 nf = 0 - ((nf ^ 0x1ff) + 1);
338         return (OS_REG_READ(ah, AR_TSF_U32) ^
339                 OS_REG_READ(ah, AR_TSF_L32) ^ nf);
340 }
341
342 /*
343  * Detect if our card is present
344  */
345 HAL_BOOL
346 ar5212DetectCardPresent(struct ath_hal *ah)
347 {
348         uint16_t macVersion, macRev;
349         uint32_t v;
350
351         /*
352          * Read the Silicon Revision register and compare that
353          * to what we read at attach time.  If the same, we say
354          * a card/device is present.
355          */
356         v = OS_REG_READ(ah, AR_SREV) & AR_SREV_ID;
357         macVersion = v >> AR_SREV_ID_S;
358         macRev = v & AR_SREV_REVISION;
359         return (AH_PRIVATE(ah)->ah_macVersion == macVersion &&
360                 AH_PRIVATE(ah)->ah_macRev == macRev);
361 }
362
363 void
364 ar5212EnableMibCounters(struct ath_hal *ah)
365 {
366         /* NB: this just resets the mib counter machinery */
367         OS_REG_WRITE(ah, AR_MIBC,
368             ~(AR_MIBC_COW | AR_MIBC_FMC | AR_MIBC_CMC | AR_MIBC_MCS) & 0x0f);
369 }
370
371 void 
372 ar5212DisableMibCounters(struct ath_hal *ah)
373 {
374         OS_REG_WRITE(ah, AR_MIBC,  AR_MIBC | AR_MIBC_CMC);
375 }
376
377 /*
378  * Update MIB Counters
379  */
380 void
381 ar5212UpdateMibCounters(struct ath_hal *ah, HAL_MIB_STATS* stats)
382 {
383         stats->ackrcv_bad += OS_REG_READ(ah, AR_ACK_FAIL);
384         stats->rts_bad    += OS_REG_READ(ah, AR_RTS_FAIL);
385         stats->fcs_bad    += OS_REG_READ(ah, AR_FCS_FAIL);
386         stats->rts_good   += OS_REG_READ(ah, AR_RTS_OK);
387         stats->beacons    += OS_REG_READ(ah, AR_BEACON_CNT);
388 }
389
390 /*
391  * Detect if the HW supports spreading a CCK signal on channel 14
392  */
393 HAL_BOOL
394 ar5212IsJapanChannelSpreadSupported(struct ath_hal *ah)
395 {
396         return AH_TRUE;
397 }
398
399 /*
400  * Get the rssi of frame curently being received.
401  */
402 uint32_t
403 ar5212GetCurRssi(struct ath_hal *ah)
404 {
405         return (OS_REG_READ(ah, AR_PHY_CURRENT_RSSI) & 0xff);
406 }
407
408 u_int
409 ar5212GetDefAntenna(struct ath_hal *ah)
410 {   
411         return (OS_REG_READ(ah, AR_DEF_ANTENNA) & 0x7);
412 }   
413
414 void
415 ar5212SetDefAntenna(struct ath_hal *ah, u_int antenna)
416 {
417         OS_REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7));
418 }
419
420 HAL_ANT_SETTING
421 ar5212GetAntennaSwitch(struct ath_hal *ah)
422 {
423         return AH5212(ah)->ah_antControl;
424 }
425
426 HAL_BOOL
427 ar5212SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING setting)
428 {
429         struct ath_hal_5212 *ahp = AH5212(ah);
430         const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan;
431
432         if (!ahp->ah_phyPowerOn || chan == AH_NULL) {
433                 /* PHY powered off, just stash settings */
434                 ahp->ah_antControl = setting;
435                 ahp->ah_diversity = (setting == HAL_ANT_VARIABLE);
436                 return AH_TRUE;
437         }
438         return ar5212SetAntennaSwitchInternal(ah, setting, chan);
439 }
440
441 HAL_BOOL
442 ar5212IsSleepAfterBeaconBroken(struct ath_hal *ah)
443 {
444         return AH_TRUE;
445 }
446
447 HAL_BOOL
448 ar5212SetSifsTime(struct ath_hal *ah, u_int us)
449 {
450         struct ath_hal_5212 *ahp = AH5212(ah);
451
452         if (us > ath_hal_mac_usec(ah, 0xffff)) {
453                 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad SIFS time %u\n",
454                     __func__, us);
455                 ahp->ah_sifstime = (u_int) -1;  /* restore default handling */
456                 return AH_FALSE;
457         } else {
458                 /* convert to system clocks */
459                 OS_REG_WRITE(ah, AR_D_GBL_IFS_SIFS, ath_hal_mac_clks(ah, us-2));
460                 ahp->ah_sifstime = us;
461                 return AH_TRUE;
462         }
463 }
464
465 u_int
466 ar5212GetSifsTime(struct ath_hal *ah)
467 {
468         u_int clks = OS_REG_READ(ah, AR_D_GBL_IFS_SIFS) & 0xffff;
469         return ath_hal_mac_usec(ah, clks)+2;    /* convert from system clocks */
470 }
471
472 HAL_BOOL
473 ar5212SetSlotTime(struct ath_hal *ah, u_int us)
474 {
475         struct ath_hal_5212 *ahp = AH5212(ah);
476
477         if (us < HAL_SLOT_TIME_6 || us > ath_hal_mac_usec(ah, 0xffff)) {
478                 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad slot time %u\n",
479                     __func__, us);
480                 ahp->ah_slottime = (u_int) -1;  /* restore default handling */
481                 return AH_FALSE;
482         } else {
483                 /* convert to system clocks */
484                 OS_REG_WRITE(ah, AR_D_GBL_IFS_SLOT, ath_hal_mac_clks(ah, us));
485                 ahp->ah_slottime = us;
486                 return AH_TRUE;
487         }
488 }
489
490 u_int
491 ar5212GetSlotTime(struct ath_hal *ah)
492 {
493         u_int clks = OS_REG_READ(ah, AR_D_GBL_IFS_SLOT) & 0xffff;
494         return ath_hal_mac_usec(ah, clks);      /* convert from system clocks */
495 }
496
497 HAL_BOOL
498 ar5212SetAckTimeout(struct ath_hal *ah, u_int us)
499 {
500         struct ath_hal_5212 *ahp = AH5212(ah);
501
502         if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) {
503                 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad ack timeout %u\n",
504                     __func__, us);
505                 ahp->ah_acktimeout = (u_int) -1; /* restore default handling */
506                 return AH_FALSE;
507         } else {
508                 /* convert to system clocks */
509                 OS_REG_RMW_FIELD(ah, AR_TIME_OUT,
510                         AR_TIME_OUT_ACK, ath_hal_mac_clks(ah, us));
511                 ahp->ah_acktimeout = us;
512                 return AH_TRUE;
513         }
514 }
515
516 u_int
517 ar5212GetAckTimeout(struct ath_hal *ah)
518 {
519         u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_ACK);
520         return ath_hal_mac_usec(ah, clks);      /* convert from system clocks */
521 }
522
523 u_int
524 ar5212GetAckCTSRate(struct ath_hal *ah)
525 {
526         return ((AH5212(ah)->ah_staId1Defaults & AR_STA_ID1_ACKCTS_6MB) == 0);
527 }
528
529 HAL_BOOL
530 ar5212SetAckCTSRate(struct ath_hal *ah, u_int high)
531 {
532         struct ath_hal_5212 *ahp = AH5212(ah);
533
534         if (high) {
535                 OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB);
536                 ahp->ah_staId1Defaults &= ~AR_STA_ID1_ACKCTS_6MB;
537         } else {
538                 OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB);
539                 ahp->ah_staId1Defaults |= AR_STA_ID1_ACKCTS_6MB;
540         }
541         return AH_TRUE;
542 }
543
544 HAL_BOOL
545 ar5212SetCTSTimeout(struct ath_hal *ah, u_int us)
546 {
547         struct ath_hal_5212 *ahp = AH5212(ah);
548
549         if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) {
550                 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad cts timeout %u\n",
551                     __func__, us);
552                 ahp->ah_ctstimeout = (u_int) -1; /* restore default handling */
553                 return AH_FALSE;
554         } else {
555                 /* convert to system clocks */
556                 OS_REG_RMW_FIELD(ah, AR_TIME_OUT,
557                         AR_TIME_OUT_CTS, ath_hal_mac_clks(ah, us));
558                 ahp->ah_ctstimeout = us;
559                 return AH_TRUE;
560         }
561 }
562
563 u_int
564 ar5212GetCTSTimeout(struct ath_hal *ah)
565 {
566         u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_CTS);
567         return ath_hal_mac_usec(ah, clks);      /* convert from system clocks */
568 }
569
570 /* Setup decompression for given key index */
571 HAL_BOOL
572 ar5212SetDecompMask(struct ath_hal *ah, uint16_t keyidx, int en)
573 {
574         struct ath_hal_5212 *ahp = AH5212(ah);
575
576         if (keyidx >= HAL_DECOMP_MASK_SIZE)
577                 return AH_FALSE;
578         OS_REG_WRITE(ah, AR_DCM_A, keyidx);
579         OS_REG_WRITE(ah, AR_DCM_D, en ? AR_DCM_D_EN : 0);
580         ahp->ah_decompMask[keyidx] = en;
581
582         return AH_TRUE;
583 }
584
585 /* Setup coverage class */
586 void
587 ar5212SetCoverageClass(struct ath_hal *ah, uint8_t coverageclass, int now)
588 {
589         uint32_t slot, timeout, eifs;
590         u_int clkRate;
591
592         AH_PRIVATE(ah)->ah_coverageClass = coverageclass;
593
594         if (now) {
595                 if (AH_PRIVATE(ah)->ah_coverageClass == 0)
596                         return;
597
598                 /* Don't apply coverage class to non A channels */
599                 if (!IEEE80211_IS_CHAN_A(AH_PRIVATE(ah)->ah_curchan))
600                         return;
601
602                 /* Get core clock rate */
603                 clkRate = ath_hal_mac_clks(ah, 1);
604
605                 /* Compute EIFS */
606                 slot = coverageclass * 3 * clkRate;
607                 eifs = coverageclass * 6 * clkRate;
608                 if (IEEE80211_IS_CHAN_HALF(AH_PRIVATE(ah)->ah_curchan)) {
609                         slot += IFS_SLOT_HALF_RATE;
610                         eifs += IFS_EIFS_HALF_RATE;
611                 } else if (IEEE80211_IS_CHAN_QUARTER(AH_PRIVATE(ah)->ah_curchan)) {
612                         slot += IFS_SLOT_QUARTER_RATE;
613                         eifs += IFS_EIFS_QUARTER_RATE;
614                 } else { /* full rate */
615                         slot += IFS_SLOT_FULL_RATE;
616                         eifs += IFS_EIFS_FULL_RATE;
617                 }
618
619                 /*
620                  * Add additional time for air propagation for ACK and CTS
621                  * timeouts. This value is in core clocks.
622                  */
623                 timeout = ACK_CTS_TIMEOUT_11A + (coverageclass * 3 * clkRate);
624         
625                 /*
626                  * Write the values: slot, eifs, ack/cts timeouts.
627                  */
628                 OS_REG_WRITE(ah, AR_D_GBL_IFS_SLOT, slot);
629                 OS_REG_WRITE(ah, AR_D_GBL_IFS_EIFS, eifs);
630                 OS_REG_WRITE(ah, AR_TIME_OUT,
631                           SM(timeout, AR_TIME_OUT_CTS)
632                         | SM(timeout, AR_TIME_OUT_ACK));
633         }
634 }
635
636 HAL_STATUS
637 ar5212SetQuiet(struct ath_hal *ah, uint32_t period, uint32_t duration,
638     uint32_t nextStart, HAL_QUIET_FLAG flag)
639 {
640         OS_REG_WRITE(ah, AR_QUIET2, period | (duration << AR_QUIET2_QUIET_DUR_S));
641         if (flag & HAL_QUIET_ENABLE) {
642                 OS_REG_WRITE(ah, AR_QUIET1, nextStart | (1 << 16));
643         }
644         else {
645                 OS_REG_WRITE(ah, AR_QUIET1, nextStart);
646         }
647         return HAL_OK;
648 }
649
650 void
651 ar5212SetPCUConfig(struct ath_hal *ah)
652 {
653         ar5212SetOperatingMode(ah, AH_PRIVATE(ah)->ah_opmode);
654 }
655
656 /*
657  * Return whether an external 32KHz crystal should be used
658  * to reduce power consumption when sleeping.  We do so if
659  * the crystal is present (obtained from EEPROM) and if we
660  * are not running as an AP and are configured to use it.
661  */
662 HAL_BOOL
663 ar5212Use32KHzclock(struct ath_hal *ah, HAL_OPMODE opmode)
664 {
665         if (opmode != HAL_M_HOSTAP) {
666                 struct ath_hal_5212 *ahp = AH5212(ah);
667                 return ath_hal_eepromGetFlag(ah, AR_EEP_32KHZCRYSTAL) &&
668                        (ahp->ah_enable32kHzClock == USE_32KHZ ||
669                         ahp->ah_enable32kHzClock == AUTO_32KHZ);
670         } else
671                 return AH_FALSE;
672 }
673
674 /*
675  * If 32KHz clock exists, use it to lower power consumption during sleep
676  *
677  * Note: If clock is set to 32 KHz, delays on accessing certain
678  *       baseband registers (27-31, 124-127) are required.
679  */
680 void
681 ar5212SetupClock(struct ath_hal *ah, HAL_OPMODE opmode)
682 {
683         if (ar5212Use32KHzclock(ah, opmode)) {
684                 /*
685                  * Enable clocks to be turned OFF in BB during sleep
686                  * and also enable turning OFF 32MHz/40MHz Refclk
687                  * from A2.
688                  */
689                 OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f);
690                 OS_REG_WRITE(ah, AR_PHY_REFCLKPD,
691                     IS_RAD5112_ANY(ah) || IS_5413(ah) ? 0x14 : 0x18);
692                 OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32, 1);
693                 OS_REG_WRITE(ah, AR_TSF_PARM, 61);  /* 32 KHz TSF incr */
694                 OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_SEL, 1);
695
696                 if (IS_2413(ah) || IS_5413(ah) || IS_2417(ah)) {
697                         OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT,   0x26);
698                         OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL,        0x0d);
699                         OS_REG_WRITE(ah, AR_PHY_M_SLEEP,           0x07);
700                         OS_REG_WRITE(ah, AR_PHY_REFCLKDLY,         0x3f);
701                         /* # Set sleep clock rate to 32 KHz. */
702                         OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0x2);
703                 } else {
704                         OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT,   0x0a);
705                         OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL,        0x0c);
706                         OS_REG_WRITE(ah, AR_PHY_M_SLEEP,           0x03);
707                         OS_REG_WRITE(ah, AR_PHY_REFCLKDLY,         0x20);
708                         OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0x3);
709                 }
710         } else {
711                 OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0x0);
712                 OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_SEL, 0);
713
714                 OS_REG_WRITE(ah, AR_TSF_PARM, 1);       /* 32MHz TSF inc */
715
716                 OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f);
717                 OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT,   0x7f);
718
719                 if (IS_2417(ah))
720                         OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0a);
721                 else if (IS_HB63(ah))
722                         OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x32);
723                 else
724                         OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e);
725                 OS_REG_WRITE(ah, AR_PHY_M_SLEEP,           0x0c);
726                 OS_REG_WRITE(ah, AR_PHY_REFCLKDLY,         0xff);
727                 OS_REG_WRITE(ah, AR_PHY_REFCLKPD,
728                     IS_RAD5112_ANY(ah) || IS_5413(ah) || IS_2417(ah) ? 0x14 : 0x18);
729                 OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32,
730                     IS_RAD5112_ANY(ah) || IS_5413(ah) ? 39 : 31);
731         }
732 }
733
734 /*
735  * If 32KHz clock exists, turn it off and turn back on the 32Mhz
736  */
737 void
738 ar5212RestoreClock(struct ath_hal *ah, HAL_OPMODE opmode)
739 {
740         if (ar5212Use32KHzclock(ah, opmode)) {
741                 /* # Set sleep clock rate back to 32 MHz. */
742                 OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0);
743                 OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_SEL, 0);
744
745                 OS_REG_WRITE(ah, AR_TSF_PARM, 1);       /* 32 MHz TSF incr */
746                 OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32,
747                     IS_RAD5112_ANY(ah) || IS_5413(ah) ? 39 : 31);
748
749                 /*
750                  * Restore BB registers to power-on defaults
751                  */
752                 OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f);
753                 OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT,   0x7f);
754                 OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL,        0x0e);
755                 OS_REG_WRITE(ah, AR_PHY_M_SLEEP,           0x0c);
756                 OS_REG_WRITE(ah, AR_PHY_REFCLKDLY,         0xff);
757                 OS_REG_WRITE(ah, AR_PHY_REFCLKPD,
758                     IS_RAD5112_ANY(ah) || IS_5413(ah) ?  0x14 : 0x18);
759         }
760 }
761
762 /*
763  * Adjust NF based on statistical values for 5GHz frequencies.
764  * Default method: this may be overridden by the rf backend.
765  */
766 int16_t
767 ar5212GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c)
768 {
769         static const struct {
770                 uint16_t freqLow;
771                 int16_t   adjust;
772         } adjustDef[] = {
773                 { 5790, 11 },   /* NB: ordered high -> low */
774                 { 5730, 10 },
775                 { 5690,  9 },
776                 { 5660,  8 },
777                 { 5610,  7 },
778                 { 5530,  5 },
779                 { 5450,  4 },
780                 { 5379,  2 },
781                 { 5209,  0 },
782                 { 3000,  1 },
783                 {    0,  0 },
784         };
785         int i;
786
787         for (i = 0; c->channel <= adjustDef[i].freqLow; i++)
788                 ;
789         return adjustDef[i].adjust;
790 }
791
792 HAL_STATUS
793 ar5212GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
794         uint32_t capability, uint32_t *result)
795 {
796 #define MACVERSION(ah)  AH_PRIVATE(ah)->ah_macVersion
797         struct ath_hal_5212 *ahp = AH5212(ah);
798         const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
799         const struct ar5212AniState *ani;
800
801         switch (type) {
802         case HAL_CAP_CIPHER:            /* cipher handled in hardware */
803                 switch (capability) {
804                 case HAL_CIPHER_AES_CCM:
805                         return pCap->halCipherAesCcmSupport ?
806                                 HAL_OK : HAL_ENOTSUPP;
807                 case HAL_CIPHER_AES_OCB:
808                 case HAL_CIPHER_TKIP:
809                 case HAL_CIPHER_WEP:
810                 case HAL_CIPHER_MIC:
811                 case HAL_CIPHER_CLR:
812                         return HAL_OK;
813                 default:
814                         return HAL_ENOTSUPP;
815                 }
816         case HAL_CAP_TKIP_MIC:          /* handle TKIP MIC in hardware */
817                 switch (capability) {
818                 case 0:                 /* hardware capability */
819                         return HAL_OK;
820                 case 1:
821                         return (ahp->ah_staId1Defaults &
822                             AR_STA_ID1_CRPT_MIC_ENABLE) ?  HAL_OK : HAL_ENXIO;
823                 }
824                 return HAL_EINVAL;
825         case HAL_CAP_TKIP_SPLIT:        /* hardware TKIP uses split keys */
826                 switch (capability) {
827                 case 0:                 /* hardware capability */
828                         return pCap->halTkipMicTxRxKeySupport ?
829                                 HAL_ENXIO : HAL_OK;
830                 case 1:                 /* current setting */
831                         return (ahp->ah_miscMode &
832                             AR_MISC_MODE_MIC_NEW_LOC_ENABLE) ? HAL_ENXIO : HAL_OK;
833                 }
834                 return HAL_EINVAL;
835         case HAL_CAP_WME_TKIPMIC:       /* hardware can do TKIP MIC w/ WMM */
836                 /* XXX move to capability bit */
837                 return MACVERSION(ah) > AR_SREV_VERSION_VENICE ||
838                     (MACVERSION(ah) == AR_SREV_VERSION_VENICE &&
839                      AH_PRIVATE(ah)->ah_macRev >= 8) ? HAL_OK : HAL_ENOTSUPP;
840         case HAL_CAP_DIVERSITY:         /* hardware supports fast diversity */
841                 switch (capability) {
842                 case 0:                 /* hardware capability */
843                         return HAL_OK;
844                 case 1:                 /* current setting */
845                         return ahp->ah_diversity ? HAL_OK : HAL_ENXIO;
846                 case HAL_CAP_STRONG_DIV:
847                         *result = OS_REG_READ(ah, AR_PHY_RESTART);
848                         *result = MS(*result, AR_PHY_RESTART_DIV_GC);
849                         return HAL_OK;
850                 }
851                 return HAL_EINVAL;
852         case HAL_CAP_DIAG:
853                 *result = AH_PRIVATE(ah)->ah_diagreg;
854                 return HAL_OK;
855         case HAL_CAP_TPC:
856                 switch (capability) {
857                 case 0:                 /* hardware capability */
858                         return HAL_OK;
859                 case 1:
860                         return ahp->ah_tpcEnabled ? HAL_OK : HAL_ENXIO;
861                 }
862                 return HAL_OK;
863         case HAL_CAP_PHYDIAG:           /* radar pulse detection capability */
864                 switch (capability) {
865                 case HAL_CAP_RADAR:
866                         return ath_hal_eepromGetFlag(ah, AR_EEP_AMODE) ?
867                             HAL_OK: HAL_ENXIO;
868                 case HAL_CAP_AR:
869                         return (ath_hal_eepromGetFlag(ah, AR_EEP_GMODE) ||
870                             ath_hal_eepromGetFlag(ah, AR_EEP_BMODE)) ?
871                                HAL_OK: HAL_ENXIO;
872                 }
873                 return HAL_ENXIO;
874         case HAL_CAP_MCAST_KEYSRCH:     /* multicast frame keycache search */
875                 switch (capability) {
876                 case 0:                 /* hardware capability */
877                         return pCap->halMcastKeySrchSupport ? HAL_OK : HAL_ENXIO;
878                 case 1:
879                         return (ahp->ah_staId1Defaults &
880                             AR_STA_ID1_MCAST_KSRCH) ? HAL_OK : HAL_ENXIO;
881                 }
882                 return HAL_EINVAL;
883         case HAL_CAP_TSF_ADJUST:        /* hardware has beacon tsf adjust */
884                 switch (capability) {
885                 case 0:                 /* hardware capability */
886                         return pCap->halTsfAddSupport ? HAL_OK : HAL_ENOTSUPP;
887                 case 1:
888                         return (ahp->ah_miscMode & AR_MISC_MODE_TX_ADD_TSF) ?
889                                 HAL_OK : HAL_ENXIO;
890                 }
891                 return HAL_EINVAL;
892         case HAL_CAP_TPC_ACK:
893                 *result = MS(ahp->ah_macTPC, AR_TPC_ACK);
894                 return HAL_OK;
895         case HAL_CAP_TPC_CTS:
896                 *result = MS(ahp->ah_macTPC, AR_TPC_CTS);
897                 return HAL_OK;
898         case HAL_CAP_INTMIT:            /* interference mitigation */
899                 switch (capability) {
900                 case HAL_CAP_INTMIT_PRESENT:            /* hardware capability */
901                         return HAL_OK;
902                 case HAL_CAP_INTMIT_ENABLE:
903                         return (ahp->ah_procPhyErr & HAL_ANI_ENA) ?
904                                 HAL_OK : HAL_ENXIO;
905                 case HAL_CAP_INTMIT_NOISE_IMMUNITY_LEVEL:
906                 case HAL_CAP_INTMIT_OFDM_WEAK_SIGNAL_LEVEL:
907                 case HAL_CAP_INTMIT_CCK_WEAK_SIGNAL_THR:
908                 case HAL_CAP_INTMIT_FIRSTEP_LEVEL:
909                 case HAL_CAP_INTMIT_SPUR_IMMUNITY_LEVEL:
910                         ani = ar5212AniGetCurrentState(ah);
911                         if (ani == AH_NULL)
912                                 return HAL_ENXIO;
913                         switch (capability) {
914                         case 2: *result = ani->noiseImmunityLevel; break;
915                         case 3: *result = !ani->ofdmWeakSigDetectOff; break;
916                         case 4: *result = ani->cckWeakSigThreshold; break;
917                         case 5: *result = ani->firstepLevel; break;
918                         case 6: *result = ani->spurImmunityLevel; break;
919                         }
920                         return HAL_OK;
921                 }
922                 return HAL_EINVAL;
923         default:
924                 return ath_hal_getcapability(ah, type, capability, result);
925         }
926 #undef MACVERSION
927 }
928
929 HAL_BOOL
930 ar5212SetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
931         uint32_t capability, uint32_t setting, HAL_STATUS *status)
932 {
933 #define N(a)    (sizeof(a)/sizeof(a[0]))
934         struct ath_hal_5212 *ahp = AH5212(ah);
935         const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
936         uint32_t v;
937
938         switch (type) {
939         case HAL_CAP_TKIP_MIC:          /* handle TKIP MIC in hardware */
940                 if (setting)
941                         ahp->ah_staId1Defaults |= AR_STA_ID1_CRPT_MIC_ENABLE;
942                 else
943                         ahp->ah_staId1Defaults &= ~AR_STA_ID1_CRPT_MIC_ENABLE;
944                 return AH_TRUE;
945         case HAL_CAP_TKIP_SPLIT:        /* hardware TKIP uses split keys */
946                 if (!pCap->halTkipMicTxRxKeySupport)
947                         return AH_FALSE;
948                 /* NB: true =>'s use split key cache layout */
949                 if (setting)
950                         ahp->ah_miscMode &= ~AR_MISC_MODE_MIC_NEW_LOC_ENABLE;
951                 else
952                         ahp->ah_miscMode |= AR_MISC_MODE_MIC_NEW_LOC_ENABLE;
953                 /* NB: write here so keys can be setup w/o a reset */
954                 OS_REG_WRITE(ah, AR_MISC_MODE, OS_REG_READ(ah, AR_MISC_MODE) | ahp->ah_miscMode);
955                 return AH_TRUE;
956         case HAL_CAP_DIVERSITY:
957                 switch (capability) {
958                 case 0:
959                         return AH_FALSE;
960                 case 1: /* setting */
961                         if (ahp->ah_phyPowerOn) {
962                                 if (capability == HAL_CAP_STRONG_DIV) {
963                                         v = OS_REG_READ(ah, AR_PHY_CCK_DETECT);
964                                         if (setting)
965                                                 v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
966                                         else
967                                                 v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
968                                         OS_REG_WRITE(ah, AR_PHY_CCK_DETECT, v);
969                                 }
970                         }
971                         ahp->ah_diversity = (setting != 0);
972                         return AH_TRUE;
973
974                 case HAL_CAP_STRONG_DIV:
975                         if (! ahp->ah_phyPowerOn)
976                                 return AH_FALSE;
977                         v = OS_REG_READ(ah, AR_PHY_RESTART);
978                         v &= ~AR_PHY_RESTART_DIV_GC;
979                         v |= SM(setting, AR_PHY_RESTART_DIV_GC);
980                         OS_REG_WRITE(ah, AR_PHY_RESTART, v);
981                         return AH_TRUE;
982                 default:
983                         return AH_FALSE;
984                 }
985         case HAL_CAP_DIAG:              /* hardware diagnostic support */
986                 /*
987                  * NB: could split this up into virtual capabilities,
988                  *     (e.g. 1 => ACK, 2 => CTS, etc.) but it hardly
989                  *     seems worth the additional complexity.
990                  */
991                 AH_PRIVATE(ah)->ah_diagreg = setting;
992                 OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg);
993                 return AH_TRUE;
994         case HAL_CAP_TPC:
995                 ahp->ah_tpcEnabled = (setting != 0);
996                 return AH_TRUE;
997         case HAL_CAP_MCAST_KEYSRCH:     /* multicast frame keycache search */
998                 if (setting)
999                         ahp->ah_staId1Defaults |= AR_STA_ID1_MCAST_KSRCH;
1000                 else
1001                         ahp->ah_staId1Defaults &= ~AR_STA_ID1_MCAST_KSRCH;
1002                 return AH_TRUE;
1003         case HAL_CAP_TPC_ACK:
1004         case HAL_CAP_TPC_CTS:
1005                 setting += ahp->ah_txPowerIndexOffset;
1006                 if (setting > 63)
1007                         setting = 63;
1008                 if (type == HAL_CAP_TPC_ACK) {
1009                         ahp->ah_macTPC &= AR_TPC_ACK;
1010                         ahp->ah_macTPC |= MS(setting, AR_TPC_ACK);
1011                 } else {
1012                         ahp->ah_macTPC &= AR_TPC_CTS;
1013                         ahp->ah_macTPC |= MS(setting, AR_TPC_CTS);
1014                 }
1015                 OS_REG_WRITE(ah, AR_TPC, ahp->ah_macTPC);
1016                 return AH_TRUE;
1017         case HAL_CAP_INTMIT: {          /* interference mitigation */
1018                 /* This maps the public ANI commands to the internal ANI commands */
1019                 /* Private: HAL_ANI_CMD; Public: HAL_CAP_INTMIT_CMD */
1020                 static const HAL_ANI_CMD cmds[] = {
1021                         HAL_ANI_PRESENT,
1022                         HAL_ANI_MODE,
1023                         HAL_ANI_NOISE_IMMUNITY_LEVEL,
1024                         HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
1025                         HAL_ANI_CCK_WEAK_SIGNAL_THR,
1026                         HAL_ANI_FIRSTEP_LEVEL,
1027                         HAL_ANI_SPUR_IMMUNITY_LEVEL,
1028                 };
1029                 return capability < N(cmds) ?
1030                         AH5212(ah)->ah_aniControl(ah, cmds[capability], setting) :
1031                         AH_FALSE;
1032         }
1033         case HAL_CAP_TSF_ADJUST:        /* hardware has beacon tsf adjust */
1034                 if (pCap->halTsfAddSupport) {
1035                         if (setting)
1036                                 ahp->ah_miscMode |= AR_MISC_MODE_TX_ADD_TSF;
1037                         else
1038                                 ahp->ah_miscMode &= ~AR_MISC_MODE_TX_ADD_TSF;
1039                         return AH_TRUE;
1040                 }
1041                 /* fall thru... */
1042         default:
1043                 return ath_hal_setcapability(ah, type, capability,
1044                                 setting, status);
1045         }
1046 #undef N
1047 }
1048
1049 HAL_BOOL
1050 ar5212GetDiagState(struct ath_hal *ah, int request,
1051         const void *args, uint32_t argsize,
1052         void **result, uint32_t *resultsize)
1053 {
1054         struct ath_hal_5212 *ahp = AH5212(ah);
1055
1056         (void) ahp;
1057         if (ath_hal_getdiagstate(ah, request, args, argsize, result, resultsize))
1058                 return AH_TRUE;
1059         switch (request) {
1060         case HAL_DIAG_EEPROM:
1061         case HAL_DIAG_EEPROM_EXP_11A:
1062         case HAL_DIAG_EEPROM_EXP_11B:
1063         case HAL_DIAG_EEPROM_EXP_11G:
1064         case HAL_DIAG_RFGAIN:
1065                 return ath_hal_eepromDiag(ah, request,
1066                     args, argsize, result, resultsize);
1067         case HAL_DIAG_RFGAIN_CURSTEP:
1068                 *result = __DECONST(void *, ahp->ah_gainValues.currStep);
1069                 *resultsize = (*result == AH_NULL) ?
1070                         0 : sizeof(GAIN_OPTIMIZATION_STEP);
1071                 return AH_TRUE;
1072         case HAL_DIAG_PCDAC:
1073                 *result = ahp->ah_pcdacTable;
1074                 *resultsize = ahp->ah_pcdacTableSize;
1075                 return AH_TRUE;
1076         case HAL_DIAG_TXRATES:
1077                 *result = &ahp->ah_ratesArray[0];
1078                 *resultsize = sizeof(ahp->ah_ratesArray);
1079                 return AH_TRUE;
1080         case HAL_DIAG_ANI_CURRENT:
1081                 *result = ar5212AniGetCurrentState(ah);
1082                 *resultsize = (*result == AH_NULL) ?
1083                         0 : sizeof(struct ar5212AniState);
1084                 return AH_TRUE;
1085         case HAL_DIAG_ANI_STATS:
1086                 *result = ar5212AniGetCurrentStats(ah);
1087                 *resultsize = (*result == AH_NULL) ?
1088                         0 : sizeof(struct ar5212Stats);
1089                 return AH_TRUE;
1090         case HAL_DIAG_ANI_CMD:
1091                 if (argsize != 2*sizeof(uint32_t))
1092                         return AH_FALSE;
1093                 AH5212(ah)->ah_aniControl(ah, ((const uint32_t *)args)[0],
1094                         ((const uint32_t *)args)[1]);
1095                 return AH_TRUE;
1096         case HAL_DIAG_ANI_PARAMS:
1097                 /*
1098                  * NB: We assume struct ar5212AniParams is identical
1099                  * to HAL_ANI_PARAMS; if they diverge then we'll need
1100                  * to handle it here
1101                  */
1102                 if (argsize == 0 && args == AH_NULL) {
1103                         struct ar5212AniState *aniState =
1104                             ar5212AniGetCurrentState(ah);
1105                         if (aniState == AH_NULL)
1106                                 return AH_FALSE;
1107                         *result = __DECONST(void *, aniState->params);
1108                         *resultsize = sizeof(struct ar5212AniParams);
1109                         return AH_TRUE;
1110                 } else {
1111                         if (argsize != sizeof(struct ar5212AniParams))
1112                                 return AH_FALSE;
1113                         return ar5212AniSetParams(ah, args, args);
1114                 }
1115                 break;
1116         case HAL_DIAG_CHANSURVEY:
1117                 *result = &ahp->ah_chansurvey;
1118                 *resultsize = sizeof(HAL_CHANNEL_SURVEY);
1119                 return AH_TRUE;
1120         }
1121         return AH_FALSE;
1122 }
1123
1124 /*
1125  * Check whether there's an in-progress NF completion.
1126  *
1127  * Returns AH_TRUE if there's a in-progress NF calibration, AH_FALSE
1128  * otherwise.
1129  */
1130 HAL_BOOL
1131 ar5212IsNFCalInProgress(struct ath_hal *ah)
1132 {
1133         if (OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF)
1134                 return AH_TRUE;
1135         return AH_FALSE;
1136 }
1137
1138 /*
1139  * Wait for an in-progress NF calibration to complete.
1140  *
1141  * The completion function waits "i" times 10uS.
1142  * It returns AH_TRUE if the NF calibration completed (or was never
1143  * in progress); AH_FALSE if it was still in progress after "i" checks.
1144  */
1145 HAL_BOOL
1146 ar5212WaitNFCalComplete(struct ath_hal *ah, int i)
1147 {
1148         int j;
1149         if (i <= 0)
1150                 i = 1;    /* it should run at least once */
1151         for (j = 0; j < i; j++) {
1152                 if (! ar5212IsNFCalInProgress(ah))
1153                         return AH_TRUE;
1154                 OS_DELAY(10);
1155         }
1156         return AH_FALSE;
1157 }
1158
1159 void
1160 ar5212EnableDfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe)
1161 {
1162         uint32_t val;
1163         val = OS_REG_READ(ah, AR_PHY_RADAR_0);
1164
1165         if (pe->pe_firpwr != HAL_PHYERR_PARAM_NOVAL) {
1166                 val &= ~AR_PHY_RADAR_0_FIRPWR;
1167                 val |= SM(pe->pe_firpwr, AR_PHY_RADAR_0_FIRPWR);
1168         }
1169         if (pe->pe_rrssi != HAL_PHYERR_PARAM_NOVAL) {
1170                 val &= ~AR_PHY_RADAR_0_RRSSI;
1171                 val |= SM(pe->pe_rrssi, AR_PHY_RADAR_0_RRSSI);
1172         }
1173         if (pe->pe_height != HAL_PHYERR_PARAM_NOVAL) {
1174                 val &= ~AR_PHY_RADAR_0_HEIGHT;
1175                 val |= SM(pe->pe_height, AR_PHY_RADAR_0_HEIGHT);
1176         }
1177         if (pe->pe_prssi != HAL_PHYERR_PARAM_NOVAL) {
1178                 val &= ~AR_PHY_RADAR_0_PRSSI;
1179                 val |= SM(pe->pe_prssi, AR_PHY_RADAR_0_PRSSI);
1180         }
1181         if (pe->pe_inband != HAL_PHYERR_PARAM_NOVAL) {
1182                 val &= ~AR_PHY_RADAR_0_INBAND;
1183                 val |= SM(pe->pe_inband, AR_PHY_RADAR_0_INBAND);
1184         }
1185         if (pe->pe_enabled)
1186                 val |= AR_PHY_RADAR_0_ENA;
1187         else
1188                 val &= ~ AR_PHY_RADAR_0_ENA;
1189
1190         if (IS_5413(ah)) {
1191
1192                 if (pe->pe_blockradar == 1)
1193                         OS_REG_SET_BIT(ah, AR_PHY_RADAR_2,
1194                             AR_PHY_RADAR_2_BLOCKOFDMWEAK);
1195                 else
1196                         OS_REG_CLR_BIT(ah, AR_PHY_RADAR_2,
1197                             AR_PHY_RADAR_2_BLOCKOFDMWEAK);
1198
1199                 if (pe->pe_en_relstep_check == 1)
1200                         OS_REG_SET_BIT(ah, AR_PHY_RADAR_2,
1201                             AR_PHY_RADAR_2_ENRELSTEPCHK);
1202                 else
1203                         OS_REG_CLR_BIT(ah, AR_PHY_RADAR_2,
1204                             AR_PHY_RADAR_2_ENRELSTEPCHK);
1205
1206                 if (pe->pe_usefir128 == 1)
1207                         OS_REG_SET_BIT(ah, AR_PHY_RADAR_2,
1208                             AR_PHY_RADAR_2_USEFIR128);
1209                 else
1210                         OS_REG_CLR_BIT(ah, AR_PHY_RADAR_2,
1211                             AR_PHY_RADAR_2_USEFIR128);
1212
1213                 if (pe->pe_enmaxrssi == 1)
1214                         OS_REG_SET_BIT(ah, AR_PHY_RADAR_2,
1215                             AR_PHY_RADAR_2_ENMAXRSSI);
1216                 else
1217                         OS_REG_CLR_BIT(ah, AR_PHY_RADAR_2,
1218                             AR_PHY_RADAR_2_ENMAXRSSI);
1219
1220                 if (pe->pe_enrelpwr == 1)
1221                         OS_REG_SET_BIT(ah, AR_PHY_RADAR_2,
1222                             AR_PHY_RADAR_2_ENRELPWRCHK);
1223                 else
1224                         OS_REG_CLR_BIT(ah, AR_PHY_RADAR_2,
1225                             AR_PHY_RADAR_2_ENRELPWRCHK);
1226
1227                 if (pe->pe_relpwr != HAL_PHYERR_PARAM_NOVAL)
1228                         OS_REG_RMW_FIELD(ah, AR_PHY_RADAR_2,
1229                             AR_PHY_RADAR_2_RELPWR, pe->pe_relpwr);
1230
1231                 if (pe->pe_relstep != HAL_PHYERR_PARAM_NOVAL)
1232                         OS_REG_RMW_FIELD(ah, AR_PHY_RADAR_2,
1233                             AR_PHY_RADAR_2_RELSTEP, pe->pe_relstep);
1234
1235                 if (pe->pe_maxlen != HAL_PHYERR_PARAM_NOVAL)
1236                         OS_REG_RMW_FIELD(ah, AR_PHY_RADAR_2,
1237                             AR_PHY_RADAR_2_MAXLEN, pe->pe_maxlen);
1238         }
1239
1240         OS_REG_WRITE(ah, AR_PHY_RADAR_0, val);
1241 }
1242
1243 /*
1244  * Parameters for the AR5212 PHY.
1245  */
1246 #define AR5212_DFS_FIRPWR       -35
1247 #define AR5212_DFS_RRSSI        20
1248 #define AR5212_DFS_HEIGHT       14
1249 #define AR5212_DFS_PRSSI        6
1250 #define AR5212_DFS_INBAND       4
1251
1252 /*
1253  * Default parameters for the AR5413 PHY.
1254  */
1255 #define AR5413_DFS_FIRPWR       -34
1256 #define AR5413_DFS_RRSSI        20
1257 #define AR5413_DFS_HEIGHT       10
1258 #define AR5413_DFS_PRSSI        15
1259 #define AR5413_DFS_INBAND       6
1260 #define AR5413_DFS_RELPWR       8
1261 #define AR5413_DFS_RELSTEP      31
1262 #define AR5413_DFS_MAXLEN       255
1263
1264 HAL_BOOL
1265 ar5212GetDfsDefaultThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe)
1266 {
1267
1268         if (IS_5413(ah)) {
1269                 pe->pe_firpwr = AR5413_DFS_FIRPWR;
1270                 pe->pe_rrssi = AR5413_DFS_RRSSI;
1271                 pe->pe_height = AR5413_DFS_HEIGHT;
1272                 pe->pe_prssi = AR5413_DFS_PRSSI;
1273                 pe->pe_inband = AR5413_DFS_INBAND;
1274                 pe->pe_relpwr = AR5413_DFS_RELPWR;
1275                 pe->pe_relstep = AR5413_DFS_RELSTEP;
1276                 pe->pe_maxlen = AR5413_DFS_MAXLEN;
1277                 pe->pe_usefir128 = 0;
1278                 pe->pe_blockradar = 1;
1279                 pe->pe_enmaxrssi = 1;
1280                 pe->pe_enrelpwr = 1;
1281                 pe->pe_en_relstep_check = 0;
1282         } else {
1283                 pe->pe_firpwr = AR5212_DFS_FIRPWR;
1284                 pe->pe_rrssi = AR5212_DFS_RRSSI;
1285                 pe->pe_height = AR5212_DFS_HEIGHT;
1286                 pe->pe_prssi = AR5212_DFS_PRSSI;
1287                 pe->pe_inband = AR5212_DFS_INBAND;
1288                 pe->pe_relpwr = 0;
1289                 pe->pe_relstep = 0;
1290                 pe->pe_maxlen = 0;
1291                 pe->pe_usefir128 = 0;
1292                 pe->pe_blockradar = 0;
1293                 pe->pe_enmaxrssi = 0;
1294                 pe->pe_enrelpwr = 0;
1295                 pe->pe_en_relstep_check = 0;
1296         }
1297
1298         return (AH_TRUE);
1299 }
1300
1301 void
1302 ar5212GetDfsThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe)
1303 {
1304         uint32_t val,temp;
1305
1306         val = OS_REG_READ(ah, AR_PHY_RADAR_0);
1307
1308         temp = MS(val,AR_PHY_RADAR_0_FIRPWR);
1309         temp |= 0xFFFFFF80;
1310         pe->pe_firpwr = temp;
1311         pe->pe_rrssi = MS(val, AR_PHY_RADAR_0_RRSSI);
1312         pe->pe_height =  MS(val, AR_PHY_RADAR_0_HEIGHT);
1313         pe->pe_prssi = MS(val, AR_PHY_RADAR_0_PRSSI);
1314         pe->pe_inband = MS(val, AR_PHY_RADAR_0_INBAND);
1315         pe->pe_enabled = !! (val & AR_PHY_RADAR_0_ENA);
1316
1317         pe->pe_relpwr = 0;
1318         pe->pe_relstep = 0;
1319         pe->pe_maxlen = 0;
1320         pe->pe_usefir128 = 0;
1321         pe->pe_blockradar = 0;
1322         pe->pe_enmaxrssi = 0;
1323         pe->pe_enrelpwr = 0;
1324         pe->pe_en_relstep_check = 0;
1325         pe->pe_extchannel = AH_FALSE;
1326
1327         if (IS_5413(ah)) {
1328                 val = OS_REG_READ(ah, AR_PHY_RADAR_2);
1329                 pe->pe_relpwr = !! MS(val, AR_PHY_RADAR_2_RELPWR);
1330                 pe->pe_relstep = !! MS(val, AR_PHY_RADAR_2_RELSTEP);
1331                 pe->pe_maxlen = !! MS(val, AR_PHY_RADAR_2_MAXLEN);
1332
1333                 pe->pe_usefir128 = !! (val & AR_PHY_RADAR_2_USEFIR128);
1334                 pe->pe_blockradar = !! (val & AR_PHY_RADAR_2_BLOCKOFDMWEAK);
1335                 pe->pe_enmaxrssi = !! (val & AR_PHY_RADAR_2_ENMAXRSSI);
1336                 pe->pe_enrelpwr = !! (val & AR_PHY_RADAR_2_ENRELPWRCHK);
1337                 pe->pe_en_relstep_check =
1338                     !! (val & AR_PHY_RADAR_2_ENRELSTEPCHK);
1339         }
1340 }
1341
1342 /*
1343  * Process the radar phy error and extract the pulse duration.
1344  */
1345 HAL_BOOL
1346 ar5212ProcessRadarEvent(struct ath_hal *ah, struct ath_rx_status *rxs,
1347     uint64_t fulltsf, const char *buf, HAL_DFS_EVENT *event)
1348 {
1349         uint8_t dur;
1350         uint8_t rssi;
1351
1352         /* Check whether the given phy error is a radar event */
1353         if ((rxs->rs_phyerr != HAL_PHYERR_RADAR) &&
1354             (rxs->rs_phyerr != HAL_PHYERR_FALSE_RADAR_EXT))
1355                 return AH_FALSE;
1356
1357         /*
1358          * The first byte is the pulse width - if there's
1359          * no data, simply set the duration to 0
1360          */
1361         if (rxs->rs_datalen >= 1)
1362                 /* The pulse width is byte 0 of the data */
1363                 dur = ((uint8_t) buf[0]) & 0xff;
1364         else
1365                 dur = 0;
1366
1367         /* Pulse RSSI is the normal reported RSSI */
1368         rssi = (uint8_t) rxs->rs_rssi;
1369
1370         /* 0 duration/rssi is not a valid radar event */
1371         if (dur == 0 && rssi == 0)
1372                 return AH_FALSE;
1373
1374         HALDEBUG(ah, HAL_DEBUG_DFS, "%s: rssi=%d, dur=%d\n",
1375             __func__, rssi, dur);
1376
1377         /* Record the event */
1378         event->re_full_ts = fulltsf;
1379         event->re_ts = rxs->rs_tstamp;
1380         event->re_rssi = rssi;
1381         event->re_dur = dur;
1382         event->re_flags = HAL_DFS_EVENT_PRICH;
1383
1384         return AH_TRUE;
1385 }
1386
1387 /*
1388  * Return whether 5GHz fast-clock (44MHz) is enabled.
1389  * It's always disabled for AR5212 series NICs.
1390  */
1391 HAL_BOOL
1392 ar5212IsFastClockEnabled(struct ath_hal *ah)
1393 {
1394         return AH_FALSE;
1395 }
1396
1397 /*
1398  * Return what percentage of the extension channel is busy.
1399  * This is always disabled for AR5212 series NICs.
1400  */
1401 uint32_t
1402 ar5212Get11nExtBusy(struct ath_hal *ah)
1403 {
1404         return 0;
1405 }
1406
1407 /*
1408  * Channel survey support.
1409  */
1410 HAL_BOOL
1411 ar5212GetMibCycleCounts(struct ath_hal *ah, HAL_SURVEY_SAMPLE *hsample)
1412 {
1413         struct ath_hal_5212 *ahp = AH5212(ah);
1414         u_int32_t good = AH_TRUE;
1415
1416         /* XXX freeze/unfreeze mib counters */
1417         uint32_t rc = OS_REG_READ(ah, AR_RCCNT);
1418         uint32_t rf = OS_REG_READ(ah, AR_RFCNT);
1419         uint32_t tf = OS_REG_READ(ah, AR_TFCNT);
1420         uint32_t cc = OS_REG_READ(ah, AR_CCCNT); /* read cycles last */
1421
1422         if (ahp->ah_cycleCount == 0 || ahp->ah_cycleCount > cc) {
1423                 /*
1424                  * Cycle counter wrap (or initial call); it's not possible
1425                  * to accurately calculate a value because the registers
1426                  * right shift rather than wrap--so punt and return 0.
1427                  */
1428                 HALDEBUG(ah, HAL_DEBUG_ANY,
1429                     "%s: cycle counter wrap. ExtBusy = 0\n", __func__);
1430                 good = AH_FALSE;
1431         } else {
1432                 hsample->cycle_count = cc - ahp->ah_cycleCount;
1433                 hsample->chan_busy = rc - ahp->ah_ctlBusy;
1434                 hsample->ext_chan_busy = 0;
1435                 hsample->rx_busy = rf - ahp->ah_rxBusy;
1436                 hsample->tx_busy = tf - ahp->ah_txBusy;
1437         }
1438
1439         /*
1440          * Keep a copy of the MIB results so the next sample has something
1441          * to work from.
1442          */
1443         ahp->ah_cycleCount = cc;
1444         ahp->ah_rxBusy = rf;
1445         ahp->ah_ctlBusy = rc;
1446         ahp->ah_txBusy = tf;
1447
1448         return (good);
1449 }
1450
1451 void
1452 ar5212SetChainMasks(struct ath_hal *ah, uint32_t tx_chainmask,
1453     uint32_t rx_chainmask)
1454 {
1455 }