]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/ath/ath_hal/ah.c
Merge ACPICA 20120711.
[FreeBSD/FreeBSD.git] / sys / dev / ath / ath_hal / ah.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_eeprom.h"                  /* for 5ghz fast clock flag */
25
26 #include "ar5416/ar5416reg.h"           /* NB: includes ar5212reg.h */
27
28 /* linker set of registered chips */
29 OS_SET_DECLARE(ah_chips, struct ath_hal_chip);
30
31 /*
32  * Check the set of registered chips to see if any recognize
33  * the device as one they can support.
34  */
35 const char*
36 ath_hal_probe(uint16_t vendorid, uint16_t devid)
37 {
38         struct ath_hal_chip * const *pchip;
39
40         OS_SET_FOREACH(pchip, ah_chips) {
41                 const char *name = (*pchip)->probe(vendorid, devid);
42                 if (name != AH_NULL)
43                         return name;
44         }
45         return AH_NULL;
46 }
47
48 /*
49  * Attach detects device chip revisions, initializes the hwLayer
50  * function list, reads EEPROM information,
51  * selects reset vectors, and performs a short self test.
52  * Any failures will return an error that should cause a hardware
53  * disable.
54  */
55 struct ath_hal*
56 ath_hal_attach(uint16_t devid, HAL_SOFTC sc,
57         HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, HAL_STATUS *error)
58 {
59         struct ath_hal_chip * const *pchip;
60
61         OS_SET_FOREACH(pchip, ah_chips) {
62                 struct ath_hal_chip *chip = *pchip;
63                 struct ath_hal *ah;
64
65                 /* XXX don't have vendorid, assume atheros one works */
66                 if (chip->probe(ATHEROS_VENDOR_ID, devid) == AH_NULL)
67                         continue;
68                 ah = chip->attach(devid, sc, st, sh, eepromdata, error);
69                 if (ah != AH_NULL) {
70                         /* copy back private state to public area */
71                         ah->ah_devid = AH_PRIVATE(ah)->ah_devid;
72                         ah->ah_subvendorid = AH_PRIVATE(ah)->ah_subvendorid;
73                         ah->ah_macVersion = AH_PRIVATE(ah)->ah_macVersion;
74                         ah->ah_macRev = AH_PRIVATE(ah)->ah_macRev;
75                         ah->ah_phyRev = AH_PRIVATE(ah)->ah_phyRev;
76                         ah->ah_analog5GhzRev = AH_PRIVATE(ah)->ah_analog5GhzRev;
77                         ah->ah_analog2GhzRev = AH_PRIVATE(ah)->ah_analog2GhzRev;
78                         return ah;
79                 }
80         }
81         return AH_NULL;
82 }
83
84 const char *
85 ath_hal_mac_name(struct ath_hal *ah)
86 {
87         switch (ah->ah_macVersion) {
88         case AR_SREV_VERSION_CRETE:
89         case AR_SREV_VERSION_MAUI_1:
90                 return "5210";
91         case AR_SREV_VERSION_MAUI_2:
92         case AR_SREV_VERSION_OAHU:
93                 return "5211";
94         case AR_SREV_VERSION_VENICE:
95                 return "5212";
96         case AR_SREV_VERSION_GRIFFIN:
97                 return "2413";
98         case AR_SREV_VERSION_CONDOR:
99                 return "5424";
100         case AR_SREV_VERSION_EAGLE:
101                 return "5413";
102         case AR_SREV_VERSION_COBRA:
103                 return "2415";
104         case AR_SREV_2425:
105                 return "2425";
106         case AR_SREV_2417:
107                 return "2417";
108         case AR_XSREV_VERSION_OWL_PCI:
109                 return "5416";
110         case AR_XSREV_VERSION_OWL_PCIE:
111                 return "5418";
112         case AR_XSREV_VERSION_HOWL:
113                 return "9130";
114         case AR_XSREV_VERSION_SOWL:
115                 return "9160";
116         case AR_XSREV_VERSION_MERLIN:
117                 if (AH_PRIVATE(ah)->ah_ispcie)
118                         return "9280";
119                 return "9220";
120         case AR_XSREV_VERSION_KITE:
121                 return "9285";
122         case AR_XSREV_VERSION_KIWI:
123                 if (AH_PRIVATE(ah)->ah_ispcie)
124                         return "9287";
125                 return "9227";
126         }
127         return "????";
128 }
129
130 /*
131  * Return the mask of available modes based on the hardware capabilities.
132  */
133 u_int
134 ath_hal_getwirelessmodes(struct ath_hal*ah)
135 {
136         return ath_hal_getWirelessModes(ah);
137 }
138
139 /* linker set of registered RF backends */
140 OS_SET_DECLARE(ah_rfs, struct ath_hal_rf);
141
142 /*
143  * Check the set of registered RF backends to see if
144  * any recognize the device as one they can support.
145  */
146 struct ath_hal_rf *
147 ath_hal_rfprobe(struct ath_hal *ah, HAL_STATUS *ecode)
148 {
149         struct ath_hal_rf * const *prf;
150
151         OS_SET_FOREACH(prf, ah_rfs) {
152                 struct ath_hal_rf *rf = *prf;
153                 if (rf->probe(ah))
154                         return rf;
155         }
156         *ecode = HAL_ENOTSUPP;
157         return AH_NULL;
158 }
159
160 const char *
161 ath_hal_rf_name(struct ath_hal *ah)
162 {
163         switch (ah->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) {
164         case 0:                 /* 5210 */
165                 return "5110";  /* NB: made up */
166         case AR_RAD5111_SREV_MAJOR:
167         case AR_RAD5111_SREV_PROD:
168                 return "5111";
169         case AR_RAD2111_SREV_MAJOR:
170                 return "2111";
171         case AR_RAD5112_SREV_MAJOR:
172         case AR_RAD5112_SREV_2_0:
173         case AR_RAD5112_SREV_2_1:
174                 return "5112";
175         case AR_RAD2112_SREV_MAJOR:
176         case AR_RAD2112_SREV_2_0:
177         case AR_RAD2112_SREV_2_1:
178                 return "2112";
179         case AR_RAD2413_SREV_MAJOR:
180                 return "2413";
181         case AR_RAD5413_SREV_MAJOR:
182                 return "5413";
183         case AR_RAD2316_SREV_MAJOR:
184                 return "2316";
185         case AR_RAD2317_SREV_MAJOR:
186                 return "2317";
187         case AR_RAD5424_SREV_MAJOR:
188                 return "5424";
189
190         case AR_RAD5133_SREV_MAJOR:
191                 return "5133";
192         case AR_RAD2133_SREV_MAJOR:
193                 return "2133";
194         case AR_RAD5122_SREV_MAJOR:
195                 return "5122";
196         case AR_RAD2122_SREV_MAJOR:
197                 return "2122";
198         }
199         return "????";
200 }
201
202 /*
203  * Poll the register looking for a specific value.
204  */
205 HAL_BOOL
206 ath_hal_wait(struct ath_hal *ah, u_int reg, uint32_t mask, uint32_t val)
207 {
208 #define AH_TIMEOUT      1000
209         return ath_hal_waitfor(ah, reg, mask, val, AH_TIMEOUT);
210 #undef AH_TIMEOUT
211 }
212
213 HAL_BOOL
214 ath_hal_waitfor(struct ath_hal *ah, u_int reg, uint32_t mask, uint32_t val, uint32_t timeout)
215 {
216         int i;
217
218         for (i = 0; i < timeout; i++) {
219                 if ((OS_REG_READ(ah, reg) & mask) == val)
220                         return AH_TRUE;
221                 OS_DELAY(10);
222         }
223         HALDEBUG(ah, HAL_DEBUG_REGIO | HAL_DEBUG_PHYIO,
224             "%s: timeout on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n",
225             __func__, reg, OS_REG_READ(ah, reg), mask, val);
226         return AH_FALSE;
227 }
228
229 /*
230  * Reverse the bits starting at the low bit for a value of
231  * bit_count in size
232  */
233 uint32_t
234 ath_hal_reverseBits(uint32_t val, uint32_t n)
235 {
236         uint32_t retval;
237         int i;
238
239         for (i = 0, retval = 0; i < n; i++) {
240                 retval = (retval << 1) | (val & 1);
241                 val >>= 1;
242         }
243         return retval;
244 }
245
246 /* 802.11n related timing definitions */
247
248 #define OFDM_PLCP_BITS  22
249 #define HT_L_STF        8
250 #define HT_L_LTF        8
251 #define HT_L_SIG        4
252 #define HT_SIG          8
253 #define HT_STF          4
254 #define HT_LTF(n)       ((n) * 4)
255
256 #define HT_RC_2_MCS(_rc)        ((_rc) & 0xf)
257 #define HT_RC_2_STREAMS(_rc)    ((((_rc) & 0x78) >> 3) + 1)
258 #define IS_HT_RATE(_rc)         ( (_rc) & IEEE80211_RATE_MCS)
259
260 /*
261  * Calculate the duration of a packet whether it is 11n or legacy.
262  */
263 uint32_t
264 ath_hal_pkt_txtime(struct ath_hal *ah, const HAL_RATE_TABLE *rates, uint32_t frameLen,
265     uint16_t rateix, HAL_BOOL isht40, HAL_BOOL shortPreamble)
266 {
267         uint8_t rc;
268         int numStreams;
269
270         rc = rates->info[rateix].rateCode;
271
272         /* Legacy rate? Return the old way */
273         if (! IS_HT_RATE(rc))
274                 return ath_hal_computetxtime(ah, rates, frameLen, rateix, shortPreamble);
275
276         /* 11n frame - extract out the number of spatial streams */
277         numStreams = HT_RC_2_STREAMS(rc);
278         KASSERT(numStreams == 1 || numStreams == 2, ("number of spatial streams needs to be 1 or 2: MCS rate 0x%x!", rateix));
279
280         return ath_computedur_ht(frameLen, rc, numStreams, isht40, shortPreamble);
281 }
282
283 /*
284  * Calculate the transmit duration of an 11n frame.
285  * This only works for MCS0->MCS15.
286  */
287 uint32_t
288 ath_computedur_ht(uint32_t frameLen, uint16_t rate, int streams, HAL_BOOL isht40,
289     HAL_BOOL isShortGI)
290 {
291         static const uint16_t ht20_bps[16] = {
292             26, 52, 78, 104, 156, 208, 234, 260,
293             52, 104, 156, 208, 312, 416, 468, 520
294         };
295         static const uint16_t ht40_bps[16] = {
296             54, 108, 162, 216, 324, 432, 486, 540,
297             108, 216, 324, 432, 648, 864, 972, 1080,
298         };
299         uint32_t bitsPerSymbol, numBits, numSymbols, txTime;
300
301         KASSERT(rate & IEEE80211_RATE_MCS, ("not mcs %d", rate));
302         KASSERT((rate &~ IEEE80211_RATE_MCS) < 16, ("bad mcs 0x%x", rate));
303
304         if (isht40)
305                 bitsPerSymbol = ht40_bps[rate & 0xf];
306         else
307                 bitsPerSymbol = ht20_bps[rate & 0xf];
308         numBits = OFDM_PLCP_BITS + (frameLen << 3);
309         numSymbols = howmany(numBits, bitsPerSymbol);
310         if (isShortGI)
311                 txTime = ((numSymbols * 18) + 4) / 5;   /* 3.6us */
312         else
313                 txTime = numSymbols * 4;                /* 4us */
314         return txTime + HT_L_STF + HT_L_LTF +
315             HT_L_SIG + HT_SIG + HT_STF + HT_LTF(streams);
316 }
317
318 /*
319  * Compute the time to transmit a frame of length frameLen bytes
320  * using the specified rate, phy, and short preamble setting.
321  */
322 uint16_t
323 ath_hal_computetxtime(struct ath_hal *ah,
324         const HAL_RATE_TABLE *rates, uint32_t frameLen, uint16_t rateix,
325         HAL_BOOL shortPreamble)
326 {
327         uint32_t bitsPerSymbol, numBits, numSymbols, phyTime, txTime;
328         uint32_t kbps;
329
330         /* Warn if this function is called for 11n rates; it should not be! */
331         if (IS_HT_RATE(rates->info[rateix].rateCode))
332                 ath_hal_printf(ah, "%s: MCS rate? (index %d; hwrate 0x%x)\n",
333                     __func__, rateix, rates->info[rateix].rateCode);
334
335         kbps = rates->info[rateix].rateKbps;
336         /*
337          * index can be invalid duting dynamic Turbo transitions. 
338          * XXX
339          */
340         if (kbps == 0)
341                 return 0;
342         switch (rates->info[rateix].phy) {
343         case IEEE80211_T_CCK:
344                 phyTime         = CCK_PREAMBLE_BITS + CCK_PLCP_BITS;
345                 if (shortPreamble && rates->info[rateix].shortPreamble)
346                         phyTime >>= 1;
347                 numBits         = frameLen << 3;
348                 txTime          = CCK_SIFS_TIME + phyTime
349                                 + ((numBits * 1000)/kbps);
350                 break;
351         case IEEE80211_T_OFDM:
352                 bitsPerSymbol   = (kbps * OFDM_SYMBOL_TIME) / 1000;
353                 HALASSERT(bitsPerSymbol != 0);
354
355                 numBits         = OFDM_PLCP_BITS + (frameLen << 3);
356                 numSymbols      = howmany(numBits, bitsPerSymbol);
357                 txTime          = OFDM_SIFS_TIME
358                                 + OFDM_PREAMBLE_TIME
359                                 + (numSymbols * OFDM_SYMBOL_TIME);
360                 break;
361         case IEEE80211_T_OFDM_HALF:
362                 bitsPerSymbol   = (kbps * OFDM_HALF_SYMBOL_TIME) / 1000;
363                 HALASSERT(bitsPerSymbol != 0);
364
365                 numBits         = OFDM_HALF_PLCP_BITS + (frameLen << 3);
366                 numSymbols      = howmany(numBits, bitsPerSymbol);
367                 txTime          = OFDM_HALF_SIFS_TIME
368                                 + OFDM_HALF_PREAMBLE_TIME
369                                 + (numSymbols * OFDM_HALF_SYMBOL_TIME);
370                 break;
371         case IEEE80211_T_OFDM_QUARTER:
372                 bitsPerSymbol   = (kbps * OFDM_QUARTER_SYMBOL_TIME) / 1000;
373                 HALASSERT(bitsPerSymbol != 0);
374
375                 numBits         = OFDM_QUARTER_PLCP_BITS + (frameLen << 3);
376                 numSymbols      = howmany(numBits, bitsPerSymbol);
377                 txTime          = OFDM_QUARTER_SIFS_TIME
378                                 + OFDM_QUARTER_PREAMBLE_TIME
379                                 + (numSymbols * OFDM_QUARTER_SYMBOL_TIME);
380                 break;
381         case IEEE80211_T_TURBO:
382                 bitsPerSymbol   = (kbps * TURBO_SYMBOL_TIME) / 1000;
383                 HALASSERT(bitsPerSymbol != 0);
384
385                 numBits         = TURBO_PLCP_BITS + (frameLen << 3);
386                 numSymbols      = howmany(numBits, bitsPerSymbol);
387                 txTime          = TURBO_SIFS_TIME
388                                 + TURBO_PREAMBLE_TIME
389                                 + (numSymbols * TURBO_SYMBOL_TIME);
390                 break;
391         default:
392                 HALDEBUG(ah, HAL_DEBUG_PHYIO,
393                     "%s: unknown phy %u (rate ix %u)\n",
394                     __func__, rates->info[rateix].phy, rateix);
395                 txTime = 0;
396                 break;
397         }
398         return txTime;
399 }
400
401 typedef enum {
402         WIRELESS_MODE_11a   = 0,
403         WIRELESS_MODE_TURBO = 1,
404         WIRELESS_MODE_11b   = 2,
405         WIRELESS_MODE_11g   = 3,
406         WIRELESS_MODE_108g  = 4,
407
408         WIRELESS_MODE_MAX
409 } WIRELESS_MODE;
410
411 static WIRELESS_MODE
412 ath_hal_chan2wmode(struct ath_hal *ah, const struct ieee80211_channel *chan)
413 {
414         if (IEEE80211_IS_CHAN_B(chan))
415                 return WIRELESS_MODE_11b;
416         if (IEEE80211_IS_CHAN_G(chan))
417                 return WIRELESS_MODE_11g;
418         if (IEEE80211_IS_CHAN_108G(chan))
419                 return WIRELESS_MODE_108g;
420         if (IEEE80211_IS_CHAN_TURBO(chan))
421                 return WIRELESS_MODE_TURBO;
422         return WIRELESS_MODE_11a;
423 }
424
425 /*
426  * Convert between microseconds and core system clocks.
427  */
428                                      /* 11a Turbo  11b  11g  108g */
429 static const uint8_t CLOCK_RATE[]  = { 40,  80,   22,  44,   88  };
430
431 #define CLOCK_FAST_RATE_5GHZ_OFDM       44
432
433 u_int
434 ath_hal_mac_clks(struct ath_hal *ah, u_int usecs)
435 {
436         const struct ieee80211_channel *c = AH_PRIVATE(ah)->ah_curchan;
437         u_int clks;
438
439         /* NB: ah_curchan may be null when called attach time */
440         /* XXX merlin and later specific workaround - 5ghz fast clock is 44 */
441         if (c != AH_NULL && IS_5GHZ_FAST_CLOCK_EN(ah, c)) {
442                 clks = usecs * CLOCK_FAST_RATE_5GHZ_OFDM;
443                 if (IEEE80211_IS_CHAN_HT40(c))
444                         clks <<= 1;
445         } else if (c != AH_NULL) {
446                 clks = usecs * CLOCK_RATE[ath_hal_chan2wmode(ah, c)];
447                 if (IEEE80211_IS_CHAN_HT40(c))
448                         clks <<= 1;
449         } else
450                 clks = usecs * CLOCK_RATE[WIRELESS_MODE_11b];
451         return clks;
452 }
453
454 u_int
455 ath_hal_mac_usec(struct ath_hal *ah, u_int clks)
456 {
457         const struct ieee80211_channel *c = AH_PRIVATE(ah)->ah_curchan;
458         u_int usec;
459
460         /* NB: ah_curchan may be null when called attach time */
461         /* XXX merlin and later specific workaround - 5ghz fast clock is 44 */
462         if (c != AH_NULL && IS_5GHZ_FAST_CLOCK_EN(ah, c)) {
463                 usec = clks / CLOCK_FAST_RATE_5GHZ_OFDM;
464                 if (IEEE80211_IS_CHAN_HT40(c))
465                         usec >>= 1;
466         } else if (c != AH_NULL) {
467                 usec = clks / CLOCK_RATE[ath_hal_chan2wmode(ah, c)];
468                 if (IEEE80211_IS_CHAN_HT40(c))
469                         usec >>= 1;
470         } else
471                 usec = clks / CLOCK_RATE[WIRELESS_MODE_11b];
472         return usec;
473 }
474
475 /*
476  * Setup a h/w rate table's reverse lookup table and
477  * fill in ack durations.  This routine is called for
478  * each rate table returned through the ah_getRateTable
479  * method.  The reverse lookup tables are assumed to be
480  * initialized to zero (or at least the first entry).
481  * We use this as a key that indicates whether or not
482  * we've previously setup the reverse lookup table.
483  *
484  * XXX not reentrant, but shouldn't matter
485  */
486 void
487 ath_hal_setupratetable(struct ath_hal *ah, HAL_RATE_TABLE *rt)
488 {
489 #define N(a)    (sizeof(a)/sizeof(a[0]))
490         int i;
491
492         if (rt->rateCodeToIndex[0] != 0)        /* already setup */
493                 return;
494         for (i = 0; i < N(rt->rateCodeToIndex); i++)
495                 rt->rateCodeToIndex[i] = (uint8_t) -1;
496         for (i = 0; i < rt->rateCount; i++) {
497                 uint8_t code = rt->info[i].rateCode;
498                 uint8_t cix = rt->info[i].controlRate;
499
500                 HALASSERT(code < N(rt->rateCodeToIndex));
501                 rt->rateCodeToIndex[code] = i;
502                 HALASSERT((code | rt->info[i].shortPreamble) <
503                     N(rt->rateCodeToIndex));
504                 rt->rateCodeToIndex[code | rt->info[i].shortPreamble] = i;
505                 /*
506                  * XXX for 11g the control rate to use for 5.5 and 11 Mb/s
507                  *     depends on whether they are marked as basic rates;
508                  *     the static tables are setup with an 11b-compatible
509                  *     2Mb/s rate which will work but is suboptimal
510                  */
511                 rt->info[i].lpAckDuration = ath_hal_computetxtime(ah, rt,
512                         WLAN_CTRL_FRAME_SIZE, cix, AH_FALSE);
513                 rt->info[i].spAckDuration = ath_hal_computetxtime(ah, rt,
514                         WLAN_CTRL_FRAME_SIZE, cix, AH_TRUE);
515         }
516 #undef N
517 }
518
519 HAL_STATUS
520 ath_hal_getcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
521         uint32_t capability, uint32_t *result)
522 {
523         const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
524
525         switch (type) {
526         case HAL_CAP_REG_DMN:           /* regulatory domain */
527                 *result = AH_PRIVATE(ah)->ah_currentRD;
528                 return HAL_OK;
529         case HAL_CAP_DFS_DMN:           /* DFS Domain */
530                 *result = AH_PRIVATE(ah)->ah_dfsDomain;
531                 return HAL_OK;
532         case HAL_CAP_CIPHER:            /* cipher handled in hardware */
533         case HAL_CAP_TKIP_MIC:          /* handle TKIP MIC in hardware */
534                 return HAL_ENOTSUPP;
535         case HAL_CAP_TKIP_SPLIT:        /* hardware TKIP uses split keys */
536                 return HAL_ENOTSUPP;
537         case HAL_CAP_PHYCOUNTERS:       /* hardware PHY error counters */
538                 return pCap->halHwPhyCounterSupport ? HAL_OK : HAL_ENXIO;
539         case HAL_CAP_WME_TKIPMIC:   /* hardware can do TKIP MIC when WMM is turned on */
540                 return HAL_ENOTSUPP;
541         case HAL_CAP_DIVERSITY:         /* hardware supports fast diversity */
542                 return HAL_ENOTSUPP;
543         case HAL_CAP_KEYCACHE_SIZE:     /* hardware key cache size */
544                 *result =  pCap->halKeyCacheSize;
545                 return HAL_OK;
546         case HAL_CAP_NUM_TXQUEUES:      /* number of hardware tx queues */
547                 *result = pCap->halTotalQueues;
548                 return HAL_OK;
549         case HAL_CAP_VEOL:              /* hardware supports virtual EOL */
550                 return pCap->halVEOLSupport ? HAL_OK : HAL_ENOTSUPP;
551         case HAL_CAP_PSPOLL:            /* hardware PS-Poll support works */
552                 return pCap->halPSPollBroken ? HAL_ENOTSUPP : HAL_OK;
553         case HAL_CAP_COMPRESSION:
554                 return pCap->halCompressSupport ? HAL_OK : HAL_ENOTSUPP;
555         case HAL_CAP_BURST:
556                 return pCap->halBurstSupport ? HAL_OK : HAL_ENOTSUPP;
557         case HAL_CAP_FASTFRAME:
558                 return pCap->halFastFramesSupport ? HAL_OK : HAL_ENOTSUPP;
559         case HAL_CAP_DIAG:              /* hardware diagnostic support */
560                 *result = AH_PRIVATE(ah)->ah_diagreg;
561                 return HAL_OK;
562         case HAL_CAP_TXPOW:             /* global tx power limit  */
563                 switch (capability) {
564                 case 0:                 /* facility is supported */
565                         return HAL_OK;
566                 case 1:                 /* current limit */
567                         *result = AH_PRIVATE(ah)->ah_powerLimit;
568                         return HAL_OK;
569                 case 2:                 /* current max tx power */
570                         *result = AH_PRIVATE(ah)->ah_maxPowerLevel;
571                         return HAL_OK;
572                 case 3:                 /* scale factor */
573                         *result = AH_PRIVATE(ah)->ah_tpScale;
574                         return HAL_OK;
575                 }
576                 return HAL_ENOTSUPP;
577         case HAL_CAP_BSSIDMASK:         /* hardware supports bssid mask */
578                 return pCap->halBssIdMaskSupport ? HAL_OK : HAL_ENOTSUPP;
579         case HAL_CAP_MCAST_KEYSRCH:     /* multicast frame keycache search */
580                 return pCap->halMcastKeySrchSupport ? HAL_OK : HAL_ENOTSUPP;
581         case HAL_CAP_TSF_ADJUST:        /* hardware has beacon tsf adjust */
582                 return HAL_ENOTSUPP;
583         case HAL_CAP_RFSILENT:          /* rfsilent support  */
584                 switch (capability) {
585                 case 0:                 /* facility is supported */
586                         return pCap->halRfSilentSupport ? HAL_OK : HAL_ENOTSUPP;
587                 case 1:                 /* current setting */
588                         return AH_PRIVATE(ah)->ah_rfkillEnabled ?
589                                 HAL_OK : HAL_ENOTSUPP;
590                 case 2:                 /* rfsilent config */
591                         *result = AH_PRIVATE(ah)->ah_rfsilent;
592                         return HAL_OK;
593                 }
594                 return HAL_ENOTSUPP;
595         case HAL_CAP_11D:
596                 return HAL_OK;
597
598         case HAL_CAP_HT:
599                 return pCap->halHTSupport ? HAL_OK : HAL_ENOTSUPP;
600         case HAL_CAP_GTXTO:
601                 return pCap->halGTTSupport ? HAL_OK : HAL_ENOTSUPP;
602         case HAL_CAP_FAST_CC:
603                 return pCap->halFastCCSupport ? HAL_OK : HAL_ENOTSUPP;
604         case HAL_CAP_TX_CHAINMASK:      /* mask of TX chains supported */
605                 *result = pCap->halTxChainMask;
606                 return HAL_OK;
607         case HAL_CAP_RX_CHAINMASK:      /* mask of RX chains supported */
608                 *result = pCap->halRxChainMask;
609                 return HAL_OK;
610         case HAL_CAP_NUM_GPIO_PINS:
611                 *result = pCap->halNumGpioPins;
612                 return HAL_OK;
613         case HAL_CAP_CST:
614                 return pCap->halCSTSupport ? HAL_OK : HAL_ENOTSUPP;
615         case HAL_CAP_RTS_AGGR_LIMIT:
616                 *result = pCap->halRtsAggrLimit;
617                 return HAL_OK;
618         case HAL_CAP_4ADDR_AGGR:
619                 return pCap->hal4AddrAggrSupport ? HAL_OK : HAL_ENOTSUPP;
620         case HAL_CAP_EXT_CHAN_DFS:
621                 return pCap->halExtChanDfsSupport ? HAL_OK : HAL_ENOTSUPP;
622         case HAL_CAP_COMBINED_RADAR_RSSI:
623                 return pCap->halUseCombinedRadarRssi ? HAL_OK : HAL_ENOTSUPP;
624         case HAL_CAP_AUTO_SLEEP:
625                 return pCap->halAutoSleepSupport ? HAL_OK : HAL_ENOTSUPP;
626         case HAL_CAP_MBSSID_AGGR_SUPPORT:
627                 return pCap->halMbssidAggrSupport ? HAL_OK : HAL_ENOTSUPP;
628         case HAL_CAP_SPLIT_4KB_TRANS:   /* hardware handles descriptors straddling 4k page boundary */
629                 return pCap->hal4kbSplitTransSupport ? HAL_OK : HAL_ENOTSUPP;
630         case HAL_CAP_REG_FLAG:
631                 *result = AH_PRIVATE(ah)->ah_currentRDext;
632                 return HAL_OK;
633         case HAL_CAP_ENHANCED_DMA_SUPPORT:
634                 return pCap->halEnhancedDmaSupport ? HAL_OK : HAL_ENOTSUPP;
635         case HAL_CAP_NUM_TXMAPS:
636                 *result = pCap->halNumTxMaps;
637                 return HAL_OK;
638         case HAL_CAP_TXDESCLEN:
639                 *result = pCap->halTxDescLen;
640                 return HAL_OK;
641         case HAL_CAP_TXSTATUSLEN:
642                 *result = pCap->halTxStatusLen;
643                 return HAL_OK;
644         case HAL_CAP_RXSTATUSLEN:
645                 *result = pCap->halRxStatusLen;
646                 return HAL_OK;
647         case HAL_CAP_RXFIFODEPTH:
648                 switch (capability) {
649                 case HAL_RX_QUEUE_HP:
650                         *result = pCap->halRxHpFifoDepth;
651                         return HAL_OK;
652                 case HAL_RX_QUEUE_LP:
653                         *result = pCap->halRxLpFifoDepth;
654                         return HAL_OK;
655                 default:
656                         return HAL_ENOTSUPP;
657         }
658         case HAL_CAP_RXBUFSIZE:
659         case HAL_CAP_NUM_MR_RETRIES:
660                 return HAL_EINVAL;      /* XXX not yet */
661         case HAL_CAP_BT_COEX:
662                 return pCap->halBtCoexSupport ? HAL_OK : HAL_ENOTSUPP;
663         case HAL_CAP_HT20_SGI:
664                 return pCap->halHTSGI20Support ? HAL_OK : HAL_ENOTSUPP;
665         case HAL_CAP_RXTSTAMP_PREC:     /* rx desc tstamp precision (bits) */
666                 *result = pCap->halTstampPrecision;
667                 return HAL_OK;
668         case HAL_CAP_ENHANCED_DFS_SUPPORT:
669                 return pCap->halEnhancedDfsSupport ? HAL_OK : HAL_ENOTSUPP;
670
671         /* FreeBSD-specific entries for now */
672         case HAL_CAP_RXORN_FATAL:       /* HAL_INT_RXORN treated as fatal  */
673                 return AH_PRIVATE(ah)->ah_rxornIsFatal ? HAL_OK : HAL_ENOTSUPP;
674         case HAL_CAP_INTRMASK:          /* mask of supported interrupts */
675                 *result = pCap->halIntrMask;
676                 return HAL_OK;
677         case HAL_CAP_BSSIDMATCH:        /* hardware has disable bssid match */
678                 return pCap->halBssidMatchSupport ? HAL_OK : HAL_ENOTSUPP;
679         case HAL_CAP_STREAMS:           /* number of 11n spatial streams */
680                 switch (capability) {
681                 case 0:                 /* TX */
682                         *result = pCap->halTxStreams;
683                         return HAL_OK;
684                 case 1:                 /* RX */
685                         *result = pCap->halRxStreams;
686                         return HAL_OK;
687                 default:
688                         return HAL_ENOTSUPP;
689                 }
690         case HAL_CAP_RXDESC_SELFLINK:   /* hardware supports self-linked final RX descriptors correctly */
691                 return pCap->halHasRxSelfLinkedTail ? HAL_OK : HAL_ENOTSUPP;
692         case HAL_CAP_LONG_RXDESC_TSF:           /* 32 bit TSF in RX descriptor? */
693                 return pCap->halHasLongRxDescTsf ? HAL_OK : HAL_ENOTSUPP;
694         case HAL_CAP_BB_READ_WAR:               /* Baseband read WAR */
695                 return pCap->halHasBBReadWar? HAL_OK : HAL_ENOTSUPP;
696         case HAL_CAP_SERIALISE_WAR:             /* PCI register serialisation */
697                 return pCap->halSerialiseRegWar ? HAL_OK : HAL_ENOTSUPP;
698
699         default:
700                 return HAL_EINVAL;
701         }
702 }
703
704 HAL_BOOL
705 ath_hal_setcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
706         uint32_t capability, uint32_t setting, HAL_STATUS *status)
707 {
708
709         switch (type) {
710         case HAL_CAP_TXPOW:
711                 switch (capability) {
712                 case 3:
713                         if (setting <= HAL_TP_SCALE_MIN) {
714                                 AH_PRIVATE(ah)->ah_tpScale = setting;
715                                 return AH_TRUE;
716                         }
717                         break;
718                 }
719                 break;
720         case HAL_CAP_RFSILENT:          /* rfsilent support  */
721                 /*
722                  * NB: allow even if halRfSilentSupport is false
723                  *     in case the EEPROM is misprogrammed.
724                  */
725                 switch (capability) {
726                 case 1:                 /* current setting */
727                         AH_PRIVATE(ah)->ah_rfkillEnabled = (setting != 0);
728                         return AH_TRUE;
729                 case 2:                 /* rfsilent config */
730                         /* XXX better done per-chip for validation? */
731                         AH_PRIVATE(ah)->ah_rfsilent = setting;
732                         return AH_TRUE;
733                 }
734                 break;
735         case HAL_CAP_REG_DMN:           /* regulatory domain */
736                 AH_PRIVATE(ah)->ah_currentRD = setting;
737                 return AH_TRUE;
738         case HAL_CAP_RXORN_FATAL:       /* HAL_INT_RXORN treated as fatal  */
739                 AH_PRIVATE(ah)->ah_rxornIsFatal = setting;
740                 return AH_TRUE;
741         default:
742                 break;
743         }
744         if (status)
745                 *status = HAL_EINVAL;
746         return AH_FALSE;
747 }
748
749 /* 
750  * Common support for getDiagState method.
751  */
752
753 static u_int
754 ath_hal_getregdump(struct ath_hal *ah, const HAL_REGRANGE *regs,
755         void *dstbuf, int space)
756 {
757         uint32_t *dp = dstbuf;
758         int i;
759
760         for (i = 0; space >= 2*sizeof(uint32_t); i++) {
761                 u_int r = regs[i].start;
762                 u_int e = regs[i].end;
763                 *dp++ = (r<<16) | e;
764                 space -= sizeof(uint32_t);
765                 do {
766                         *dp++ = OS_REG_READ(ah, r);
767                         r += sizeof(uint32_t);
768                         space -= sizeof(uint32_t);
769                 } while (r <= e && space >= sizeof(uint32_t));
770         }
771         return (char *) dp - (char *) dstbuf;
772 }
773  
774 static void
775 ath_hal_setregs(struct ath_hal *ah, const HAL_REGWRITE *regs, int space)
776 {
777         while (space >= sizeof(HAL_REGWRITE)) {
778                 OS_REG_WRITE(ah, regs->addr, regs->value);
779                 regs++, space -= sizeof(HAL_REGWRITE);
780         }
781 }
782
783 HAL_BOOL
784 ath_hal_getdiagstate(struct ath_hal *ah, int request,
785         const void *args, uint32_t argsize,
786         void **result, uint32_t *resultsize)
787 {
788         switch (request) {
789         case HAL_DIAG_REVS:
790                 *result = &AH_PRIVATE(ah)->ah_devid;
791                 *resultsize = sizeof(HAL_REVS);
792                 return AH_TRUE;
793         case HAL_DIAG_REGS:
794                 *resultsize = ath_hal_getregdump(ah, args, *result,*resultsize);
795                 return AH_TRUE;
796         case HAL_DIAG_SETREGS:
797                 ath_hal_setregs(ah, args, argsize);
798                 *resultsize = 0;
799                 return AH_TRUE;
800         case HAL_DIAG_FATALERR:
801                 *result = &AH_PRIVATE(ah)->ah_fatalState[0];
802                 *resultsize = sizeof(AH_PRIVATE(ah)->ah_fatalState);
803                 return AH_TRUE;
804         case HAL_DIAG_EEREAD:
805                 if (argsize != sizeof(uint16_t))
806                         return AH_FALSE;
807                 if (!ath_hal_eepromRead(ah, *(const uint16_t *)args, *result))
808                         return AH_FALSE;
809                 *resultsize = sizeof(uint16_t);
810                 return AH_TRUE;
811 #ifdef AH_PRIVATE_DIAG
812         case HAL_DIAG_SETKEY: {
813                 const HAL_DIAG_KEYVAL *dk;
814
815                 if (argsize != sizeof(HAL_DIAG_KEYVAL))
816                         return AH_FALSE;
817                 dk = (const HAL_DIAG_KEYVAL *)args;
818                 return ah->ah_setKeyCacheEntry(ah, dk->dk_keyix,
819                         &dk->dk_keyval, dk->dk_mac, dk->dk_xor);
820         }
821         case HAL_DIAG_RESETKEY:
822                 if (argsize != sizeof(uint16_t))
823                         return AH_FALSE;
824                 return ah->ah_resetKeyCacheEntry(ah, *(const uint16_t *)args);
825 #ifdef AH_SUPPORT_WRITE_EEPROM
826         case HAL_DIAG_EEWRITE: {
827                 const HAL_DIAG_EEVAL *ee;
828                 if (argsize != sizeof(HAL_DIAG_EEVAL))
829                         return AH_FALSE;
830                 ee = (const HAL_DIAG_EEVAL *)args;
831                 return ath_hal_eepromWrite(ah, ee->ee_off, ee->ee_data);
832         }
833 #endif /* AH_SUPPORT_WRITE_EEPROM */
834 #endif /* AH_PRIVATE_DIAG */
835         case HAL_DIAG_11NCOMPAT:
836                 if (argsize == 0) {
837                         *resultsize = sizeof(uint32_t);
838                         *((uint32_t *)(*result)) =
839                                 AH_PRIVATE(ah)->ah_11nCompat;
840                 } else if (argsize == sizeof(uint32_t)) {
841                         AH_PRIVATE(ah)->ah_11nCompat = *(const uint32_t *)args;
842                 } else
843                         return AH_FALSE;
844                 return AH_TRUE;
845         }
846         return AH_FALSE;
847 }
848
849 /*
850  * Set the properties of the tx queue with the parameters
851  * from qInfo.
852  */
853 HAL_BOOL
854 ath_hal_setTxQProps(struct ath_hal *ah,
855         HAL_TX_QUEUE_INFO *qi, const HAL_TXQ_INFO *qInfo)
856 {
857         uint32_t cw;
858
859         if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
860                 HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
861                     "%s: inactive queue\n", __func__);
862                 return AH_FALSE;
863         }
864         /* XXX validate parameters */
865         qi->tqi_ver = qInfo->tqi_ver;
866         qi->tqi_subtype = qInfo->tqi_subtype;
867         qi->tqi_qflags = qInfo->tqi_qflags;
868         qi->tqi_priority = qInfo->tqi_priority;
869         if (qInfo->tqi_aifs != HAL_TXQ_USEDEFAULT)
870                 qi->tqi_aifs = AH_MIN(qInfo->tqi_aifs, 255);
871         else
872                 qi->tqi_aifs = INIT_AIFS;
873         if (qInfo->tqi_cwmin != HAL_TXQ_USEDEFAULT) {
874                 cw = AH_MIN(qInfo->tqi_cwmin, 1024);
875                 /* make sure that the CWmin is of the form (2^n - 1) */
876                 qi->tqi_cwmin = 1;
877                 while (qi->tqi_cwmin < cw)
878                         qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1;
879         } else
880                 qi->tqi_cwmin = qInfo->tqi_cwmin;
881         if (qInfo->tqi_cwmax != HAL_TXQ_USEDEFAULT) {
882                 cw = AH_MIN(qInfo->tqi_cwmax, 1024);
883                 /* make sure that the CWmax is of the form (2^n - 1) */
884                 qi->tqi_cwmax = 1;
885                 while (qi->tqi_cwmax < cw)
886                         qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1;
887         } else
888                 qi->tqi_cwmax = INIT_CWMAX;
889         /* Set retry limit values */
890         if (qInfo->tqi_shretry != 0)
891                 qi->tqi_shretry = AH_MIN(qInfo->tqi_shretry, 15);
892         else
893                 qi->tqi_shretry = INIT_SH_RETRY;
894         if (qInfo->tqi_lgretry != 0)
895                 qi->tqi_lgretry = AH_MIN(qInfo->tqi_lgretry, 15);
896         else
897                 qi->tqi_lgretry = INIT_LG_RETRY;
898         qi->tqi_cbrPeriod = qInfo->tqi_cbrPeriod;
899         qi->tqi_cbrOverflowLimit = qInfo->tqi_cbrOverflowLimit;
900         qi->tqi_burstTime = qInfo->tqi_burstTime;
901         qi->tqi_readyTime = qInfo->tqi_readyTime;
902
903         switch (qInfo->tqi_subtype) {
904         case HAL_WME_UPSD:
905                 if (qi->tqi_type == HAL_TX_QUEUE_DATA)
906                         qi->tqi_intFlags = HAL_TXQ_USE_LOCKOUT_BKOFF_DIS;
907                 break;
908         default:
909                 break;          /* NB: silence compiler */
910         }
911         return AH_TRUE;
912 }
913
914 HAL_BOOL
915 ath_hal_getTxQProps(struct ath_hal *ah,
916         HAL_TXQ_INFO *qInfo, const HAL_TX_QUEUE_INFO *qi)
917 {
918         if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
919                 HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
920                     "%s: inactive queue\n", __func__);
921                 return AH_FALSE;
922         }
923
924         qInfo->tqi_qflags = qi->tqi_qflags;
925         qInfo->tqi_ver = qi->tqi_ver;
926         qInfo->tqi_subtype = qi->tqi_subtype;
927         qInfo->tqi_qflags = qi->tqi_qflags;
928         qInfo->tqi_priority = qi->tqi_priority;
929         qInfo->tqi_aifs = qi->tqi_aifs;
930         qInfo->tqi_cwmin = qi->tqi_cwmin;
931         qInfo->tqi_cwmax = qi->tqi_cwmax;
932         qInfo->tqi_shretry = qi->tqi_shretry;
933         qInfo->tqi_lgretry = qi->tqi_lgretry;
934         qInfo->tqi_cbrPeriod = qi->tqi_cbrPeriod;
935         qInfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit;
936         qInfo->tqi_burstTime = qi->tqi_burstTime;
937         qInfo->tqi_readyTime = qi->tqi_readyTime;
938         return AH_TRUE;
939 }
940
941                                      /* 11a Turbo  11b  11g  108g */
942 static const int16_t NOISE_FLOOR[] = { -96, -93,  -98, -96,  -93 };
943
944 /*
945  * Read the current channel noise floor and return.
946  * If nf cal hasn't finished, channel noise floor should be 0
947  * and we return a nominal value based on band and frequency.
948  *
949  * NB: This is a private routine used by per-chip code to
950  *     implement the ah_getChanNoise method.
951  */
952 int16_t
953 ath_hal_getChanNoise(struct ath_hal *ah, const struct ieee80211_channel *chan)
954 {
955         HAL_CHANNEL_INTERNAL *ichan;
956
957         ichan = ath_hal_checkchannel(ah, chan);
958         if (ichan == AH_NULL) {
959                 HALDEBUG(ah, HAL_DEBUG_NFCAL,
960                     "%s: invalid channel %u/0x%x; no mapping\n",
961                     __func__, chan->ic_freq, chan->ic_flags);
962                 return 0;
963         }
964         if (ichan->rawNoiseFloor == 0) {
965                 WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan);
966
967                 HALASSERT(mode < WIRELESS_MODE_MAX);
968                 return NOISE_FLOOR[mode] + ath_hal_getNfAdjust(ah, ichan);
969         } else
970                 return ichan->rawNoiseFloor + ichan->noiseFloorAdjust;
971 }
972
973 /*
974  * Fetch the current setup of ctl/ext noise floor values.
975  *
976  * If the CHANNEL_MIMO_NF_VALID flag isn't set, the array is simply
977  * populated with values from NOISE_FLOOR[] + ath_hal_getNfAdjust().
978  *
979  * The caller must supply ctl/ext NF arrays which are at least
980  * AH_MIMO_MAX_CHAINS entries long.
981  */
982 int
983 ath_hal_get_mimo_chan_noise(struct ath_hal *ah,
984     const struct ieee80211_channel *chan, int16_t *nf_ctl,
985     int16_t *nf_ext)
986 {
987 #ifdef  AH_SUPPORT_AR5416
988         HAL_CHANNEL_INTERNAL *ichan;
989         int i;
990
991         ichan = ath_hal_checkchannel(ah, chan);
992         if (ichan == AH_NULL) {
993                 HALDEBUG(ah, HAL_DEBUG_NFCAL,
994                     "%s: invalid channel %u/0x%x; no mapping\n",
995                     __func__, chan->ic_freq, chan->ic_flags);
996                 for (i = 0; i < AH_MIMO_MAX_CHAINS; i++) {
997                         nf_ctl[i] = nf_ext[i] = 0;
998                 }
999                 return 0;
1000         }
1001
1002         /* Return 0 if there's no valid MIMO values (yet) */
1003         if (! (ichan->privFlags & CHANNEL_MIMO_NF_VALID)) {
1004                 for (i = 0; i < AH_MIMO_MAX_CHAINS; i++) {
1005                         nf_ctl[i] = nf_ext[i] = 0;
1006                 }
1007                 return 0;
1008         }
1009         if (ichan->rawNoiseFloor == 0) {
1010                 WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan);
1011                 HALASSERT(mode < WIRELESS_MODE_MAX);
1012                 /*
1013                  * See the comment below - this could cause issues for
1014                  * stations which have a very low RSSI, below the
1015                  * 'normalised' NF values in NOISE_FLOOR[].
1016                  */
1017                 for (i = 0; i < AH_MIMO_MAX_CHAINS; i++) {
1018                         nf_ctl[i] = nf_ext[i] = NOISE_FLOOR[mode] +
1019                             ath_hal_getNfAdjust(ah, ichan);
1020                 }
1021                 return 1;
1022         } else {
1023                 /*
1024                  * The value returned here from a MIMO radio is presumed to be
1025                  * "good enough" as a NF calculation. As RSSI values are calculated
1026                  * against this, an adjusted NF may be higher than the RSSI value
1027                  * returned from a vary weak station, resulting in an obscenely
1028                  * high signal strength calculation being returned.
1029                  *
1030                  * This should be re-evaluated at a later date, along with any
1031                  * signal strength calculations which are made. Quite likely the
1032                  * RSSI values will need to be adjusted to ensure the calculations
1033                  * don't "wrap" when RSSI is less than the "adjusted" NF value.
1034                  * ("Adjust" here is via ichan->noiseFloorAdjust.)
1035                  */
1036                 for (i = 0; i < AH_MIMO_MAX_CHAINS; i++) {
1037                         nf_ctl[i] = ichan->noiseFloorCtl[i] + ath_hal_getNfAdjust(ah, ichan);
1038                         nf_ext[i] = ichan->noiseFloorExt[i] + ath_hal_getNfAdjust(ah, ichan);
1039                 }
1040                 return 1;
1041         }
1042 #else
1043         return 0;
1044 #endif  /* AH_SUPPORT_AR5416 */
1045 }
1046
1047 /*
1048  * Process all valid raw noise floors into the dBm noise floor values.
1049  * Though our device has no reference for a dBm noise floor, we perform
1050  * a relative minimization of NF's based on the lowest NF found across a
1051  * channel scan.
1052  */
1053 void
1054 ath_hal_process_noisefloor(struct ath_hal *ah)
1055 {
1056         HAL_CHANNEL_INTERNAL *c;
1057         int16_t correct2, correct5;
1058         int16_t lowest2, lowest5;
1059         int i;
1060
1061         /* 
1062          * Find the lowest 2GHz and 5GHz noise floor values after adjusting
1063          * for statistically recorded NF/channel deviation.
1064          */
1065         correct2 = lowest2 = 0;
1066         correct5 = lowest5 = 0;
1067         for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
1068                 WIRELESS_MODE mode;
1069                 int16_t nf;
1070
1071                 c = &AH_PRIVATE(ah)->ah_channels[i];
1072                 if (c->rawNoiseFloor >= 0)
1073                         continue;
1074                 /* XXX can't identify proper mode */
1075                 mode = IS_CHAN_5GHZ(c) ? WIRELESS_MODE_11a : WIRELESS_MODE_11g;
1076                 nf = c->rawNoiseFloor + NOISE_FLOOR[mode] +
1077                         ath_hal_getNfAdjust(ah, c);
1078                 if (IS_CHAN_5GHZ(c)) {
1079                         if (nf < lowest5) { 
1080                                 lowest5 = nf;
1081                                 correct5 = NOISE_FLOOR[mode] -
1082                                     (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
1083                         }
1084                 } else {
1085                         if (nf < lowest2) { 
1086                                 lowest2 = nf;
1087                                 correct2 = NOISE_FLOOR[mode] -
1088                                     (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
1089                         }
1090                 }
1091         }
1092
1093         /* Correct the channels to reach the expected NF value */
1094         for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
1095                 c = &AH_PRIVATE(ah)->ah_channels[i];
1096                 if (c->rawNoiseFloor >= 0)
1097                         continue;
1098                 /* Apply correction factor */
1099                 c->noiseFloorAdjust = ath_hal_getNfAdjust(ah, c) +
1100                         (IS_CHAN_5GHZ(c) ? correct5 : correct2);
1101                 HALDEBUG(ah, HAL_DEBUG_NFCAL, "%u raw nf %d adjust %d\n",
1102                     c->channel, c->rawNoiseFloor, c->noiseFloorAdjust);
1103         }
1104 }
1105
1106 /*
1107  * INI support routines.
1108  */
1109
1110 int
1111 ath_hal_ini_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
1112         int col, int regWr)
1113 {
1114         int r;
1115
1116         HALASSERT(col < ia->cols);
1117         for (r = 0; r < ia->rows; r++) {
1118                 OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0),
1119                     HAL_INI_VAL(ia, r, col));
1120
1121                 /* Analog shift register delay seems needed for Merlin - PR kern/154220 */
1122                 if (HAL_INI_VAL(ia, r, 0) >= 0x7800 && HAL_INI_VAL(ia, r, 0) < 0x7900)
1123                         OS_DELAY(100);
1124
1125                 DMA_YIELD(regWr);
1126         }
1127         return regWr;
1128 }
1129
1130 void
1131 ath_hal_ini_bank_setup(uint32_t data[], const HAL_INI_ARRAY *ia, int col)
1132 {
1133         int r;
1134
1135         HALASSERT(col < ia->cols);
1136         for (r = 0; r < ia->rows; r++)
1137                 data[r] = HAL_INI_VAL(ia, r, col);
1138 }
1139
1140 int
1141 ath_hal_ini_bank_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
1142         const uint32_t data[], int regWr)
1143 {
1144         int r;
1145
1146         for (r = 0; r < ia->rows; r++) {
1147                 OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0), data[r]);
1148                 DMA_YIELD(regWr);
1149         }
1150         return regWr;
1151 }
1152
1153 /*
1154  * These are EEPROM board related routines which should likely live in
1155  * a helper library of some sort.
1156  */
1157
1158 /**************************************************************
1159  * ath_ee_getLowerUppderIndex
1160  *
1161  * Return indices surrounding the value in sorted integer lists.
1162  * Requirement: the input list must be monotonically increasing
1163  *     and populated up to the list size
1164  * Returns: match is set if an index in the array matches exactly
1165  *     or a the target is before or after the range of the array.
1166  */
1167 HAL_BOOL
1168 ath_ee_getLowerUpperIndex(uint8_t target, uint8_t *pList, uint16_t listSize,
1169                    uint16_t *indexL, uint16_t *indexR)
1170 {
1171     uint16_t i;
1172
1173     /*
1174      * Check first and last elements for beyond ordered array cases.
1175      */
1176     if (target <= pList[0]) {
1177         *indexL = *indexR = 0;
1178         return AH_TRUE;
1179     }
1180     if (target >= pList[listSize-1]) {
1181         *indexL = *indexR = (uint16_t)(listSize - 1);
1182         return AH_TRUE;
1183     }
1184
1185     /* look for value being near or between 2 values in list */
1186     for (i = 0; i < listSize - 1; i++) {
1187         /*
1188          * If value is close to the current value of the list
1189          * then target is not between values, it is one of the values
1190          */
1191         if (pList[i] == target) {
1192             *indexL = *indexR = i;
1193             return AH_TRUE;
1194         }
1195         /*
1196          * Look for value being between current value and next value
1197          * if so return these 2 values
1198          */
1199         if (target < pList[i + 1]) {
1200             *indexL = i;
1201             *indexR = (uint16_t)(i + 1);
1202             return AH_FALSE;
1203         }
1204     }
1205     HALASSERT(0);
1206     *indexL = *indexR = 0;
1207     return AH_FALSE;
1208 }
1209
1210 /**************************************************************
1211  * ath_ee_FillVpdTable
1212  *
1213  * Fill the Vpdlist for indices Pmax-Pmin
1214  * Note: pwrMin, pwrMax and Vpdlist are all in dBm * 4
1215  */
1216 HAL_BOOL
1217 ath_ee_FillVpdTable(uint8_t pwrMin, uint8_t pwrMax, uint8_t *pPwrList,
1218                    uint8_t *pVpdList, uint16_t numIntercepts, uint8_t *pRetVpdList)
1219 {
1220     uint16_t  i, k;
1221     uint8_t   currPwr = pwrMin;
1222     uint16_t  idxL, idxR;
1223
1224     HALASSERT(pwrMax > pwrMin);
1225     for (i = 0; i <= (pwrMax - pwrMin) / 2; i++) {
1226         ath_ee_getLowerUpperIndex(currPwr, pPwrList, numIntercepts,
1227                            &(idxL), &(idxR));
1228         if (idxR < 1)
1229             idxR = 1;           /* extrapolate below */
1230         if (idxL == numIntercepts - 1)
1231             idxL = (uint16_t)(numIntercepts - 2);   /* extrapolate above */
1232         if (pPwrList[idxL] == pPwrList[idxR])
1233             k = pVpdList[idxL];
1234         else
1235             k = (uint16_t)( ((currPwr - pPwrList[idxL]) * pVpdList[idxR] + (pPwrList[idxR] - currPwr) * pVpdList[idxL]) /
1236                   (pPwrList[idxR] - pPwrList[idxL]) );
1237         HALASSERT(k < 256);
1238         pRetVpdList[i] = (uint8_t)k;
1239         currPwr += 2;               /* half dB steps */
1240     }
1241
1242     return AH_TRUE;
1243 }
1244
1245 /**************************************************************************
1246  * ath_ee_interpolate
1247  *
1248  * Returns signed interpolated or the scaled up interpolated value
1249  */
1250 int16_t
1251 ath_ee_interpolate(uint16_t target, uint16_t srcLeft, uint16_t srcRight,
1252             int16_t targetLeft, int16_t targetRight)
1253 {
1254     int16_t rv;
1255
1256     if (srcRight == srcLeft) {
1257         rv = targetLeft;
1258     } else {
1259         rv = (int16_t)( ((target - srcLeft) * targetRight +
1260               (srcRight - target) * targetLeft) / (srcRight - srcLeft) );
1261     }
1262     return rv;
1263 }
1264
1265 /*
1266  * Adjust the TSF.
1267  */
1268 void
1269 ath_hal_adjusttsf(struct ath_hal *ah, int32_t tsfdelta)
1270 {
1271         /* XXX handle wrap/overflow */
1272         OS_REG_WRITE(ah, AR_TSF_L32, OS_REG_READ(ah, AR_TSF_L32) + tsfdelta);
1273 }
1274
1275 /*
1276  * Enable or disable CCA.
1277  */
1278 void
1279 ath_hal_setcca(struct ath_hal *ah, int ena)
1280 {
1281         /*
1282          * NB: fill me in; this is not provided by default because disabling
1283          *     CCA in most locales violates regulatory.
1284          */
1285 }
1286
1287 /*
1288  * Get CCA setting.
1289  */
1290 int
1291 ath_hal_getcca(struct ath_hal *ah)
1292 {
1293         u_int32_t diag;
1294         if (ath_hal_getcapability(ah, HAL_CAP_DIAG, 0, &diag) != HAL_OK)
1295                 return 1;
1296         return ((diag & 0x500000) == 0);
1297 }
1298
1299 /*
1300  * This routine is only needed when supporting EEPROM-in-RAM setups
1301  * (eg embedded SoCs and on-board PCI/PCIe devices.)
1302  */
1303 /* NB: This is in 16 bit words; not bytes */
1304 /* XXX This doesn't belong here!  */
1305 #define ATH_DATA_EEPROM_SIZE    2048
1306
1307 HAL_BOOL
1308 ath_hal_EepromDataRead(struct ath_hal *ah, u_int off, uint16_t *data)
1309 {
1310         if (ah->ah_eepromdata == AH_NULL) {
1311                 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: no eeprom data!\n", __func__);
1312                 return AH_FALSE;
1313         }
1314         if (off > ATH_DATA_EEPROM_SIZE) {
1315                 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: offset %x > %x\n",
1316                     __func__, off, ATH_DATA_EEPROM_SIZE);
1317                 return AH_FALSE;
1318         }
1319         (*data) = ah->ah_eepromdata[off];
1320         return AH_TRUE;
1321 }