Initial import of binutils 2.22 on the new vendor branch
[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         int i;
387
388         if (rt->rateCodeToIndex[0] != 0)        /* already setup */
389                 return;
390         for (i = 0; i < NELEM(rt->rateCodeToIndex); i++)
391                 rt->rateCodeToIndex[i] = (uint8_t) -1;
392         for (i = 0; i < rt->rateCount; i++) {
393                 uint8_t code = rt->info[i].rateCode;
394                 uint8_t cix = rt->info[i].controlRate;
395
396                 HALASSERT(code < NELEM(rt->rateCodeToIndex));
397                 rt->rateCodeToIndex[code] = i;
398                 HALASSERT((code | rt->info[i].shortPreamble) <
399                     NELEM(rt->rateCodeToIndex));
400                 rt->rateCodeToIndex[code | rt->info[i].shortPreamble] = i;
401                 /*
402                  * XXX for 11g the control rate to use for 5.5 and 11 Mb/s
403                  *     depends on whether they are marked as basic rates;
404                  *     the static tables are setup with an 11b-compatible
405                  *     2Mb/s rate which will work but is suboptimal
406                  */
407                 rt->info[i].lpAckDuration = ath_hal_computetxtime(ah, rt,
408                         WLAN_CTRL_FRAME_SIZE, cix, AH_FALSE);
409                 rt->info[i].spAckDuration = ath_hal_computetxtime(ah, rt,
410                         WLAN_CTRL_FRAME_SIZE, cix, AH_TRUE);
411         }
412 }
413
414 HAL_STATUS
415 ath_hal_getcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
416         uint32_t capability, uint32_t *result)
417 {
418         const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
419
420         switch (type) {
421         case HAL_CAP_REG_DMN:           /* regulatory domain */
422                 *result = AH_PRIVATE(ah)->ah_currentRD;
423                 return HAL_OK;
424         case HAL_CAP_CIPHER:            /* cipher handled in hardware */
425         case HAL_CAP_TKIP_MIC:          /* handle TKIP MIC in hardware */
426                 return HAL_ENOTSUPP;
427         case HAL_CAP_TKIP_SPLIT:        /* hardware TKIP uses split keys */
428                 return HAL_ENOTSUPP;
429         case HAL_CAP_PHYCOUNTERS:       /* hardware PHY error counters */
430                 return pCap->halHwPhyCounterSupport ? HAL_OK : HAL_ENXIO;
431         case HAL_CAP_WME_TKIPMIC:   /* hardware can do TKIP MIC when WMM is turned on */
432                 return HAL_ENOTSUPP;
433         case HAL_CAP_DIVERSITY:         /* hardware supports fast diversity */
434                 return HAL_ENOTSUPP;
435         case HAL_CAP_KEYCACHE_SIZE:     /* hardware key cache size */
436                 *result =  pCap->halKeyCacheSize;
437                 return HAL_OK;
438         case HAL_CAP_NUM_TXQUEUES:      /* number of hardware tx queues */
439                 *result = pCap->halTotalQueues;
440                 return HAL_OK;
441         case HAL_CAP_VEOL:              /* hardware supports virtual EOL */
442                 return pCap->halVEOLSupport ? HAL_OK : HAL_ENOTSUPP;
443         case HAL_CAP_PSPOLL:            /* hardware PS-Poll support works */
444                 return pCap->halPSPollBroken ? HAL_ENOTSUPP : HAL_OK;
445         case HAL_CAP_COMPRESSION:
446                 return pCap->halCompressSupport ? HAL_OK : HAL_ENOTSUPP;
447         case HAL_CAP_BURST:
448                 return pCap->halBurstSupport ? HAL_OK : HAL_ENOTSUPP;
449         case HAL_CAP_FASTFRAME:
450                 return pCap->halFastFramesSupport ? HAL_OK : HAL_ENOTSUPP;
451         case HAL_CAP_DIAG:              /* hardware diagnostic support */
452                 *result = AH_PRIVATE(ah)->ah_diagreg;
453                 return HAL_OK;
454         case HAL_CAP_TXPOW:             /* global tx power limit  */
455                 switch (capability) {
456                 case 0:                 /* facility is supported */
457                         return HAL_OK;
458                 case 1:                 /* current limit */
459                         *result = AH_PRIVATE(ah)->ah_powerLimit;
460                         return HAL_OK;
461                 case 2:                 /* current max tx power */
462                         *result = AH_PRIVATE(ah)->ah_maxPowerLevel;
463                         return HAL_OK;
464                 case 3:                 /* scale factor */
465                         *result = AH_PRIVATE(ah)->ah_tpScale;
466                         return HAL_OK;
467                 }
468                 return HAL_ENOTSUPP;
469         case HAL_CAP_BSSIDMASK:         /* hardware supports bssid mask */
470                 return pCap->halBssIdMaskSupport ? HAL_OK : HAL_ENOTSUPP;
471         case HAL_CAP_MCAST_KEYSRCH:     /* multicast frame keycache search */
472                 return pCap->halMcastKeySrchSupport ? HAL_OK : HAL_ENOTSUPP;
473         case HAL_CAP_TSF_ADJUST:        /* hardware has beacon tsf adjust */
474                 return HAL_ENOTSUPP;
475         case HAL_CAP_RFSILENT:          /* rfsilent support  */
476                 switch (capability) {
477                 case 0:                 /* facility is supported */
478                         return pCap->halRfSilentSupport ? HAL_OK : HAL_ENOTSUPP;
479                 case 1:                 /* current setting */
480                         return AH_PRIVATE(ah)->ah_rfkillEnabled ?
481                                 HAL_OK : HAL_ENOTSUPP;
482                 case 2:                 /* rfsilent config */
483                         *result = AH_PRIVATE(ah)->ah_rfsilent;
484                         return HAL_OK;
485                 }
486                 return HAL_ENOTSUPP;
487         case HAL_CAP_11D:
488                 return HAL_OK;
489         case HAL_CAP_RXORN_FATAL:       /* HAL_INT_RXORN treated as fatal  */
490                 return AH_PRIVATE(ah)->ah_rxornIsFatal ? HAL_OK : HAL_ENOTSUPP;
491         case HAL_CAP_HT:
492                 return pCap->halHTSupport ? HAL_OK : HAL_ENOTSUPP;
493         case HAL_CAP_TX_CHAINMASK:      /* mask of TX chains supported */
494                 *result = pCap->halTxChainMask;
495                 return HAL_OK;
496         case HAL_CAP_RX_CHAINMASK:      /* mask of RX chains supported */
497                 *result = pCap->halRxChainMask;
498                 return HAL_OK;
499         case HAL_CAP_RXTSTAMP_PREC:     /* rx desc tstamp precision (bits) */
500                 *result = pCap->halTstampPrecision;
501                 return HAL_OK;
502         case HAL_CAP_INTRMASK:          /* mask of supported interrupts */
503                 *result = pCap->halIntrMask;
504                 return HAL_OK;
505         case HAL_CAP_BSSIDMATCH:        /* hardware has disable bssid match */
506                 return pCap->halBssidMatchSupport ? HAL_OK : HAL_ENOTSUPP;
507         default:
508                 return HAL_EINVAL;
509         }
510 }
511
512 HAL_BOOL
513 ath_hal_setcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
514         uint32_t capability, uint32_t setting, HAL_STATUS *status)
515 {
516
517         switch (type) {
518         case HAL_CAP_TXPOW:
519                 switch (capability) {
520                 case 3:
521                         if (setting <= HAL_TP_SCALE_MIN) {
522                                 AH_PRIVATE(ah)->ah_tpScale = setting;
523                                 return AH_TRUE;
524                         }
525                         break;
526                 }
527                 break;
528         case HAL_CAP_RFSILENT:          /* rfsilent support  */
529                 /*
530                  * NB: allow even if halRfSilentSupport is false
531                  *     in case the EEPROM is misprogrammed.
532                  */
533                 switch (capability) {
534                 case 1:                 /* current setting */
535                         AH_PRIVATE(ah)->ah_rfkillEnabled = (setting != 0);
536                         return AH_TRUE;
537                 case 2:                 /* rfsilent config */
538                         /* XXX better done per-chip for validation? */
539                         AH_PRIVATE(ah)->ah_rfsilent = setting;
540                         return AH_TRUE;
541                 }
542                 break;
543         case HAL_CAP_REG_DMN:           /* regulatory domain */
544                 AH_PRIVATE(ah)->ah_currentRD = setting;
545                 return AH_TRUE;
546         case HAL_CAP_RXORN_FATAL:       /* HAL_INT_RXORN treated as fatal  */
547                 AH_PRIVATE(ah)->ah_rxornIsFatal = setting;
548                 return AH_TRUE;
549         default:
550                 break;
551         }
552         if (status)
553                 *status = HAL_EINVAL;
554         return AH_FALSE;
555 }
556
557 /* 
558  * Common support for getDiagState method.
559  */
560
561 static u_int
562 ath_hal_getregdump(struct ath_hal *ah, const HAL_REGRANGE *regs,
563         void *dstbuf, int space)
564 {
565         uint32_t *dp = dstbuf;
566         int i;
567
568         for (i = 0; space >= 2*sizeof(uint32_t); i++) {
569                 u_int r = regs[i].start;
570                 u_int e = regs[i].end;
571                 *dp++ = (r<<16) | e;
572                 space -= sizeof(uint32_t);
573                 do {
574                         *dp++ = OS_REG_READ(ah, r);
575                         r += sizeof(uint32_t);
576                         space -= sizeof(uint32_t);
577                 } while (r <= e && space >= sizeof(uint32_t));
578         }
579         return (char *) dp - (char *) dstbuf;
580 }
581  
582 static void
583 ath_hal_setregs(struct ath_hal *ah, const HAL_REGWRITE *regs, int space)
584 {
585         while (space >= sizeof(HAL_REGWRITE)) {
586                 OS_REG_WRITE(ah, regs->addr, regs->value);
587                 regs++, space -= sizeof(HAL_REGWRITE);
588         }
589 }
590
591 HAL_BOOL
592 ath_hal_getdiagstate(struct ath_hal *ah, int request,
593         const void *args, uint32_t argsize,
594         void **result, uint32_t *resultsize)
595 {
596         switch (request) {
597         case HAL_DIAG_REVS:
598                 *result = &AH_PRIVATE(ah)->ah_devid;
599                 *resultsize = sizeof(HAL_REVS);
600                 return AH_TRUE;
601         case HAL_DIAG_REGS:
602                 *resultsize = ath_hal_getregdump(ah, args, *result,*resultsize);
603                 return AH_TRUE;
604         case HAL_DIAG_SETREGS:
605                 ath_hal_setregs(ah, args, argsize);
606                 *resultsize = 0;
607                 return AH_TRUE;
608         case HAL_DIAG_FATALERR:
609                 *result = &AH_PRIVATE(ah)->ah_fatalState[0];
610                 *resultsize = sizeof(AH_PRIVATE(ah)->ah_fatalState);
611                 return AH_TRUE;
612         case HAL_DIAG_EEREAD:
613                 if (argsize != sizeof(uint16_t))
614                         return AH_FALSE;
615                 if (!ath_hal_eepromRead(ah, *(const uint16_t *)args, *result))
616                         return AH_FALSE;
617                 *resultsize = sizeof(uint16_t);
618                 return AH_TRUE;
619 #ifdef AH_PRIVATE_DIAG
620         case HAL_DIAG_SETKEY: {
621                 const HAL_DIAG_KEYVAL *dk;
622
623                 if (argsize != sizeof(HAL_DIAG_KEYVAL))
624                         return AH_FALSE;
625                 dk = (const HAL_DIAG_KEYVAL *)args;
626                 return ah->ah_setKeyCacheEntry(ah, dk->dk_keyix,
627                         &dk->dk_keyval, dk->dk_mac, dk->dk_xor);
628         }
629         case HAL_DIAG_RESETKEY:
630                 if (argsize != sizeof(uint16_t))
631                         return AH_FALSE;
632                 return ah->ah_resetKeyCacheEntry(ah, *(const uint16_t *)args);
633 #ifdef AH_SUPPORT_WRITE_EEPROM
634         case HAL_DIAG_EEWRITE: {
635                 const HAL_DIAG_EEVAL *ee;
636                 if (argsize != sizeof(HAL_DIAG_EEVAL))
637                         return AH_FALSE;
638                 ee = (const HAL_DIAG_EEVAL *)args;
639                 return ath_hal_eepromWrite(ah, ee->ee_off, ee->ee_data);
640         }
641 #endif /* AH_SUPPORT_WRITE_EEPROM */
642 #endif /* AH_PRIVATE_DIAG */
643         case HAL_DIAG_11NCOMPAT:
644                 if (argsize == 0) {
645                         *resultsize = sizeof(uint32_t);
646                         *((uint32_t *)(*result)) =
647                                 AH_PRIVATE(ah)->ah_11nCompat;
648                 } else if (argsize == sizeof(uint32_t)) {
649                         AH_PRIVATE(ah)->ah_11nCompat = *(const uint32_t *)args;
650                 } else
651                         return AH_FALSE;
652                 return AH_TRUE;
653         }
654         return AH_FALSE;
655 }
656
657 /*
658  * Set the properties of the tx queue with the parameters
659  * from qInfo.
660  */
661 HAL_BOOL
662 ath_hal_setTxQProps(struct ath_hal *ah,
663         HAL_TX_QUEUE_INFO *qi, const HAL_TXQ_INFO *qInfo)
664 {
665         uint32_t cw;
666
667         if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
668                 HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
669                     "%s: inactive queue\n", __func__);
670                 return AH_FALSE;
671         }
672         /* XXX validate parameters */
673         qi->tqi_ver = qInfo->tqi_ver;
674         qi->tqi_subtype = qInfo->tqi_subtype;
675         qi->tqi_qflags = qInfo->tqi_qflags;
676         qi->tqi_priority = qInfo->tqi_priority;
677         if (qInfo->tqi_aifs != HAL_TXQ_USEDEFAULT)
678                 qi->tqi_aifs = AH_MIN(qInfo->tqi_aifs, 255);
679         else
680                 qi->tqi_aifs = INIT_AIFS;
681         if (qInfo->tqi_cwmin != HAL_TXQ_USEDEFAULT) {
682                 cw = AH_MIN(qInfo->tqi_cwmin, 1024);
683                 /* make sure that the CWmin is of the form (2^n - 1) */
684                 qi->tqi_cwmin = 1;
685                 while (qi->tqi_cwmin < cw)
686                         qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1;
687         } else
688                 qi->tqi_cwmin = qInfo->tqi_cwmin;
689         if (qInfo->tqi_cwmax != HAL_TXQ_USEDEFAULT) {
690                 cw = AH_MIN(qInfo->tqi_cwmax, 1024);
691                 /* make sure that the CWmax is of the form (2^n - 1) */
692                 qi->tqi_cwmax = 1;
693                 while (qi->tqi_cwmax < cw)
694                         qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1;
695         } else
696                 qi->tqi_cwmax = INIT_CWMAX;
697         /* Set retry limit values */
698         if (qInfo->tqi_shretry != 0)
699                 qi->tqi_shretry = AH_MIN(qInfo->tqi_shretry, 15);
700         else
701                 qi->tqi_shretry = INIT_SH_RETRY;
702         if (qInfo->tqi_lgretry != 0)
703                 qi->tqi_lgretry = AH_MIN(qInfo->tqi_lgretry, 15);
704         else
705                 qi->tqi_lgretry = INIT_LG_RETRY;
706         qi->tqi_cbrPeriod = qInfo->tqi_cbrPeriod;
707         qi->tqi_cbrOverflowLimit = qInfo->tqi_cbrOverflowLimit;
708         qi->tqi_burstTime = qInfo->tqi_burstTime;
709         qi->tqi_readyTime = qInfo->tqi_readyTime;
710
711         switch (qInfo->tqi_subtype) {
712         case HAL_WME_UPSD:
713                 if (qi->tqi_type == HAL_TX_QUEUE_DATA)
714                         qi->tqi_intFlags = HAL_TXQ_USE_LOCKOUT_BKOFF_DIS;
715                 break;
716         default:
717                 break;          /* NB: silence compiler */
718         }
719         return AH_TRUE;
720 }
721
722 HAL_BOOL
723 ath_hal_getTxQProps(struct ath_hal *ah,
724         HAL_TXQ_INFO *qInfo, const HAL_TX_QUEUE_INFO *qi)
725 {
726         if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
727                 HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
728                     "%s: inactive queue\n", __func__);
729                 return AH_FALSE;
730         }
731
732         qInfo->tqi_qflags = qi->tqi_qflags;
733         qInfo->tqi_ver = qi->tqi_ver;
734         qInfo->tqi_subtype = qi->tqi_subtype;
735         qInfo->tqi_qflags = qi->tqi_qflags;
736         qInfo->tqi_priority = qi->tqi_priority;
737         qInfo->tqi_aifs = qi->tqi_aifs;
738         qInfo->tqi_cwmin = qi->tqi_cwmin;
739         qInfo->tqi_cwmax = qi->tqi_cwmax;
740         qInfo->tqi_shretry = qi->tqi_shretry;
741         qInfo->tqi_lgretry = qi->tqi_lgretry;
742         qInfo->tqi_cbrPeriod = qi->tqi_cbrPeriod;
743         qInfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit;
744         qInfo->tqi_burstTime = qi->tqi_burstTime;
745         qInfo->tqi_readyTime = qi->tqi_readyTime;
746         return AH_TRUE;
747 }
748
749                                      /* 11a Turbo  11b  11g  108g */
750 static const int16_t NOISE_FLOOR[] = { -96, -93,  -98, -96,  -93 };
751
752 /*
753  * Read the current channel noise floor and return.
754  * If nf cal hasn't finished, channel noise floor should be 0
755  * and we return a nominal value based on band and frequency.
756  *
757  * NB: This is a private routine used by per-chip code to
758  *     implement the ah_getChanNoise method.
759  */
760 int16_t
761 ath_hal_getChanNoise(struct ath_hal *ah, const struct ieee80211_channel *chan)
762 {
763         HAL_CHANNEL_INTERNAL *ichan;
764
765         ichan = ath_hal_checkchannel(ah, chan);
766         if (ichan == AH_NULL) {
767                 HALDEBUG(ah, HAL_DEBUG_NFCAL,
768                     "%s: invalid channel %u/0x%x; no mapping\n",
769                     __func__, chan->ic_freq, chan->ic_flags);
770                 return 0;
771         }
772         if (ichan->rawNoiseFloor == 0) {
773                 WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan);
774
775                 HALASSERT(mode < WIRELESS_MODE_MAX);
776                 return NOISE_FLOOR[mode] + ath_hal_getNfAdjust(ah, ichan);
777         } else
778                 return ichan->rawNoiseFloor + ichan->noiseFloorAdjust;
779 }
780
781 /*
782  * Process all valid raw noise floors into the dBm noise floor values.
783  * Though our device has no reference for a dBm noise floor, we perform
784  * a relative minimization of NF's based on the lowest NF found across a
785  * channel scan.
786  */
787 void
788 ath_hal_process_noisefloor(struct ath_hal *ah)
789 {
790         HAL_CHANNEL_INTERNAL *c;
791         int16_t correct2, correct5;
792         int16_t lowest2, lowest5;
793         int i;
794
795         /* 
796          * Find the lowest 2GHz and 5GHz noise floor values after adjusting
797          * for statistically recorded NF/channel deviation.
798          */
799         correct2 = lowest2 = 0;
800         correct5 = lowest5 = 0;
801         for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
802                 WIRELESS_MODE mode;
803                 int16_t nf;
804
805                 c = &AH_PRIVATE(ah)->ah_channels[i];
806                 if (c->rawNoiseFloor >= 0)
807                         continue;
808                 /* XXX can't identify proper mode */
809                 mode = IS_CHAN_5GHZ(c) ? WIRELESS_MODE_11a : WIRELESS_MODE_11g;
810                 nf = c->rawNoiseFloor + NOISE_FLOOR[mode] +
811                         ath_hal_getNfAdjust(ah, c);
812                 if (IS_CHAN_5GHZ(c)) {
813                         if (nf < lowest5) { 
814                                 lowest5 = nf;
815                                 correct5 = NOISE_FLOOR[mode] -
816                                     (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
817                         }
818                 } else {
819                         if (nf < lowest2) { 
820                                 lowest2 = nf;
821                                 correct2 = NOISE_FLOOR[mode] -
822                                     (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
823                         }
824                 }
825         }
826
827         /* Correct the channels to reach the expected NF value */
828         for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
829                 c = &AH_PRIVATE(ah)->ah_channels[i];
830                 if (c->rawNoiseFloor >= 0)
831                         continue;
832                 /* Apply correction factor */
833                 c->noiseFloorAdjust = ath_hal_getNfAdjust(ah, c) +
834                         (IS_CHAN_5GHZ(c) ? correct5 : correct2);
835                 HALDEBUG(ah, HAL_DEBUG_NFCAL, "%u raw nf %d adjust %d\n",
836                     c->channel, c->rawNoiseFloor, c->noiseFloorAdjust);
837         }
838 }
839
840 /*
841  * INI support routines.
842  */
843
844 int
845 ath_hal_ini_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
846         int col, int regWr)
847 {
848         int r;
849
850         HALASSERT(col < ia->cols);
851         for (r = 0; r < ia->rows; r++) {
852                 OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0),
853                     HAL_INI_VAL(ia, r, col));
854                 DMA_YIELD(regWr);
855         }
856         return regWr;
857 }
858
859 void
860 ath_hal_ini_bank_setup(uint32_t data[], const HAL_INI_ARRAY *ia, int col)
861 {
862         int r;
863
864         HALASSERT(col < ia->cols);
865         for (r = 0; r < ia->rows; r++)
866                 data[r] = HAL_INI_VAL(ia, r, col);
867 }
868
869 int
870 ath_hal_ini_bank_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
871         const uint32_t data[], int regWr)
872 {
873         int r;
874
875         for (r = 0; r < ia->rows; r++) {
876                 OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0), data[r]);
877                 DMA_YIELD(regWr);
878         }
879         return regWr;
880 }