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