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