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