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.
22 #include "ah_internal.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
*);
29 #ifdef AH_SUPPORT_AR5211
30 extern struct ath_hal
*ar5211Attach(uint16_t, HAL_SOFTC
,
31 HAL_BUS_TAG
, HAL_BUS_HANDLE
, HAL_STATUS
*);
33 #ifdef AH_SUPPORT_AR5212
34 extern struct ath_hal
*ar5212Attach(uint16_t, HAL_SOFTC
,
35 HAL_BUS_TAG
, HAL_BUS_HANDLE
, HAL_STATUS
*);
37 #ifdef AH_SUPPORT_AR5312
38 extern struct ath_hal
*ar5312Attach(uint16_t, HAL_SOFTC
,
39 HAL_BUS_TAG
, HAL_BUS_HANDLE
, HAL_STATUS
*);
41 #ifdef AH_SUPPORT_AR5416
42 extern struct ath_hal
*ar5416Attach(uint16_t, HAL_SOFTC
,
43 HAL_BUS_TAG
, HAL_BUS_HANDLE
, HAL_STATUS
*);
45 #ifdef AH_SUPPORT_AR9160
46 extern struct ath_hal
*ar9160Attach(uint16_t, HAL_SOFTC
,
47 HAL_BUS_TAG
, HAL_BUS_HANDLE
, HAL_STATUS
*);
51 char ath_hal_version
[] = ATH_HAL_VERSION
;
52 const char* ath_hal_buildopts
[] = {
53 #ifdef AH_SUPPORT_AR5210
56 #ifdef AH_SUPPORT_AR5211
59 #ifdef AH_SUPPORT_AR5212
62 #ifdef AH_SUPPORT_AR5312
65 #ifdef AH_SUPPORT_AR5416
68 #ifdef AH_SUPPORT_AR9180
71 #ifdef AH_SUPPORT_5111
74 #ifdef AH_SUPPORT_5112
77 #ifdef AH_SUPPORT_2413
80 #ifdef AH_SUPPORT_5413
83 #ifdef AH_SUPPORT_2316
86 #ifdef AH_SUPPORT_2317
89 #ifdef AH_SUPPORT_2133
92 #ifdef AH_SUPPORT_2425
95 #ifdef AH_SUPPORT_2417
107 #ifdef AH_REGOPS_FUNC
110 #ifdef AH_PRIVATE_DIAG
113 #ifdef AH_DEBUG_COUNTRY
116 #ifdef AH_NEED_DESC_SWAP
119 #ifdef AH_DISABLE_WME
122 #ifdef AH_SUPPORT_11D
129 ath_hal_devname(uint16_t devid
)
134 return "Atheros 5210";
139 return "Atheros 5211";
141 return "Atheros 5211 (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";
156 case AR5212_DEVID_IBM
:
158 return "Atheros 5212";
160 return "Atheros 2413";
162 return "Atheros 2417";
164 return "Atheros 5413";
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";
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
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
;
199 #ifdef AH_SUPPORT_AR5210
203 ah
= ar5210Attach(devid
, sc
, st
, sh
, error
);
206 #ifdef AH_SUPPORT_AR5211
211 ah
= ar5211Attach(devid
, sc
, st
, sh
, error
);
214 #ifdef AH_SUPPORT_AR5212
215 case AR5212_DEVID_IBM
:
220 case AR5212_DEVID_FF19
: /* XXX PCI Express extra */
221 devid
= AR5212_DEVID
;
226 ah
= ar5212Attach(devid
, sc
, st
, sh
, error
);
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
);
239 #ifdef AH_SUPPORT_AR5416
240 case AR5416_DEVID_PCI
:
241 case AR5416_DEVID_PCIE
:
242 ah
= ar5416Attach(devid
, sc
, st
, sh
, error
);
245 #ifdef AH_SUPPORT_AR9160
246 case AR9160_DEVID_PCI
:
247 ah
= ar9160Attach(devid
, sc
, st
, sh
, error
);
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
;
269 * Poll the register looking for a specific value.
272 ath_hal_wait(struct ath_hal
*ah
, u_int reg
, uint32_t mask
, uint32_t val
)
274 #define AH_TIMEOUT 1000
277 for (i
= 0; i
< AH_TIMEOUT
; i
++) {
278 if ((OS_REG_READ(ah
, reg
) & mask
) == val
)
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
);
290 * Reverse the bits starting at the low bit for a value of
294 ath_hal_reverseBits(uint32_t val
, uint32_t n
)
299 for (i
= 0, retval
= 0; i
< n
; i
++) {
300 retval
= (retval
<< 1) | (val
& 1);
307 * Compute the time to transmit a frame of length frameLen bytes
308 * using the specified rate, phy, and short preamble setting.
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
;
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
)
332 numBits
= frameLen
<< 3;
333 txTime
= CCK_SIFS_TIME
+ phyTime
334 + ((numBits
* 1000)/kbps
);
337 #undef CCK_PREAMBLE_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
);
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
);
406 #undef TURBO_SIFS_TIME
407 #undef TURBO_PREAMBLE_TIME
408 #undef TURBO_PLCP_BITS
409 #undef TURBO_SYMBOL_TIME
412 HALDEBUG(ah
, HAL_DEBUG_PHYIO
,
413 "%s: unknown phy %u (rate ix %u)\n",
414 __func__
, rates
->info
[rateix
].phy
, rateix
);
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 */
437 return ((int)freq
- 2407) / 5;
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;
447 return (freq
- 5000) / 5;
449 } else { /* either, guess */
453 return ((int)freq
- 2407) / 5;
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;
462 return 15 + ((freq
- 2512) / 20);
465 return (freq
- 5000) / 5;
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,
480 ath_hal_chan2wmode(struct ath_hal
*ah
, const HAL_CHANNEL
*chan
)
482 if (IS_CHAN_CCK(chan
))
483 return WIRELESS_MODE_11b
;
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 };
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
;
505 /* NB: ah_curchan may be null when called attach time */
507 clks
= usecs
* CLOCK_RATE
[ath_hal_chan2wmode(ah
, c
)];
510 else if (IS_CHAN_HALF_RATE(c
))
512 else if (IS_CHAN_QUARTER_RATE(c
))
515 clks
= usecs
* CLOCK_RATE
[WIRELESS_MODE_11b
];
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
;
525 /* NB: ah_curchan may be null when called attach time */
527 usec
= clks
/ CLOCK_RATE
[ath_hal_chan2wmode(ah
, c
)];
530 else if (IS_CHAN_HALF_RATE(c
))
532 else if (IS_CHAN_QUARTER_RATE(c
))
535 usec
= clks
/ CLOCK_RATE
[WIRELESS_MODE_11b
];
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
551 ath_hal_setupratetable(struct ath_hal
*ah
, HAL_RATE_TABLE
*rt
)
553 #define N(a) (sizeof(a)/sizeof(a[0]))
556 if (rt
->rateCodeToIndex
[0] != 0) /* already setup */
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
);
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
;
590 case HAL_CAP_REG_DMN
: /* regulatory domain */
591 *result
= AH_PRIVATE(ah
)->ah_currentRD
;
593 case HAL_CAP_CIPHER
: /* cipher handled in hardware */
594 case HAL_CAP_TKIP_MIC
: /* handle TKIP MIC in hardware */
596 case HAL_CAP_TKIP_SPLIT
: /* hardware TKIP uses split keys */
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 */
602 case HAL_CAP_DIVERSITY
: /* hardware supports fast diversity */
604 case HAL_CAP_KEYCACHE_SIZE
: /* hardware key cache size */
605 *result
= pCap
->halKeyCacheSize
;
607 case HAL_CAP_NUM_TXQUEUES
: /* number of hardware tx queues */
608 *result
= pCap
->halTotalQueues
;
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
;
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
;
623 case HAL_CAP_TXPOW
: /* global tx power limit */
624 switch (capability
) {
625 case 0: /* facility is supported */
627 case 1: /* current limit */
628 *result
= AH_PRIVATE(ah
)->ah_powerLimit
;
630 case 2: /* current max tx power */
631 *result
= AH_PRIVATE(ah
)->ah_maxPowerLevel
;
633 case 3: /* scale factor */
634 *result
= AH_PRIVATE(ah
)->ah_tpScale
;
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 */
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
;
661 #ifdef AH_SUPPORT_11D
666 case HAL_CAP_RXORN_FATAL
: /* HAL_INT_RXORN treated as fatal */
667 return AH_PRIVATE(ah
)->ah_rxornIsFatal
? HAL_OK
: HAL_ENOTSUPP
;
669 return pCap
->halHTSupport
? HAL_OK
: HAL_ENOTSUPP
;
670 case HAL_CAP_TX_CHAINMASK
: /* mask of TX chains supported */
671 *result
= pCap
->halTxChainMask
;
673 case HAL_CAP_RX_CHAINMASK
: /* mask of RX chains supported */
674 *result
= pCap
->halRxChainMask
;
676 case HAL_CAP_RXTSTAMP_PREC
: /* rx desc tstamp precision (bits) */
677 *result
= pCap
->halTstampPrecision
;
685 ath_hal_setcapability(struct ath_hal
*ah
, HAL_CAPABILITY_TYPE type
,
686 uint32_t capability
, uint32_t setting
, HAL_STATUS
*status
)
691 switch (capability
) {
693 if (setting
<= HAL_TP_SCALE_MIN
) {
694 AH_PRIVATE(ah
)->ah_tpScale
= setting
;
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);
709 case 2: /* rfsilent config */
710 /* XXX better done per-chip for validation? */
711 AH_PRIVATE(ah
)->ah_rfsilent
= setting
;
715 case HAL_CAP_REG_DMN
: /* regulatory domain */
716 AH_PRIVATE(ah
)->ah_currentRD
= setting
;
718 case HAL_CAP_RXORN_FATAL
: /* HAL_INT_RXORN treated as fatal */
719 AH_PRIVATE(ah
)->ah_rxornIsFatal
= setting
;
725 *status
= HAL_EINVAL
;
730 * Common support for getDiagState method.
734 ath_hal_getregdump(struct ath_hal
*ah
, const HAL_REGRANGE
*regs
,
735 void *dstbuf
, int space
)
737 uint32_t *dp
= dstbuf
;
740 for (i
= 0; space
>= 2*sizeof(uint32_t); i
++) {
741 u_int r
= regs
[i
].start
;
742 u_int e
= regs
[i
].end
;
744 space
-= sizeof(uint32_t);
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
;
755 ath_hal_getdiagstate(struct ath_hal
*ah
, int request
,
756 const void *args
, uint32_t argsize
,
757 void **result
, uint32_t *resultsize
)
761 *result
= &AH_PRIVATE(ah
)->ah_devid
;
762 *resultsize
= sizeof(HAL_REVS
);
765 *resultsize
= ath_hal_getregdump(ah
, args
, *result
,*resultsize
);
767 case HAL_DIAG_FATALERR
:
768 *result
= &AH_PRIVATE(ah
)->ah_fatalState
[0];
769 *resultsize
= sizeof(AH_PRIVATE(ah
)->ah_fatalState
);
771 case HAL_DIAG_EEREAD
:
772 if (argsize
!= sizeof(uint16_t))
774 if (!ath_hal_eepromRead(ah
, *(const uint16_t *)args
, *result
))
776 *resultsize
= sizeof(uint16_t);
778 #ifdef AH_PRIVATE_DIAG
779 case HAL_DIAG_SETKEY
: {
780 const HAL_DIAG_KEYVAL
*dk
;
782 if (argsize
!= sizeof(HAL_DIAG_KEYVAL
))
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))
791 return ah
->ah_resetKeyCacheEntry(ah
, *(const uint16_t *)args
);
792 #endif /* AH_PRIVATE_DIAG */
793 case HAL_DIAG_11NCOMPAT
:
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
;
808 * Set the properties of the tx queue with the parameters
812 ath_hal_setTxQProps(struct ath_hal
*ah
,
813 HAL_TX_QUEUE_INFO
*qi
, const HAL_TXQ_INFO
*qInfo
)
817 if (qi
->tqi_type
== HAL_TX_QUEUE_INACTIVE
) {
818 HALDEBUG(ah
, HAL_DEBUG_TXQUEUE
,
819 "%s: inactive queue\n", __func__
);
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);
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) */
835 while (qi
->tqi_cwmin
< cw
)
836 qi
->tqi_cwmin
= (qi
->tqi_cwmin
<< 1) | 1;
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) */
843 while (qi
->tqi_cwmax
< cw
)
844 qi
->tqi_cwmax
= (qi
->tqi_cwmax
<< 1) | 1;
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);
851 qi
->tqi_shretry
= INIT_SH_RETRY
;
852 if (qInfo
->tqi_lgretry
!= 0)
853 qi
->tqi_lgretry
= AH_MIN(qInfo
->tqi_lgretry
, 15);
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
) {
863 if (qi
->tqi_type
== HAL_TX_QUEUE_DATA
)
864 qi
->tqi_intFlags
= HAL_TXQ_USE_LOCKOUT_BKOFF_DIS
;
867 break; /* NB: silence compiler */
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__
);
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
;
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.
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
);
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
);
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
938 ath_hal_process_noisefloor(struct ath_hal
*ah
)
940 HAL_CHANNEL_INTERNAL
*c
;
941 int16_t correct2
, correct5
;
942 int16_t lowest2
, lowest5
;
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
++) {
955 c
= &AH_PRIVATE(ah
)->ah_channels
[i
];
956 if (c
->rawNoiseFloor
>= 0)
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
)) {
965 correct5
= NOISE_FLOOR
[mode
] -
966 (c
->rawNoiseFloor
+ ath_hal_getNfAdjust(ah
, c
));
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)
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
,
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
));
1010 ath_hal_ini_bank_setup(uint32_t data
[], const HAL_INI_ARRAY
*ia
, int col
)
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
)
1024 for (r
= 0; r
< ia
->rows
; r
++) {
1025 OS_REG_WRITE(ah
, HAL_INI_VAL(ia
, r
, 0), data
[r
]);