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