Merge branch 'vendor/LIBPCAP' and updated build for new version.
[dragonfly.git] / sys / dev / netif / ath / hal / ath_hal / ah.c
1 /*
2  * Copyright (c) 2002-2008 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: src/sys/dev/ath/ath_hal/ah.c,v 1.2.2.1.2.1 2009/04/15 03:14:26 kensmith Exp $
18  */
19 #include "opt_ah.h"
20
21 #include "ah.h"
22 #include "ah_internal.h"
23 #include "ah_devid.h"
24 /* linker set of registered chips */
25 OS_SET_DECLARE(ah_chips, struct ath_hal_chip);
26
27 /*
28  * Check the set of registered chips to see if any recognize
29  * the device as one they can support.
30  */
31 const char*
32 ath_hal_probe(uint16_t vendorid, uint16_t devid)
33 {
34         struct ath_hal_chip * const *pchip;
35
36         OS_SET_FOREACH(pchip, ah_chips) {
37                 const char *name = (*pchip)->probe(vendorid, devid);
38                 if (name != AH_NULL)
39                         return name;
40         }
41         return AH_NULL;
42 }
43
44 /*
45  * Attach detects device chip revisions, initializes the hwLayer
46  * function list, reads EEPROM information,
47  * selects reset vectors, and performs a short self test.
48  * Any failures will return an error that should cause a hardware
49  * disable.
50  */
51 struct ath_hal*
52 ath_hal_attach(uint16_t devid, HAL_SOFTC sc,
53         HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *error)
54 {
55         struct ath_hal_chip * const *pchip;
56
57         OS_SET_FOREACH(pchip, ah_chips) {
58                 struct ath_hal_chip *chip = *pchip;
59                 struct ath_hal *ah;
60
61                 /* XXX don't have vendorid, assume atheros one works */
62                 if (chip->probe(ATHEROS_VENDOR_ID, devid) == AH_NULL)
63                         continue;
64                 ah = chip->attach(devid, sc, st, sh, error);
65                 if (ah != AH_NULL) {
66                         /* copy back private state to public area */
67                         ah->ah_devid = AH_PRIVATE(ah)->ah_devid;
68                         ah->ah_subvendorid = AH_PRIVATE(ah)->ah_subvendorid;
69                         ah->ah_macVersion = AH_PRIVATE(ah)->ah_macVersion;
70                         ah->ah_macRev = AH_PRIVATE(ah)->ah_macRev;
71                         ah->ah_phyRev = AH_PRIVATE(ah)->ah_phyRev;
72                         ah->ah_analog5GhzRev = AH_PRIVATE(ah)->ah_analog5GhzRev;
73                         ah->ah_analog2GhzRev = AH_PRIVATE(ah)->ah_analog2GhzRev;
74                         return ah;
75                 }
76         }
77         return AH_NULL;
78 }
79
80 /* linker set of registered RF backends */
81 OS_SET_DECLARE(ah_rfs, struct ath_hal_rf);
82
83 /*
84  * Check the set of registered RF backends to see if
85  * any recognize the device as one they can support.
86  */
87 struct ath_hal_rf *
88 ath_hal_rfprobe(struct ath_hal *ah, HAL_STATUS *ecode)
89 {
90         struct ath_hal_rf * const *prf;
91
92         OS_SET_FOREACH(prf, ah_rfs) {
93                 struct ath_hal_rf *rf = *prf;
94                 if (rf->probe(ah))
95                         return rf;
96         }
97         *ecode = HAL_ENOTSUPP;
98         return AH_NULL;
99 }
100
101 /*
102  * Poll the register looking for a specific value.
103  */
104 HAL_BOOL
105 ath_hal_wait(struct ath_hal *ah, u_int reg, uint32_t mask, uint32_t val)
106 {
107 #define AH_TIMEOUT      1000
108         int i;
109
110         for (i = 0; i < AH_TIMEOUT; i++) {
111                 if ((OS_REG_READ(ah, reg) & mask) == val)
112                         return AH_TRUE;
113                 OS_DELAY(10);
114         }
115         HALDEBUG(ah, HAL_DEBUG_REGIO | HAL_DEBUG_PHYIO,
116             "%s: timeout on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n",
117             __func__, reg, OS_REG_READ(ah, reg), mask, val);
118         return AH_FALSE;
119 #undef AH_TIMEOUT
120 }
121
122 /*
123  * Reverse the bits starting at the low bit for a value of
124  * bit_count in size
125  */
126 uint32_t
127 ath_hal_reverseBits(uint32_t val, uint32_t n)
128 {
129         uint32_t retval;
130         int i;
131
132         for (i = 0, retval = 0; i < n; i++) {
133                 retval = (retval << 1) | (val & 1);
134                 val >>= 1;
135         }
136         return retval;
137 }
138
139 /*
140  * Compute the time to transmit a frame of length frameLen bytes
141  * using the specified rate, phy, and short preamble setting.
142  */
143 uint16_t
144 ath_hal_computetxtime(struct ath_hal *ah,
145         const HAL_RATE_TABLE *rates, uint32_t frameLen, uint16_t rateix,
146         HAL_BOOL shortPreamble)
147 {
148         uint32_t bitsPerSymbol, numBits, numSymbols, phyTime, txTime;
149         uint32_t kbps;
150
151         kbps = rates->info[rateix].rateKbps;
152         /*
153          * index can be invalid duting dynamic Turbo transitions. 
154          */
155         if(kbps == 0) return 0;
156         switch (rates->info[rateix].phy) {
157
158         case IEEE80211_T_CCK:
159 #define CCK_SIFS_TIME        10
160 #define CCK_PREAMBLE_BITS   144
161 #define CCK_PLCP_BITS        48
162                 phyTime         = CCK_PREAMBLE_BITS + CCK_PLCP_BITS;
163                 if (shortPreamble && rates->info[rateix].shortPreamble)
164                         phyTime >>= 1;
165                 numBits         = frameLen << 3;
166                 txTime          = CCK_SIFS_TIME + phyTime
167                                 + ((numBits * 1000)/kbps);
168                 break;
169 #undef CCK_SIFS_TIME
170 #undef CCK_PREAMBLE_BITS
171 #undef CCK_PLCP_BITS
172
173         case IEEE80211_T_OFDM:
174 #define OFDM_SIFS_TIME        16
175 #define OFDM_PREAMBLE_TIME    20
176 #define OFDM_PLCP_BITS        22
177 #define OFDM_SYMBOL_TIME       4
178
179 #define OFDM_SIFS_TIME_HALF     32
180 #define OFDM_PREAMBLE_TIME_HALF 40
181 #define OFDM_PLCP_BITS_HALF     22
182 #define OFDM_SYMBOL_TIME_HALF   8
183
184 #define OFDM_SIFS_TIME_QUARTER          64
185 #define OFDM_PREAMBLE_TIME_QUARTER      80
186 #define OFDM_PLCP_BITS_QUARTER          22
187 #define OFDM_SYMBOL_TIME_QUARTER        16
188
189                 if (AH_PRIVATE(ah)->ah_curchan && 
190                         IS_CHAN_QUARTER_RATE(AH_PRIVATE(ah)->ah_curchan)) {
191                         bitsPerSymbol   = (kbps * OFDM_SYMBOL_TIME_QUARTER) / 1000;
192                         HALASSERT(bitsPerSymbol != 0);
193
194                         numBits         = OFDM_PLCP_BITS + (frameLen << 3);
195                         numSymbols      = howmany(numBits, bitsPerSymbol);
196                         txTime          = OFDM_SIFS_TIME_QUARTER 
197                                                 + OFDM_PREAMBLE_TIME_QUARTER
198                                         + (numSymbols * OFDM_SYMBOL_TIME_QUARTER);
199                 } else if (AH_PRIVATE(ah)->ah_curchan &&
200                                 IS_CHAN_HALF_RATE(AH_PRIVATE(ah)->ah_curchan)) {
201                         bitsPerSymbol   = (kbps * OFDM_SYMBOL_TIME_HALF) / 1000;
202                         HALASSERT(bitsPerSymbol != 0);
203
204                         numBits         = OFDM_PLCP_BITS + (frameLen << 3);
205                         numSymbols      = howmany(numBits, bitsPerSymbol);
206                         txTime          = OFDM_SIFS_TIME_HALF + 
207                                                 OFDM_PREAMBLE_TIME_HALF
208                                         + (numSymbols * OFDM_SYMBOL_TIME_HALF);
209                 } else { /* full rate channel */
210                         bitsPerSymbol   = (kbps * OFDM_SYMBOL_TIME) / 1000;
211                         HALASSERT(bitsPerSymbol != 0);
212
213                         numBits         = OFDM_PLCP_BITS + (frameLen << 3);
214                         numSymbols      = howmany(numBits, bitsPerSymbol);
215                         txTime          = OFDM_SIFS_TIME + OFDM_PREAMBLE_TIME
216                                         + (numSymbols * OFDM_SYMBOL_TIME);
217                 }
218                 break;
219
220 #undef OFDM_SIFS_TIME
221 #undef OFDM_PREAMBLE_TIME
222 #undef OFDM_PLCP_BITS
223 #undef OFDM_SYMBOL_TIME
224
225         case IEEE80211_T_TURBO:
226 #define TURBO_SIFS_TIME         8
227 #define TURBO_PREAMBLE_TIME    14
228 #define TURBO_PLCP_BITS        22
229 #define TURBO_SYMBOL_TIME       4
230                 /* we still save OFDM rates in kbps - so double them */
231                 bitsPerSymbol = ((kbps << 1) * TURBO_SYMBOL_TIME) / 1000;
232                 HALASSERT(bitsPerSymbol != 0);
233
234                 numBits       = TURBO_PLCP_BITS + (frameLen << 3);
235                 numSymbols    = howmany(numBits, bitsPerSymbol);
236                 txTime        = TURBO_SIFS_TIME + TURBO_PREAMBLE_TIME
237                               + (numSymbols * TURBO_SYMBOL_TIME);
238                 break;
239 #undef TURBO_SIFS_TIME
240 #undef TURBO_PREAMBLE_TIME
241 #undef TURBO_PLCP_BITS
242 #undef TURBO_SYMBOL_TIME
243
244         default:
245                 HALDEBUG(ah, HAL_DEBUG_PHYIO,
246                     "%s: unknown phy %u (rate ix %u)\n",
247                     __func__, rates->info[rateix].phy, rateix);
248                 txTime = 0;
249                 break;
250         }
251         return txTime;
252 }
253
254 static __inline int
255 mapgsm(u_int freq, u_int flags)
256 {
257         freq *= 10;
258         if (flags & CHANNEL_QUARTER)
259                 freq += 5;
260         else if (flags & CHANNEL_HALF)
261                 freq += 10;
262         else
263                 freq += 20;
264         return (freq - 24220) / 5;
265 }
266
267 static __inline int
268 mappsb(u_int freq, u_int flags)
269 {
270         return ((freq * 10) + (((freq % 5) == 2) ? 5 : 0) - 49400) / 5;
271 }
272
273 /*
274  * Convert GHz frequency to IEEE channel number.
275  */
276 int
277 ath_hal_mhz2ieee(struct ath_hal *ah, u_int freq, u_int flags)
278 {
279         if (flags & CHANNEL_2GHZ) {     /* 2GHz band */
280                 if (freq == 2484)
281                         return 14;
282                 if (freq < 2484) {
283                         if (ath_hal_isgsmsku(ah))
284                                 return mapgsm(freq, flags);
285                         return ((int)freq - 2407) / 5;
286                 } else
287                         return 15 + ((freq - 2512) / 20);
288         } else if (flags & CHANNEL_5GHZ) {/* 5Ghz band */
289                 if (ath_hal_ispublicsafetysku(ah) &&
290                     IS_CHAN_IN_PUBLIC_SAFETY_BAND(freq)) {
291                         return mappsb(freq, flags);
292                 } else if ((flags & CHANNEL_A) && (freq <= 5000)) {
293                         return (freq - 4000) / 5;
294                 } else {
295                         return (freq - 5000) / 5;
296                 }
297         } else {                        /* either, guess */
298                 if (freq == 2484)
299                         return 14;
300                 if (freq < 2484) {
301                         if (ath_hal_isgsmsku(ah))
302                                 return mapgsm(freq, flags);
303                         return ((int)freq - 2407) / 5;
304                 }
305                 if (freq < 5000) {
306                         if (ath_hal_ispublicsafetysku(ah) &&
307                             IS_CHAN_IN_PUBLIC_SAFETY_BAND(freq)) {
308                                 return mappsb(freq, flags);
309                         } else if (freq > 4900) {
310                                 return (freq - 4000) / 5;
311                         } else {
312                                 return 15 + ((freq - 2512) / 20);
313                         }
314                 }
315                 return (freq - 5000) / 5;
316         }
317 }
318
319 typedef enum {
320         WIRELESS_MODE_11a   = 0,
321         WIRELESS_MODE_TURBO = 1,
322         WIRELESS_MODE_11b   = 2,
323         WIRELESS_MODE_11g   = 3,
324         WIRELESS_MODE_108g  = 4,
325
326         WIRELESS_MODE_MAX
327 } WIRELESS_MODE;
328
329 static WIRELESS_MODE
330 ath_hal_chan2wmode(struct ath_hal *ah, const HAL_CHANNEL *chan)
331 {
332         if (IS_CHAN_CCK(chan))
333                 return WIRELESS_MODE_11b;
334         if (IS_CHAN_G(chan))
335                 return WIRELESS_MODE_11g;
336         if (IS_CHAN_108G(chan))
337                 return WIRELESS_MODE_108g;
338         if (IS_CHAN_TURBO(chan))
339                 return WIRELESS_MODE_TURBO;
340         return WIRELESS_MODE_11a;
341 }
342
343 /*
344  * Convert between microseconds and core system clocks.
345  */
346                                      /* 11a Turbo  11b  11g  108g */
347 static const uint8_t CLOCK_RATE[]  = { 40,  80,   22,  44,   88  };
348
349 u_int
350 ath_hal_mac_clks(struct ath_hal *ah, u_int usecs)
351 {
352         const HAL_CHANNEL *c = (const HAL_CHANNEL *) AH_PRIVATE(ah)->ah_curchan;
353         u_int clks;
354
355         /* NB: ah_curchan may be null when called attach time */
356         if (c != AH_NULL) {
357                 clks = usecs * CLOCK_RATE[ath_hal_chan2wmode(ah, c)];
358                 if (IS_CHAN_HT40(c))
359                         clks <<= 1;
360                 else if (IS_CHAN_HALF_RATE(c))
361                         clks >>= 1;
362                 else if (IS_CHAN_QUARTER_RATE(c))
363                         clks >>= 2;
364         } else
365                 clks = usecs * CLOCK_RATE[WIRELESS_MODE_11b];
366         return clks;
367 }
368
369 u_int
370 ath_hal_mac_usec(struct ath_hal *ah, u_int clks)
371 {
372         const HAL_CHANNEL *c = (const HAL_CHANNEL *) AH_PRIVATE(ah)->ah_curchan;
373         u_int usec;
374
375         /* NB: ah_curchan may be null when called attach time */
376         if (c != AH_NULL) {
377                 usec = clks / CLOCK_RATE[ath_hal_chan2wmode(ah, c)];
378                 if (IS_CHAN_HT40(c))
379                         usec >>= 1;
380                 else if (IS_CHAN_HALF_RATE(c))
381                         usec <<= 1;
382                 else if (IS_CHAN_QUARTER_RATE(c))
383                         usec <<= 2;
384         } else
385                 usec = clks / CLOCK_RATE[WIRELESS_MODE_11b];
386         return usec;
387 }
388
389 /*
390  * Setup a h/w rate table's reverse lookup table and
391  * fill in ack durations.  This routine is called for
392  * each rate table returned through the ah_getRateTable
393  * method.  The reverse lookup tables are assumed to be
394  * initialized to zero (or at least the first entry).
395  * We use this as a key that indicates whether or not
396  * we've previously setup the reverse lookup table.
397  *
398  * XXX not reentrant, but shouldn't matter
399  */
400 void
401 ath_hal_setupratetable(struct ath_hal *ah, HAL_RATE_TABLE *rt)
402 {
403 #define N(a)    (sizeof(a)/sizeof(a[0]))
404         int i;
405
406         if (rt->rateCodeToIndex[0] != 0)        /* already setup */
407                 return;
408         for (i = 0; i < N(rt->rateCodeToIndex); i++)
409                 rt->rateCodeToIndex[i] = (uint8_t) -1;
410         for (i = 0; i < rt->rateCount; i++) {
411                 uint8_t code = rt->info[i].rateCode;
412                 uint8_t cix = rt->info[i].controlRate;
413
414                 HALASSERT(code < N(rt->rateCodeToIndex));
415                 rt->rateCodeToIndex[code] = i;
416                 HALASSERT((code | rt->info[i].shortPreamble) <
417                     N(rt->rateCodeToIndex));
418                 rt->rateCodeToIndex[code | rt->info[i].shortPreamble] = i;
419                 /*
420                  * XXX for 11g the control rate to use for 5.5 and 11 Mb/s
421                  *     depends on whether they are marked as basic rates;
422                  *     the static tables are setup with an 11b-compatible
423                  *     2Mb/s rate which will work but is suboptimal
424                  */
425                 rt->info[i].lpAckDuration = ath_hal_computetxtime(ah, rt,
426                         WLAN_CTRL_FRAME_SIZE, cix, AH_FALSE);
427                 rt->info[i].spAckDuration = ath_hal_computetxtime(ah, rt,
428                         WLAN_CTRL_FRAME_SIZE, cix, AH_TRUE);
429         }
430 #undef N
431 }
432
433 HAL_STATUS
434 ath_hal_getcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
435         uint32_t capability, uint32_t *result)
436 {
437         const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
438
439         switch (type) {
440         case HAL_CAP_REG_DMN:           /* regulatory domain */
441                 *result = AH_PRIVATE(ah)->ah_currentRD;
442                 return HAL_OK;
443         case HAL_CAP_CIPHER:            /* cipher handled in hardware */
444         case HAL_CAP_TKIP_MIC:          /* handle TKIP MIC in hardware */
445                 return HAL_ENOTSUPP;
446         case HAL_CAP_TKIP_SPLIT:        /* hardware TKIP uses split keys */
447                 return HAL_ENOTSUPP;
448         case HAL_CAP_PHYCOUNTERS:       /* hardware PHY error counters */
449                 return pCap->halHwPhyCounterSupport ? HAL_OK : HAL_ENXIO;
450         case HAL_CAP_WME_TKIPMIC:   /* hardware can do TKIP MIC when WMM is turned on */
451                 return HAL_ENOTSUPP;
452         case HAL_CAP_DIVERSITY:         /* hardware supports fast diversity */
453                 return HAL_ENOTSUPP;
454         case HAL_CAP_KEYCACHE_SIZE:     /* hardware key cache size */
455                 *result =  pCap->halKeyCacheSize;
456                 return HAL_OK;
457         case HAL_CAP_NUM_TXQUEUES:      /* number of hardware tx queues */
458                 *result = pCap->halTotalQueues;
459                 return HAL_OK;
460         case HAL_CAP_VEOL:              /* hardware supports virtual EOL */
461                 return pCap->halVEOLSupport ? HAL_OK : HAL_ENOTSUPP;
462         case HAL_CAP_PSPOLL:            /* hardware PS-Poll support works */
463                 return pCap->halPSPollBroken ? HAL_ENOTSUPP : HAL_OK;
464         case HAL_CAP_COMPRESSION:
465                 return pCap->halCompressSupport ? HAL_OK : HAL_ENOTSUPP;
466         case HAL_CAP_BURST:
467                 return pCap->halBurstSupport ? HAL_OK : HAL_ENOTSUPP;
468         case HAL_CAP_FASTFRAME:
469                 return pCap->halFastFramesSupport ? HAL_OK : HAL_ENOTSUPP;
470         case HAL_CAP_DIAG:              /* hardware diagnostic support */
471                 *result = AH_PRIVATE(ah)->ah_diagreg;
472                 return HAL_OK;
473         case HAL_CAP_TXPOW:             /* global tx power limit  */
474                 switch (capability) {
475                 case 0:                 /* facility is supported */
476                         return HAL_OK;
477                 case 1:                 /* current limit */
478                         *result = AH_PRIVATE(ah)->ah_powerLimit;
479                         return HAL_OK;
480                 case 2:                 /* current max tx power */
481                         *result = AH_PRIVATE(ah)->ah_maxPowerLevel;
482                         return HAL_OK;
483                 case 3:                 /* scale factor */
484                         *result = AH_PRIVATE(ah)->ah_tpScale;
485                         return HAL_OK;
486                 }
487                 return HAL_ENOTSUPP;
488         case HAL_CAP_BSSIDMASK:         /* hardware supports bssid mask */
489                 return pCap->halBssIdMaskSupport ? HAL_OK : HAL_ENOTSUPP;
490         case HAL_CAP_MCAST_KEYSRCH:     /* multicast frame keycache search */
491                 return pCap->halMcastKeySrchSupport ? HAL_OK : HAL_ENOTSUPP;
492         case HAL_CAP_TSF_ADJUST:        /* hardware has beacon tsf adjust */
493                 return HAL_ENOTSUPP;
494         case HAL_CAP_RFSILENT:          /* rfsilent support  */
495                 switch (capability) {
496                 case 0:                 /* facility is supported */
497                         return pCap->halRfSilentSupport ? HAL_OK : HAL_ENOTSUPP;
498                 case 1:                 /* current setting */
499                         return AH_PRIVATE(ah)->ah_rfkillEnabled ?
500                                 HAL_OK : HAL_ENOTSUPP;
501                 case 2:                 /* rfsilent config */
502                         *result = AH_PRIVATE(ah)->ah_rfsilent;
503                         return HAL_OK;
504                 }
505                 return HAL_ENOTSUPP;
506         case HAL_CAP_11D:
507 #ifdef AH_SUPPORT_11D
508                 return HAL_OK;
509 #else
510                 return HAL_ENOTSUPP;
511 #endif
512         case HAL_CAP_RXORN_FATAL:       /* HAL_INT_RXORN treated as fatal  */
513                 return AH_PRIVATE(ah)->ah_rxornIsFatal ? HAL_OK : HAL_ENOTSUPP;
514         case HAL_CAP_HT:
515                 return pCap->halHTSupport ? HAL_OK : HAL_ENOTSUPP;
516         case HAL_CAP_TX_CHAINMASK:      /* mask of TX chains supported */
517                 *result = pCap->halTxChainMask;
518                 return HAL_OK;
519         case HAL_CAP_RX_CHAINMASK:      /* mask of RX chains supported */
520                 *result = pCap->halRxChainMask;
521                 return HAL_OK;
522         case HAL_CAP_RXTSTAMP_PREC:     /* rx desc tstamp precision (bits) */
523                 *result = pCap->halTstampPrecision;
524                 return HAL_OK;
525         default:
526                 return HAL_EINVAL;
527         }
528 }
529
530 HAL_BOOL
531 ath_hal_setcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
532         uint32_t capability, uint32_t setting, HAL_STATUS *status)
533 {
534
535         switch (type) {
536         case HAL_CAP_TXPOW:
537                 switch (capability) {
538                 case 3:
539                         if (setting <= HAL_TP_SCALE_MIN) {
540                                 AH_PRIVATE(ah)->ah_tpScale = setting;
541                                 return AH_TRUE;
542                         }
543                         break;
544                 }
545                 break;
546         case HAL_CAP_RFSILENT:          /* rfsilent support  */
547                 /*
548                  * NB: allow even if halRfSilentSupport is false
549                  *     in case the EEPROM is misprogrammed.
550                  */
551                 switch (capability) {
552                 case 1:                 /* current setting */
553                         AH_PRIVATE(ah)->ah_rfkillEnabled = (setting != 0);
554                         return AH_TRUE;
555                 case 2:                 /* rfsilent config */
556                         /* XXX better done per-chip for validation? */
557                         AH_PRIVATE(ah)->ah_rfsilent = setting;
558                         return AH_TRUE;
559                 }
560                 break;
561         case HAL_CAP_REG_DMN:           /* regulatory domain */
562                 AH_PRIVATE(ah)->ah_currentRD = setting;
563                 return AH_TRUE;
564         case HAL_CAP_RXORN_FATAL:       /* HAL_INT_RXORN treated as fatal  */
565                 AH_PRIVATE(ah)->ah_rxornIsFatal = setting;
566                 return AH_TRUE;
567         default:
568                 break;
569         }
570         if (status)
571                 *status = HAL_EINVAL;
572         return AH_FALSE;
573 }
574
575 /* 
576  * Common support for getDiagState method.
577  */
578
579 static u_int
580 ath_hal_getregdump(struct ath_hal *ah, const HAL_REGRANGE *regs,
581         void *dstbuf, int space)
582 {
583         uint32_t *dp = dstbuf;
584         int i;
585
586         for (i = 0; space >= 2*sizeof(uint32_t); i++) {
587                 u_int r = regs[i].start;
588                 u_int e = regs[i].end;
589                 *dp++ = (r<<16) | e;
590                 space -= sizeof(uint32_t);
591                 do {
592                         *dp++ = OS_REG_READ(ah, r);
593                         r += sizeof(uint32_t);
594                         space -= sizeof(uint32_t);
595                 } while (r <= e && space >= sizeof(uint32_t));
596         }
597         return (char *) dp - (char *) dstbuf;
598 }
599
600 HAL_BOOL
601 ath_hal_getdiagstate(struct ath_hal *ah, int request,
602         const void *args, uint32_t argsize,
603         void **result, uint32_t *resultsize)
604 {
605         switch (request) {
606         case HAL_DIAG_REVS:
607                 *result = &AH_PRIVATE(ah)->ah_devid;
608                 *resultsize = sizeof(HAL_REVS);
609                 return AH_TRUE;
610         case HAL_DIAG_REGS:
611                 *resultsize = ath_hal_getregdump(ah, args, *result,*resultsize);
612                 return AH_TRUE;
613         case HAL_DIAG_FATALERR:
614                 *result = &AH_PRIVATE(ah)->ah_fatalState[0];
615                 *resultsize = sizeof(AH_PRIVATE(ah)->ah_fatalState);
616                 return AH_TRUE;
617         case HAL_DIAG_EEREAD:
618                 if (argsize != sizeof(uint16_t))
619                         return AH_FALSE;
620                 if (!ath_hal_eepromRead(ah, *(const uint16_t *)args, *result))
621                         return AH_FALSE;
622                 *resultsize = sizeof(uint16_t);
623                 return AH_TRUE;
624 #ifdef AH_PRIVATE_DIAG
625         case HAL_DIAG_SETKEY: {
626                 const HAL_DIAG_KEYVAL *dk;
627
628                 if (argsize != sizeof(HAL_DIAG_KEYVAL))
629                         return AH_FALSE;
630                 dk = (const HAL_DIAG_KEYVAL *)args;
631                 return ah->ah_setKeyCacheEntry(ah, dk->dk_keyix,
632                         &dk->dk_keyval, dk->dk_mac, dk->dk_xor);
633         }
634         case HAL_DIAG_RESETKEY:
635                 if (argsize != sizeof(uint16_t))
636                         return AH_FALSE;
637                 return ah->ah_resetKeyCacheEntry(ah, *(const uint16_t *)args);
638 #ifdef AH_SUPPORT_WRITE_EEPROM
639         case HAL_DIAG_EEWRITE: {
640                 const HAL_DIAG_EEVAL *ee;
641                 if (argsize != sizeof(HAL_DIAG_EEVAL))
642                         return AH_FALSE;
643                 ee = (const HAL_DIAG_EEVAL *)args;
644                 return ath_hal_eepromWrite(ah, ee->ee_off, ee->ee_data);
645         }
646 #endif /* AH_SUPPORT_WRITE_EEPROM */
647 #endif /* AH_PRIVATE_DIAG */
648         case HAL_DIAG_11NCOMPAT:
649                 if (argsize == 0) {
650                         *resultsize = sizeof(uint32_t);
651                         *((uint32_t *)(*result)) =
652                                 AH_PRIVATE(ah)->ah_11nCompat;
653                 } else if (argsize == sizeof(uint32_t)) {
654                         AH_PRIVATE(ah)->ah_11nCompat = *(const uint32_t *)args;
655                 } else
656                         return AH_FALSE;
657                 return AH_TRUE;
658         }
659         return AH_FALSE;
660 }
661
662 /*
663  * Set the properties of the tx queue with the parameters
664  * from qInfo.
665  */
666 HAL_BOOL
667 ath_hal_setTxQProps(struct ath_hal *ah,
668         HAL_TX_QUEUE_INFO *qi, const HAL_TXQ_INFO *qInfo)
669 {
670         uint32_t cw;
671
672         if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
673                 HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
674                     "%s: inactive queue\n", __func__);
675                 return AH_FALSE;
676         }
677         /* XXX validate parameters */
678         qi->tqi_ver = qInfo->tqi_ver;
679         qi->tqi_subtype = qInfo->tqi_subtype;
680         qi->tqi_qflags = qInfo->tqi_qflags;
681         qi->tqi_priority = qInfo->tqi_priority;
682         if (qInfo->tqi_aifs != HAL_TXQ_USEDEFAULT)
683                 qi->tqi_aifs = AH_MIN(qInfo->tqi_aifs, 255);
684         else
685                 qi->tqi_aifs = INIT_AIFS;
686         if (qInfo->tqi_cwmin != HAL_TXQ_USEDEFAULT) {
687                 cw = AH_MIN(qInfo->tqi_cwmin, 1024);
688                 /* make sure that the CWmin is of the form (2^n - 1) */
689                 qi->tqi_cwmin = 1;
690                 while (qi->tqi_cwmin < cw)
691                         qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1;
692         } else
693                 qi->tqi_cwmin = qInfo->tqi_cwmin;
694         if (qInfo->tqi_cwmax != HAL_TXQ_USEDEFAULT) {
695                 cw = AH_MIN(qInfo->tqi_cwmax, 1024);
696                 /* make sure that the CWmax is of the form (2^n - 1) */
697                 qi->tqi_cwmax = 1;
698                 while (qi->tqi_cwmax < cw)
699                         qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1;
700         } else
701                 qi->tqi_cwmax = INIT_CWMAX;
702         /* Set retry limit values */
703         if (qInfo->tqi_shretry != 0)
704                 qi->tqi_shretry = AH_MIN(qInfo->tqi_shretry, 15);
705         else
706                 qi->tqi_shretry = INIT_SH_RETRY;
707         if (qInfo->tqi_lgretry != 0)
708                 qi->tqi_lgretry = AH_MIN(qInfo->tqi_lgretry, 15);
709         else
710                 qi->tqi_lgretry = INIT_LG_RETRY;
711         qi->tqi_cbrPeriod = qInfo->tqi_cbrPeriod;
712         qi->tqi_cbrOverflowLimit = qInfo->tqi_cbrOverflowLimit;
713         qi->tqi_burstTime = qInfo->tqi_burstTime;
714         qi->tqi_readyTime = qInfo->tqi_readyTime;
715
716         switch (qInfo->tqi_subtype) {
717         case HAL_WME_UPSD:
718                 if (qi->tqi_type == HAL_TX_QUEUE_DATA)
719                         qi->tqi_intFlags = HAL_TXQ_USE_LOCKOUT_BKOFF_DIS;
720                 break;
721         default:
722                 break;          /* NB: silence compiler */
723         }
724         return AH_TRUE;
725 }
726
727 HAL_BOOL
728 ath_hal_getTxQProps(struct ath_hal *ah,
729         HAL_TXQ_INFO *qInfo, const HAL_TX_QUEUE_INFO *qi)
730 {
731         if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
732                 HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
733                     "%s: inactive queue\n", __func__);
734                 return AH_FALSE;
735         }
736
737         qInfo->tqi_qflags = qi->tqi_qflags;
738         qInfo->tqi_ver = qi->tqi_ver;
739         qInfo->tqi_subtype = qi->tqi_subtype;
740         qInfo->tqi_qflags = qi->tqi_qflags;
741         qInfo->tqi_priority = qi->tqi_priority;
742         qInfo->tqi_aifs = qi->tqi_aifs;
743         qInfo->tqi_cwmin = qi->tqi_cwmin;
744         qInfo->tqi_cwmax = qi->tqi_cwmax;
745         qInfo->tqi_shretry = qi->tqi_shretry;
746         qInfo->tqi_lgretry = qi->tqi_lgretry;
747         qInfo->tqi_cbrPeriod = qi->tqi_cbrPeriod;
748         qInfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit;
749         qInfo->tqi_burstTime = qi->tqi_burstTime;
750         qInfo->tqi_readyTime = qi->tqi_readyTime;
751         return AH_TRUE;
752 }
753
754                                      /* 11a Turbo  11b  11g  108g */
755 static const int16_t NOISE_FLOOR[] = { -96, -93,  -98, -96,  -93 };
756
757 /*
758  * Read the current channel noise floor and return.
759  * If nf cal hasn't finished, channel noise floor should be 0
760  * and we return a nominal value based on band and frequency.
761  *
762  * NB: This is a private routine used by per-chip code to
763  *     implement the ah_getChanNoise method.
764  */
765 int16_t
766 ath_hal_getChanNoise(struct ath_hal *ah, HAL_CHANNEL *chan)
767 {
768         HAL_CHANNEL_INTERNAL *ichan;
769
770         ichan = ath_hal_checkchannel(ah, chan);
771         if (ichan == AH_NULL) {
772                 HALDEBUG(ah, HAL_DEBUG_NFCAL,
773                     "%s: invalid channel %u/0x%x; no mapping\n",
774                     __func__, chan->channel, chan->channelFlags);
775                 return 0;
776         }
777         if (ichan->rawNoiseFloor == 0) {
778                 WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan);
779
780                 HALASSERT(mode < WIRELESS_MODE_MAX);
781                 return NOISE_FLOOR[mode] + ath_hal_getNfAdjust(ah, ichan);
782         } else
783                 return ichan->rawNoiseFloor + ichan->noiseFloorAdjust;
784 }
785
786 /*
787  * Process all valid raw noise floors into the dBm noise floor values.
788  * Though our device has no reference for a dBm noise floor, we perform
789  * a relative minimization of NF's based on the lowest NF found across a
790  * channel scan.
791  */
792 void
793 ath_hal_process_noisefloor(struct ath_hal *ah)
794 {
795         HAL_CHANNEL_INTERNAL *c;
796         int16_t correct2, correct5;
797         int16_t lowest2, lowest5;
798         int i;
799
800         /* 
801          * Find the lowest 2GHz and 5GHz noise floor values after adjusting
802          * for statistically recorded NF/channel deviation.
803          */
804         correct2 = lowest2 = 0;
805         correct5 = lowest5 = 0;
806         for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
807                 WIRELESS_MODE mode;
808                 int16_t nf;
809
810                 c = &AH_PRIVATE(ah)->ah_channels[i];
811                 if (c->rawNoiseFloor >= 0)
812                         continue;
813                 mode = ath_hal_chan2wmode(ah, (HAL_CHANNEL *) c);
814                 HALASSERT(mode < WIRELESS_MODE_MAX);
815                 nf = c->rawNoiseFloor + NOISE_FLOOR[mode] +
816                         ath_hal_getNfAdjust(ah, c);
817                 if (IS_CHAN_5GHZ(c)) {
818                         if (nf < lowest5) { 
819                                 lowest5 = nf;
820                                 correct5 = NOISE_FLOOR[mode] -
821                                     (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
822                         }
823                 } else {
824                         if (nf < lowest2) { 
825                                 lowest2 = nf;
826                                 correct2 = NOISE_FLOOR[mode] -
827                                     (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
828                         }
829                 }
830         }
831
832         /* Correct the channels to reach the expected NF value */
833         for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
834                 c = &AH_PRIVATE(ah)->ah_channels[i];
835                 if (c->rawNoiseFloor >= 0)
836                         continue;
837                 /* Apply correction factor */
838                 c->noiseFloorAdjust = ath_hal_getNfAdjust(ah, c) +
839                         (IS_CHAN_5GHZ(c) ? correct5 : correct2);
840                 HALDEBUG(ah, HAL_DEBUG_NFCAL, "%u/0x%x raw nf %d adjust %d\n",
841                     c->channel, c->channelFlags, c->rawNoiseFloor,
842                     c->noiseFloorAdjust);
843         }
844 }
845
846 /*
847  * INI support routines.
848  */
849
850 int
851 ath_hal_ini_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
852         int col, int regWr)
853 {
854         int r;
855
856         for (r = 0; r < ia->rows; r++) {
857                 OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0),
858                     HAL_INI_VAL(ia, r, col));
859                 DMA_YIELD(regWr);
860         }
861         return regWr;
862 }
863
864 void
865 ath_hal_ini_bank_setup(uint32_t data[], const HAL_INI_ARRAY *ia, int col)
866 {
867         int r;
868
869         for (r = 0; r < ia->rows; r++)
870                 data[r] = HAL_INI_VAL(ia, r, col);
871 }
872
873 int
874 ath_hal_ini_bank_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
875         const uint32_t data[], int regWr)
876 {
877         int r;
878
879         for (r = 0; r < ia->rows; r++) {
880                 OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0), data[r]);
881                 DMA_YIELD(regWr);
882         }
883         return regWr;
884 }