Check for SYS/GL during library init. Reason is that
[AROS.git] / workbench / devs / networks / atheros5000 / hal / ah.c
blob92e6daab4b449cc2853f06d8f0a7f53ab45562cd
1 /*
2 * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
3 * Copyright (c) 2002-2008 Atheros Communications, Inc.
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.
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.
17 * $Id$
19 #include "opt_ah.h"
21 #include "ah.h"
22 #include "ah_internal.h"
23 #include "ah_devid.h"
25 #ifdef AH_SUPPORT_AR5210
26 extern struct ath_hal *ar5210Attach(uint16_t, HAL_SOFTC,
27 HAL_BUS_TAG, HAL_BUS_HANDLE, HAL_STATUS*);
28 #endif
29 #ifdef AH_SUPPORT_AR5211
30 extern struct ath_hal *ar5211Attach(uint16_t, HAL_SOFTC,
31 HAL_BUS_TAG, HAL_BUS_HANDLE, HAL_STATUS*);
32 #endif
33 #ifdef AH_SUPPORT_AR5212
34 extern struct ath_hal *ar5212Attach(uint16_t, HAL_SOFTC,
35 HAL_BUS_TAG, HAL_BUS_HANDLE, HAL_STATUS*);
36 #endif
37 #ifdef AH_SUPPORT_AR5312
38 extern struct ath_hal *ar5312Attach(uint16_t, HAL_SOFTC,
39 HAL_BUS_TAG, HAL_BUS_HANDLE, HAL_STATUS*);
40 #endif
41 #ifdef AH_SUPPORT_AR5416
42 extern struct ath_hal *ar5416Attach(uint16_t, HAL_SOFTC,
43 HAL_BUS_TAG, HAL_BUS_HANDLE, HAL_STATUS*);
44 #endif
45 #ifdef AH_SUPPORT_AR9160
46 extern struct ath_hal *ar9160Attach(uint16_t, HAL_SOFTC,
47 HAL_BUS_TAG, HAL_BUS_HANDLE, HAL_STATUS*);
48 #endif
50 #include "version.h"
51 char ath_hal_version[] = ATH_HAL_VERSION;
52 const char* ath_hal_buildopts[] = {
53 #ifdef AH_SUPPORT_AR5210
54 "AR5210",
55 #endif
56 #ifdef AH_SUPPORT_AR5211
57 "AR5211",
58 #endif
59 #ifdef AH_SUPPORT_AR5212
60 "AR5212",
61 #endif
62 #ifdef AH_SUPPORT_AR5312
63 "AR5312",
64 #endif
65 #ifdef AH_SUPPORT_AR5416
66 "AR5416",
67 #endif
68 #ifdef AH_SUPPORT_AR9180
69 "AR9180",
70 #endif
71 #ifdef AH_SUPPORT_5111
72 "RF5111",
73 #endif
74 #ifdef AH_SUPPORT_5112
75 "RF5112",
76 #endif
77 #ifdef AH_SUPPORT_2413
78 "RF2413",
79 #endif
80 #ifdef AH_SUPPORT_5413
81 "RF5413",
82 #endif
83 #ifdef AH_SUPPORT_2316
84 "RF2316",
85 #endif
86 #ifdef AH_SUPPORT_2317
87 "RF2317",
88 #endif
89 #ifdef AH_SUPPORT_2133
90 "RF2133",
91 #endif
92 #ifdef AH_SUPPORT_2425
93 "RF2425",
94 #endif
95 #ifdef AH_SUPPORT_2417
96 "RF2417",
97 #endif
98 #ifdef AH_DEBUG
99 "DEBUG",
100 #endif
101 #ifdef AH_ASSERT
102 "ASSERT",
103 #endif
104 #ifdef AH_DEBUG_ALQ
105 "DEBUG_ALQ",
106 #endif
107 #ifdef AH_REGOPS_FUNC
108 "REGOPS_FUNC",
109 #endif
110 #ifdef AH_PRIVATE_DIAG
111 "PRIVATE_DIAG",
112 #endif
113 #ifdef AH_DEBUG_COUNTRY
114 "DEBUG_COUNTRY",
115 #endif
116 #ifdef AH_NEED_DESC_SWAP
117 "TX_DESC_SWAP",
118 #endif
119 #ifdef AH_DISABLE_WME
120 "DISABLE_WME",
121 #endif
122 #ifdef AH_SUPPORT_11D
123 "11D",
124 #endif
125 AH_NULL
128 static const char*
129 ath_hal_devname(uint16_t devid)
131 switch (devid) {
132 case AR5210_PROD:
133 case AR5210_DEFAULT:
134 return "Atheros 5210";
136 case AR5211_DEVID:
137 case AR5311_DEVID:
138 case AR5211_DEFAULT:
139 return "Atheros 5211";
140 case AR5211_FPGA11B:
141 return "Atheros 5211 (FPGA)";
143 case AR5212_FPGA:
144 return "Atheros 5212 (FPGA)";
145 case AR5212_AR5312_REV2:
146 case AR5212_AR5312_REV7:
147 return "Atheros 5312 WiSoC";
148 case AR5212_AR2315_REV6:
149 case AR5212_AR2315_REV7:
150 return "Atheros 2315 WiSoC";
151 case AR5212_AR2317_REV1:
152 return "Atheros 2317 WiSoC";
153 case AR5212_AR2313_REV8:
154 return "Atheros 2313 WiSoC";
155 case AR5212_DEVID:
156 case AR5212_DEVID_IBM:
157 case AR5212_DEFAULT:
158 return "Atheros 5212";
159 case AR5212_AR2413:
160 return "Atheros 2413";
161 case AR5212_AR2417:
162 return "Atheros 2417";
163 case AR5212_AR5413:
164 return "Atheros 5413";
165 case AR5212_AR5424:
166 return "Atheros 5424/2424";
167 case AR5416_DEVID_PCI:
168 case AR5416_DEVID_PCIE:
169 return "Atheros 5416";
170 case AR9160_DEVID_PCI:
171 return "Atheros 9160";
173 return AH_NULL;
176 const char*
177 ath_hal_probe(uint16_t vendorid, uint16_t devid)
179 return (vendorid == ATHEROS_VENDOR_ID ||
180 vendorid == ATHEROS_3COM_VENDOR_ID ||
181 vendorid == ATHEROS_3COM2_VENDOR_ID ?
182 ath_hal_devname(devid) : 0);
186 * Attach detects device chip revisions, initializes the hwLayer
187 * function list, reads EEPROM information,
188 * selects reset vectors, and performs a short self test.
189 * Any failures will return an error that should cause a hardware
190 * disable.
192 struct ath_hal*
193 ath_hal_attach(uint16_t devid, HAL_SOFTC sc,
194 HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *error)
196 struct ath_hal *ah=AH_NULL;
198 switch (devid) {
199 #ifdef AH_SUPPORT_AR5210
200 case AR5210_AP:
201 case AR5210_PROD:
202 case AR5210_DEFAULT:
203 ah = ar5210Attach(devid, sc, st, sh, error);
204 break;
205 #endif
206 #ifdef AH_SUPPORT_AR5211
207 case AR5211_DEVID:
208 case AR5311_DEVID:
209 case AR5211_FPGA11B:
210 case AR5211_DEFAULT:
211 ah = ar5211Attach(devid, sc, st, sh, error);
212 break;
213 #endif
214 #ifdef AH_SUPPORT_AR5212
215 case AR5212_DEVID_IBM:
216 case AR5212_AR2413:
217 case AR5212_AR2417:
218 case AR5212_AR5413:
219 case AR5212_AR5424:
220 case AR5212_DEVID_FF19: /* XXX PCI Express extra */
221 devid = AR5212_DEVID;
222 /* fall thru... */
223 case AR5212_DEVID:
224 case AR5212_FPGA:
225 case AR5212_DEFAULT:
226 ah = ar5212Attach(devid, sc, st, sh, error);
227 break;
228 #endif
229 #ifdef AH_SUPPORT_AR5312
230 case AR5212_AR5312_REV2:
231 case AR5212_AR5312_REV7:
232 case AR5212_AR2313_REV8:
233 case AR5212_AR2315_REV6:
234 case AR5212_AR2315_REV7:
235 case AR5212_AR2317_REV1:
236 ah = ar5312Attach(devid, sc, st, sh, error);
237 break;
238 #endif
239 #ifdef AH_SUPPORT_AR5416
240 case AR5416_DEVID_PCI:
241 case AR5416_DEVID_PCIE:
242 ah = ar5416Attach(devid, sc, st, sh, error);
243 break;
244 #endif
245 #ifdef AH_SUPPORT_AR9160
246 case AR9160_DEVID_PCI:
247 ah = ar9160Attach(devid, sc, st, sh, error);
248 break;
249 #endif
250 default:
251 ah = AH_NULL;
252 *error = HAL_ENXIO;
253 break;
255 if (ah != AH_NULL) {
256 /* copy back private state to public area */
257 ah->ah_devid = AH_PRIVATE(ah)->ah_devid;
258 ah->ah_subvendorid = AH_PRIVATE(ah)->ah_subvendorid;
259 ah->ah_macVersion = AH_PRIVATE(ah)->ah_macVersion;
260 ah->ah_macRev = AH_PRIVATE(ah)->ah_macRev;
261 ah->ah_phyRev = AH_PRIVATE(ah)->ah_phyRev;
262 ah->ah_analog5GhzRev = AH_PRIVATE(ah)->ah_analog5GhzRev;
263 ah->ah_analog2GhzRev = AH_PRIVATE(ah)->ah_analog2GhzRev;
265 return ah;
269 * Poll the register looking for a specific value.
271 HAL_BOOL
272 ath_hal_wait(struct ath_hal *ah, u_int reg, uint32_t mask, uint32_t val)
274 #define AH_TIMEOUT 1000
275 int i;
277 for (i = 0; i < AH_TIMEOUT; i++) {
278 if ((OS_REG_READ(ah, reg) & mask) == val)
279 return AH_TRUE;
280 OS_DELAY(10);
282 HALDEBUG(ah, HAL_DEBUG_REGIO | HAL_DEBUG_PHYIO,
283 "%s: timeout on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n",
284 __func__, reg, OS_REG_READ(ah, reg), mask, val);
285 return AH_FALSE;
286 #undef AH_TIMEOUT
290 * Reverse the bits starting at the low bit for a value of
291 * bit_count in size
293 uint32_t
294 ath_hal_reverseBits(uint32_t val, uint32_t n)
296 uint32_t retval;
297 int i;
299 for (i = 0, retval = 0; i < n; i++) {
300 retval = (retval << 1) | (val & 1);
301 val >>= 1;
303 return retval;
307 * Compute the time to transmit a frame of length frameLen bytes
308 * using the specified rate, phy, and short preamble setting.
310 uint16_t
311 ath_hal_computetxtime(struct ath_hal *ah,
312 const HAL_RATE_TABLE *rates, uint32_t frameLen, uint16_t rateix,
313 HAL_BOOL shortPreamble)
315 uint32_t bitsPerSymbol, numBits, numSymbols, phyTime, txTime;
316 uint32_t kbps;
318 kbps = rates->info[rateix].rateKbps;
320 * index can be invalid duting dynamic Turbo transitions.
322 if(kbps == 0) return 0;
323 switch (rates->info[rateix].phy) {
325 case IEEE80211_T_CCK:
326 #define CCK_SIFS_TIME 10
327 #define CCK_PREAMBLE_BITS 144
328 #define CCK_PLCP_BITS 48
329 phyTime = CCK_PREAMBLE_BITS + CCK_PLCP_BITS;
330 if (shortPreamble && rates->info[rateix].shortPreamble)
331 phyTime >>= 1;
332 numBits = frameLen << 3;
333 txTime = CCK_SIFS_TIME + phyTime
334 + ((numBits * 1000)/kbps);
335 break;
336 #undef CCK_SIFS_TIME
337 #undef CCK_PREAMBLE_BITS
338 #undef CCK_PLCP_BITS
340 case IEEE80211_T_OFDM:
341 #define OFDM_SIFS_TIME 16
342 #define OFDM_PREAMBLE_TIME 20
343 #define OFDM_PLCP_BITS 22
344 #define OFDM_SYMBOL_TIME 4
346 #define OFDM_SIFS_TIME_HALF 32
347 #define OFDM_PREAMBLE_TIME_HALF 40
348 #define OFDM_PLCP_BITS_HALF 22
349 #define OFDM_SYMBOL_TIME_HALF 8
351 #define OFDM_SIFS_TIME_QUARTER 64
352 #define OFDM_PREAMBLE_TIME_QUARTER 80
353 #define OFDM_PLCP_BITS_QUARTER 22
354 #define OFDM_SYMBOL_TIME_QUARTER 16
356 if (AH_PRIVATE(ah)->ah_curchan &&
357 IS_CHAN_QUARTER_RATE(AH_PRIVATE(ah)->ah_curchan)) {
358 bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME_QUARTER) / 1000;
359 HALASSERT(bitsPerSymbol != 0);
361 numBits = OFDM_PLCP_BITS + (frameLen << 3);
362 numSymbols = howmany(numBits, bitsPerSymbol);
363 txTime = OFDM_SIFS_TIME_QUARTER
364 + OFDM_PREAMBLE_TIME_QUARTER
365 + (numSymbols * OFDM_SYMBOL_TIME_QUARTER);
366 } else if (AH_PRIVATE(ah)->ah_curchan &&
367 IS_CHAN_HALF_RATE(AH_PRIVATE(ah)->ah_curchan)) {
368 bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME_HALF) / 1000;
369 HALASSERT(bitsPerSymbol != 0);
371 numBits = OFDM_PLCP_BITS + (frameLen << 3);
372 numSymbols = howmany(numBits, bitsPerSymbol);
373 txTime = OFDM_SIFS_TIME_HALF +
374 OFDM_PREAMBLE_TIME_HALF
375 + (numSymbols * OFDM_SYMBOL_TIME_HALF);
376 } else { /* full rate channel */
377 bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME) / 1000;
378 HALASSERT(bitsPerSymbol != 0);
380 numBits = OFDM_PLCP_BITS + (frameLen << 3);
381 numSymbols = howmany(numBits, bitsPerSymbol);
382 txTime = OFDM_SIFS_TIME + OFDM_PREAMBLE_TIME
383 + (numSymbols * OFDM_SYMBOL_TIME);
385 break;
387 #undef OFDM_SIFS_TIME
388 #undef OFDM_PREAMBLE_TIME
389 #undef OFDM_PLCP_BITS
390 #undef OFDM_SYMBOL_TIME
392 case IEEE80211_T_TURBO:
393 #define TURBO_SIFS_TIME 8
394 #define TURBO_PREAMBLE_TIME 14
395 #define TURBO_PLCP_BITS 22
396 #define TURBO_SYMBOL_TIME 4
397 /* we still save OFDM rates in kbps - so double them */
398 bitsPerSymbol = ((kbps << 1) * TURBO_SYMBOL_TIME) / 1000;
399 HALASSERT(bitsPerSymbol != 0);
401 numBits = TURBO_PLCP_BITS + (frameLen << 3);
402 numSymbols = howmany(numBits, bitsPerSymbol);
403 txTime = TURBO_SIFS_TIME + TURBO_PREAMBLE_TIME
404 + (numSymbols * TURBO_SYMBOL_TIME);
405 break;
406 #undef TURBO_SIFS_TIME
407 #undef TURBO_PREAMBLE_TIME
408 #undef TURBO_PLCP_BITS
409 #undef TURBO_SYMBOL_TIME
411 default:
412 HALDEBUG(ah, HAL_DEBUG_PHYIO,
413 "%s: unknown phy %u (rate ix %u)\n",
414 __func__, rates->info[rateix].phy, rateix);
415 txTime = 0;
416 break;
418 return txTime;
421 static __inline int
422 mappsb(u_int freq, u_int flags)
424 return ((freq * 10) + (((freq % 5) == 2) ? 5 : 0) - 49400) / 5;
428 * Convert GHz frequency to IEEE channel number.
431 ath_hal_mhz2ieee(struct ath_hal *ah, u_int freq, u_int flags)
433 if (flags & CHANNEL_2GHZ) { /* 2GHz band */
434 if (freq == 2484)
435 return 14;
436 if (freq < 2484) {
437 return ((int)freq - 2407) / 5;
438 } else
439 return 15 + ((freq - 2512) / 20);
440 } else if (flags & CHANNEL_5GHZ) {/* 5Ghz band */
441 if (ath_hal_ispublicsafetysku(ah) &&
442 IS_CHAN_IN_PUBLIC_SAFETY_BAND(freq)) {
443 return mappsb(freq, flags);
444 } else if ((flags & CHANNEL_A) && (freq <= 5000)) {
445 return (freq - 4000) / 5;
446 } else {
447 return (freq - 5000) / 5;
449 } else { /* either, guess */
450 if (freq == 2484)
451 return 14;
452 if (freq < 2484) {
453 return ((int)freq - 2407) / 5;
455 if (freq < 5000) {
456 if (ath_hal_ispublicsafetysku(ah) &&
457 IS_CHAN_IN_PUBLIC_SAFETY_BAND(freq)) {
458 return mappsb(freq, flags);
459 } else if (freq > 4900) {
460 return (freq - 4000) / 5;
461 } else {
462 return 15 + ((freq - 2512) / 20);
465 return (freq - 5000) / 5;
469 typedef enum {
470 WIRELESS_MODE_11a = 0,
471 WIRELESS_MODE_TURBO = 1,
472 WIRELESS_MODE_11b = 2,
473 WIRELESS_MODE_11g = 3,
474 WIRELESS_MODE_108g = 4,
476 WIRELESS_MODE_MAX
477 } WIRELESS_MODE;
479 static WIRELESS_MODE
480 ath_hal_chan2wmode(struct ath_hal *ah, const HAL_CHANNEL *chan)
482 if (IS_CHAN_CCK(chan))
483 return WIRELESS_MODE_11b;
484 if (IS_CHAN_G(chan))
485 return WIRELESS_MODE_11g;
486 if (IS_CHAN_108G(chan))
487 return WIRELESS_MODE_108g;
488 if (IS_CHAN_TURBO(chan))
489 return WIRELESS_MODE_TURBO;
490 return WIRELESS_MODE_11a;
494 * Convert between microseconds and core system clocks.
496 /* 11a Turbo 11b 11g 108g */
497 static const uint8_t CLOCK_RATE[] = { 40, 80, 22, 44, 88 };
499 u_int
500 ath_hal_mac_clks(struct ath_hal *ah, u_int usecs)
502 const HAL_CHANNEL *c = (const HAL_CHANNEL *) AH_PRIVATE(ah)->ah_curchan;
503 u_int clks;
505 /* NB: ah_curchan may be null when called attach time */
506 if (c != AH_NULL) {
507 clks = usecs * CLOCK_RATE[ath_hal_chan2wmode(ah, c)];
508 if (IS_CHAN_HT40(c))
509 clks <<= 1;
510 else if (IS_CHAN_HALF_RATE(c))
511 clks >>= 1;
512 else if (IS_CHAN_QUARTER_RATE(c))
513 clks >>= 2;
514 } else
515 clks = usecs * CLOCK_RATE[WIRELESS_MODE_11b];
516 return clks;
519 u_int
520 ath_hal_mac_usec(struct ath_hal *ah, u_int clks)
522 const HAL_CHANNEL *c = (const HAL_CHANNEL *) AH_PRIVATE(ah)->ah_curchan;
523 u_int usec;
525 /* NB: ah_curchan may be null when called attach time */
526 if (c != AH_NULL) {
527 usec = clks / CLOCK_RATE[ath_hal_chan2wmode(ah, c)];
528 if (IS_CHAN_HT40(c))
529 usec >>= 1;
530 else if (IS_CHAN_HALF_RATE(c))
531 usec <<= 1;
532 else if (IS_CHAN_QUARTER_RATE(c))
533 usec <<= 2;
534 } else
535 usec = clks / CLOCK_RATE[WIRELESS_MODE_11b];
536 return usec;
540 * Setup a h/w rate table's reverse lookup table and
541 * fill in ack durations. This routine is called for
542 * each rate table returned through the ah_getRateTable
543 * method. The reverse lookup tables are assumed to be
544 * initialized to zero (or at least the first entry).
545 * We use this as a key that indicates whether or not
546 * we've previously setup the reverse lookup table.
548 * XXX not reentrant, but shouldn't matter
550 void
551 ath_hal_setupratetable(struct ath_hal *ah, HAL_RATE_TABLE *rt)
553 #define N(a) (sizeof(a)/sizeof(a[0]))
554 int i;
556 if (rt->rateCodeToIndex[0] != 0) /* already setup */
557 return;
558 for (i = 0; i < N(rt->rateCodeToIndex); i++)
559 rt->rateCodeToIndex[i] = (uint8_t) -1;
560 for (i = 0; i < rt->rateCount; i++) {
561 uint8_t code = rt->info[i].rateCode;
562 uint8_t cix = rt->info[i].controlRate;
564 HALASSERT(code < N(rt->rateCodeToIndex));
565 rt->rateCodeToIndex[code] = i;
566 HALASSERT((code | rt->info[i].shortPreamble) <
567 N(rt->rateCodeToIndex));
568 rt->rateCodeToIndex[code | rt->info[i].shortPreamble] = i;
570 * XXX for 11g the control rate to use for 5.5 and 11 Mb/s
571 * depends on whether they are marked as basic rates;
572 * the static tables are setup with an 11b-compatible
573 * 2Mb/s rate which will work but is suboptimal
575 rt->info[i].lpAckDuration = ath_hal_computetxtime(ah, rt,
576 WLAN_CTRL_FRAME_SIZE, cix, AH_FALSE);
577 rt->info[i].spAckDuration = ath_hal_computetxtime(ah, rt,
578 WLAN_CTRL_FRAME_SIZE, cix, AH_TRUE);
580 #undef N
583 HAL_STATUS
584 ath_hal_getcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
585 uint32_t capability, uint32_t *result)
587 const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
589 switch (type) {
590 case HAL_CAP_REG_DMN: /* regulatory domain */
591 *result = AH_PRIVATE(ah)->ah_currentRD;
592 return HAL_OK;
593 case HAL_CAP_CIPHER: /* cipher handled in hardware */
594 case HAL_CAP_TKIP_MIC: /* handle TKIP MIC in hardware */
595 return HAL_ENOTSUPP;
596 case HAL_CAP_TKIP_SPLIT: /* hardware TKIP uses split keys */
597 return HAL_ENOTSUPP;
598 case HAL_CAP_PHYCOUNTERS: /* hardware PHY error counters */
599 return pCap->halHwPhyCounterSupport ? HAL_OK : HAL_ENXIO;
600 case HAL_CAP_WME_TKIPMIC: /* hardware can do TKIP MIC when WMM is turned on */
601 return HAL_ENOTSUPP;
602 case HAL_CAP_DIVERSITY: /* hardware supports fast diversity */
603 return HAL_ENOTSUPP;
604 case HAL_CAP_KEYCACHE_SIZE: /* hardware key cache size */
605 *result = pCap->halKeyCacheSize;
606 return HAL_OK;
607 case HAL_CAP_NUM_TXQUEUES: /* number of hardware tx queues */
608 *result = pCap->halTotalQueues;
609 return HAL_OK;
610 case HAL_CAP_VEOL: /* hardware supports virtual EOL */
611 return pCap->halVEOLSupport ? HAL_OK : HAL_ENOTSUPP;
612 case HAL_CAP_PSPOLL: /* hardware PS-Poll support works */
613 return pCap->halPSPollBroken ? HAL_ENOTSUPP : HAL_OK;
614 case HAL_CAP_COMPRESSION:
615 return pCap->halCompressSupport ? HAL_OK : HAL_ENOTSUPP;
616 case HAL_CAP_BURST:
617 return pCap->halBurstSupport ? HAL_OK : HAL_ENOTSUPP;
618 case HAL_CAP_FASTFRAME:
619 return pCap->halFastFramesSupport ? HAL_OK : HAL_ENOTSUPP;
620 case HAL_CAP_DIAG: /* hardware diagnostic support */
621 *result = AH_PRIVATE(ah)->ah_diagreg;
622 return HAL_OK;
623 case HAL_CAP_TXPOW: /* global tx power limit */
624 switch (capability) {
625 case 0: /* facility is supported */
626 return HAL_OK;
627 case 1: /* current limit */
628 *result = AH_PRIVATE(ah)->ah_powerLimit;
629 return HAL_OK;
630 case 2: /* current max tx power */
631 *result = AH_PRIVATE(ah)->ah_maxPowerLevel;
632 return HAL_OK;
633 case 3: /* scale factor */
634 *result = AH_PRIVATE(ah)->ah_tpScale;
635 return HAL_OK;
637 return HAL_ENOTSUPP;
638 case HAL_CAP_BSSIDMASK: /* hardware supports bssid mask */
639 return pCap->halBssIdMaskSupport ? HAL_OK : HAL_ENOTSUPP;
640 case HAL_CAP_MCAST_KEYSRCH: /* multicast frame keycache search */
641 return pCap->halMcastKeySrchSupport ? HAL_OK : HAL_ENOTSUPP;
642 case HAL_CAP_TSF_ADJUST: /* hardware has beacon tsf adjust */
643 return HAL_ENOTSUPP;
644 case HAL_CAP_CHAN_HALFRATE:
645 return pCap->halChanHalfRate ? HAL_OK : HAL_ENOTSUPP;
646 case HAL_CAP_CHAN_QUARTERRATE:
647 return pCap->halChanQuarterRate ? HAL_OK : HAL_ENOTSUPP;
648 case HAL_CAP_RFSILENT: /* rfsilent support */
649 switch (capability) {
650 case 0: /* facility is supported */
651 return pCap->halRfSilentSupport ? HAL_OK : HAL_ENOTSUPP;
652 case 1: /* current setting */
653 return AH_PRIVATE(ah)->ah_rfkillEnabled ?
654 HAL_OK : HAL_ENOTSUPP;
655 case 2: /* rfsilent config */
656 *result = AH_PRIVATE(ah)->ah_rfsilent;
657 return HAL_OK;
659 return HAL_ENOTSUPP;
660 case HAL_CAP_11D:
661 #ifdef AH_SUPPORT_11D
662 return HAL_OK;
663 #else
664 return HAL_ENOTSUPP;
665 #endif
666 case HAL_CAP_RXORN_FATAL: /* HAL_INT_RXORN treated as fatal */
667 return AH_PRIVATE(ah)->ah_rxornIsFatal ? HAL_OK : HAL_ENOTSUPP;
668 case HAL_CAP_HT:
669 return pCap->halHTSupport ? HAL_OK : HAL_ENOTSUPP;
670 case HAL_CAP_TX_CHAINMASK: /* mask of TX chains supported */
671 *result = pCap->halTxChainMask;
672 return HAL_OK;
673 case HAL_CAP_RX_CHAINMASK: /* mask of RX chains supported */
674 *result = pCap->halRxChainMask;
675 return HAL_OK;
676 case HAL_CAP_RXTSTAMP_PREC: /* rx desc tstamp precision (bits) */
677 *result = pCap->halTstampPrecision;
678 return HAL_OK;
679 default:
680 return HAL_EINVAL;
684 HAL_BOOL
685 ath_hal_setcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
686 uint32_t capability, uint32_t setting, HAL_STATUS *status)
689 switch (type) {
690 case HAL_CAP_TXPOW:
691 switch (capability) {
692 case 3:
693 if (setting <= HAL_TP_SCALE_MIN) {
694 AH_PRIVATE(ah)->ah_tpScale = setting;
695 return AH_TRUE;
697 break;
699 break;
700 case HAL_CAP_RFSILENT: /* rfsilent support */
702 * NB: allow even if halRfSilentSupport is false
703 * in case the EEPROM is misprogrammed.
705 switch (capability) {
706 case 1: /* current setting */
707 AH_PRIVATE(ah)->ah_rfkillEnabled = (setting != 0);
708 return AH_TRUE;
709 case 2: /* rfsilent config */
710 /* XXX better done per-chip for validation? */
711 AH_PRIVATE(ah)->ah_rfsilent = setting;
712 return AH_TRUE;
714 break;
715 case HAL_CAP_REG_DMN: /* regulatory domain */
716 AH_PRIVATE(ah)->ah_currentRD = setting;
717 return AH_TRUE;
718 case HAL_CAP_RXORN_FATAL: /* HAL_INT_RXORN treated as fatal */
719 AH_PRIVATE(ah)->ah_rxornIsFatal = setting;
720 return AH_TRUE;
721 default:
722 break;
724 if (status)
725 *status = HAL_EINVAL;
726 return AH_FALSE;
730 * Common support for getDiagState method.
733 static u_int
734 ath_hal_getregdump(struct ath_hal *ah, const HAL_REGRANGE *regs,
735 void *dstbuf, int space)
737 uint32_t *dp = dstbuf;
738 int i;
740 for (i = 0; space >= 2*sizeof(uint32_t); i++) {
741 u_int r = regs[i].start;
742 u_int e = regs[i].end;
743 *dp++ = (r<<16) | e;
744 space -= sizeof(uint32_t);
745 do {
746 *dp++ = OS_REG_READ(ah, r);
747 r += sizeof(uint32_t);
748 space -= sizeof(uint32_t);
749 } while (r <= e && space >= sizeof(uint32_t));
751 return (char *) dp - (char *) dstbuf;
754 HAL_BOOL
755 ath_hal_getdiagstate(struct ath_hal *ah, int request,
756 const void *args, uint32_t argsize,
757 void **result, uint32_t *resultsize)
759 switch (request) {
760 case HAL_DIAG_REVS:
761 *result = &AH_PRIVATE(ah)->ah_devid;
762 *resultsize = sizeof(HAL_REVS);
763 return AH_TRUE;
764 case HAL_DIAG_REGS:
765 *resultsize = ath_hal_getregdump(ah, args, *result,*resultsize);
766 return AH_TRUE;
767 case HAL_DIAG_FATALERR:
768 *result = &AH_PRIVATE(ah)->ah_fatalState[0];
769 *resultsize = sizeof(AH_PRIVATE(ah)->ah_fatalState);
770 return AH_TRUE;
771 case HAL_DIAG_EEREAD:
772 if (argsize != sizeof(uint16_t))
773 return AH_FALSE;
774 if (!ath_hal_eepromRead(ah, *(const uint16_t *)args, *result))
775 return AH_FALSE;
776 *resultsize = sizeof(uint16_t);
777 return AH_TRUE;
778 #ifdef AH_PRIVATE_DIAG
779 case HAL_DIAG_SETKEY: {
780 const HAL_DIAG_KEYVAL *dk;
782 if (argsize != sizeof(HAL_DIAG_KEYVAL))
783 return AH_FALSE;
784 dk = (const HAL_DIAG_KEYVAL *)args;
785 return ah->ah_setKeyCacheEntry(ah, dk->dk_keyix,
786 &dk->dk_keyval, dk->dk_mac, dk->dk_xor);
788 case HAL_DIAG_RESETKEY:
789 if (argsize != sizeof(uint16_t))
790 return AH_FALSE;
791 return ah->ah_resetKeyCacheEntry(ah, *(const uint16_t *)args);
792 #endif /* AH_PRIVATE_DIAG */
793 case HAL_DIAG_11NCOMPAT:
794 if (argsize == 0) {
795 *resultsize = sizeof(uint32_t);
796 *((uint32_t *)(*result)) =
797 AH_PRIVATE(ah)->ah_11nCompat;
798 } else if (argsize == sizeof(uint32_t)) {
799 AH_PRIVATE(ah)->ah_11nCompat = *(const uint32_t *)args;
800 } else
801 return AH_FALSE;
802 return AH_TRUE;
804 return AH_FALSE;
808 * Set the properties of the tx queue with the parameters
809 * from qInfo.
811 HAL_BOOL
812 ath_hal_setTxQProps(struct ath_hal *ah,
813 HAL_TX_QUEUE_INFO *qi, const HAL_TXQ_INFO *qInfo)
815 uint32_t cw;
817 if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
818 HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
819 "%s: inactive queue\n", __func__);
820 return AH_FALSE;
822 /* XXX validate parameters */
823 qi->tqi_ver = qInfo->tqi_ver;
824 qi->tqi_subtype = qInfo->tqi_subtype;
825 qi->tqi_qflags = qInfo->tqi_qflags;
826 qi->tqi_priority = qInfo->tqi_priority;
827 if (qInfo->tqi_aifs != HAL_TXQ_USEDEFAULT)
828 qi->tqi_aifs = AH_MIN(qInfo->tqi_aifs, 255);
829 else
830 qi->tqi_aifs = INIT_AIFS;
831 if (qInfo->tqi_cwmin != HAL_TXQ_USEDEFAULT) {
832 cw = AH_MIN(qInfo->tqi_cwmin, 1024);
833 /* make sure that the CWmin is of the form (2^n - 1) */
834 qi->tqi_cwmin = 1;
835 while (qi->tqi_cwmin < cw)
836 qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1;
837 } else
838 qi->tqi_cwmin = qInfo->tqi_cwmin;
839 if (qInfo->tqi_cwmax != HAL_TXQ_USEDEFAULT) {
840 cw = AH_MIN(qInfo->tqi_cwmax, 1024);
841 /* make sure that the CWmax is of the form (2^n - 1) */
842 qi->tqi_cwmax = 1;
843 while (qi->tqi_cwmax < cw)
844 qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1;
845 } else
846 qi->tqi_cwmax = INIT_CWMAX;
847 /* Set retry limit values */
848 if (qInfo->tqi_shretry != 0)
849 qi->tqi_shretry = AH_MIN(qInfo->tqi_shretry, 15);
850 else
851 qi->tqi_shretry = INIT_SH_RETRY;
852 if (qInfo->tqi_lgretry != 0)
853 qi->tqi_lgretry = AH_MIN(qInfo->tqi_lgretry, 15);
854 else
855 qi->tqi_lgretry = INIT_LG_RETRY;
856 qi->tqi_cbrPeriod = qInfo->tqi_cbrPeriod;
857 qi->tqi_cbrOverflowLimit = qInfo->tqi_cbrOverflowLimit;
858 qi->tqi_burstTime = qInfo->tqi_burstTime;
859 qi->tqi_readyTime = qInfo->tqi_readyTime;
861 switch (qInfo->tqi_subtype) {
862 case HAL_WME_UPSD:
863 if (qi->tqi_type == HAL_TX_QUEUE_DATA)
864 qi->tqi_intFlags = HAL_TXQ_USE_LOCKOUT_BKOFF_DIS;
865 break;
866 default:
867 break; /* NB: silence compiler */
869 return AH_TRUE;
872 HAL_BOOL
873 ath_hal_getTxQProps(struct ath_hal *ah,
874 HAL_TXQ_INFO *qInfo, const HAL_TX_QUEUE_INFO *qi)
876 if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
877 HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
878 "%s: inactive queue\n", __func__);
879 return AH_FALSE;
882 qInfo->tqi_qflags = qi->tqi_qflags;
883 qInfo->tqi_ver = qi->tqi_ver;
884 qInfo->tqi_subtype = qi->tqi_subtype;
885 qInfo->tqi_qflags = qi->tqi_qflags;
886 qInfo->tqi_priority = qi->tqi_priority;
887 qInfo->tqi_aifs = qi->tqi_aifs;
888 qInfo->tqi_cwmin = qi->tqi_cwmin;
889 qInfo->tqi_cwmax = qi->tqi_cwmax;
890 qInfo->tqi_shretry = qi->tqi_shretry;
891 qInfo->tqi_lgretry = qi->tqi_lgretry;
892 qInfo->tqi_cbrPeriod = qi->tqi_cbrPeriod;
893 qInfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit;
894 qInfo->tqi_burstTime = qi->tqi_burstTime;
895 qInfo->tqi_readyTime = qi->tqi_readyTime;
896 return AH_TRUE;
899 /* 11a Turbo 11b 11g 108g */
900 static const int16_t NOISE_FLOOR[] = { -96, -93, -98, -96, -93 };
903 * Read the current channel noise floor and return.
904 * If nf cal hasn't finished, channel noise floor should be 0
905 * and we return a nominal value based on band and frequency.
907 * NB: This is a private routine used by per-chip code to
908 * implement the ah_getChanNoise method.
910 int16_t
911 ath_hal_getChanNoise(struct ath_hal *ah, HAL_CHANNEL *chan)
913 HAL_CHANNEL_INTERNAL *ichan;
915 ichan = ath_hal_checkchannel(ah, chan);
916 if (ichan == AH_NULL) {
917 HALDEBUG(ah, HAL_DEBUG_NFCAL,
918 "%s: invalid channel %u/0x%x; no mapping\n",
919 __func__, chan->channel, chan->channelFlags);
920 return 0;
922 if (ichan->rawNoiseFloor == 0) {
923 WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan);
925 HALASSERT(mode < WIRELESS_MODE_MAX);
926 return NOISE_FLOOR[mode] + ath_hal_getNfAdjust(ah, ichan);
927 } else
928 return ichan->rawNoiseFloor + ichan->noiseFloorAdjust;
932 * Process all valid raw noise floors into the dBm noise floor values.
933 * Though our device has no reference for a dBm noise floor, we perform
934 * a relative minimization of NF's based on the lowest NF found across a
935 * channel scan.
937 void
938 ath_hal_process_noisefloor(struct ath_hal *ah)
940 HAL_CHANNEL_INTERNAL *c;
941 int16_t correct2, correct5;
942 int16_t lowest2, lowest5;
943 int i;
946 * Find the lowest 2GHz and 5GHz noise floor values after adjusting
947 * for statistically recorded NF/channel deviation.
949 correct2 = lowest2 = 0;
950 correct5 = lowest5 = 0;
951 for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
952 WIRELESS_MODE mode;
953 int16_t nf;
955 c = &AH_PRIVATE(ah)->ah_channels[i];
956 if (c->rawNoiseFloor >= 0)
957 continue;
958 mode = ath_hal_chan2wmode(ah, (HAL_CHANNEL *) c);
959 HALASSERT(mode < WIRELESS_MODE_MAX);
960 nf = c->rawNoiseFloor + NOISE_FLOOR[mode] +
961 ath_hal_getNfAdjust(ah, c);
962 if (IS_CHAN_5GHZ(c)) {
963 if (nf < lowest5) {
964 lowest5 = nf;
965 correct5 = NOISE_FLOOR[mode] -
966 (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
968 } else {
969 if (nf < lowest2) {
970 lowest2 = nf;
971 correct2 = NOISE_FLOOR[mode] -
972 (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
977 /* Correct the channels to reach the expected NF value */
978 for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
979 c = &AH_PRIVATE(ah)->ah_channels[i];
980 if (c->rawNoiseFloor >= 0)
981 continue;
982 /* Apply correction factor */
983 c->noiseFloorAdjust = ath_hal_getNfAdjust(ah, c) +
984 (IS_CHAN_5GHZ(c) ? correct5 : correct2);
985 HALDEBUG(ah, HAL_DEBUG_NFCAL, "%u/0x%x raw nf %d adjust %d\n",
986 c->channel, c->channelFlags, c->rawNoiseFloor,
987 c->noiseFloorAdjust);
992 * INI support routines.
996 ath_hal_ini_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
997 int col, int regWr)
999 int r;
1001 for (r = 0; r < ia->rows; r++) {
1002 OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0),
1003 HAL_INI_VAL(ia, r, col));
1004 DMA_YIELD(regWr);
1006 return regWr;
1009 void
1010 ath_hal_ini_bank_setup(uint32_t data[], const HAL_INI_ARRAY *ia, int col)
1012 int r;
1014 for (r = 0; r < ia->rows; r++)
1015 data[r] = HAL_INI_VAL(ia, r, col);
1019 ath_hal_ini_bank_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
1020 const uint32_t data[], int regWr)
1022 int r;
1024 for (r = 0; r < ia->rows; r++) {
1025 OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0), data[r]);
1026 DMA_YIELD(regWr);
1028 return regWr;