Deleted Added
full compact
ah.c (220298) ah.c (220324)
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 *
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 220298 2011-04-03 17:36:32Z adrian $
17 * $FreeBSD: head/sys/dev/ath/ath_hal/ah.c 220324 2011-04-04 14:52:31Z adrian $
18 */
19#include "opt_ah.h"
20
21#include "ah.h"
22#include "ah_internal.h"
23#include "ah_devid.h"
24#include "ah_eeprom.h" /* for 5ghz fast clock flag */
25
26#include "ar5416/ar5416reg.h" /* NB: includes ar5212reg.h */
27
28/* linker set of registered chips */
29OS_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 */
35const char*
36ath_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 */
55struct ath_hal*
56ath_hal_attach(uint16_t devid, HAL_SOFTC sc,
57 HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, 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, eepromdata, 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
84const char *
85ath_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 */
125u_int
126ath_hal_getwirelessmodes(struct ath_hal*ah)
127{
128 return ath_hal_getWirelessModes(ah);
129}
130
131/* linker set of registered RF backends */
132OS_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 */
138struct ath_hal_rf *
139ath_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
152const char *
153ath_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 */
197HAL_BOOL
198ath_hal_wait(struct ath_hal *ah, u_int reg, uint32_t mask, uint32_t val)
199{
200#define AH_TIMEOUT 1000
201 return ath_hal_waitfor(ah, reg, mask, val, AH_TIMEOUT);
202#undef AH_TIMEOUT
203}
204
205HAL_BOOL
206ath_hal_waitfor(struct ath_hal *ah, u_int reg, uint32_t mask, uint32_t val, uint32_t timeout)
207{
208 int i;
209
210 for (i = 0; i < timeout; i++) {
211 if ((OS_REG_READ(ah, reg) & mask) == val)
212 return AH_TRUE;
213 OS_DELAY(10);
214 }
215 HALDEBUG(ah, HAL_DEBUG_REGIO | HAL_DEBUG_PHYIO,
216 "%s: timeout on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n",
217 __func__, reg, OS_REG_READ(ah, reg), mask, val);
218 return AH_FALSE;
219}
220
221/*
222 * Reverse the bits starting at the low bit for a value of
223 * bit_count in size
224 */
225uint32_t
226ath_hal_reverseBits(uint32_t val, uint32_t n)
227{
228 uint32_t retval;
229 int i;
230
231 for (i = 0, retval = 0; i < n; i++) {
232 retval = (retval << 1) | (val & 1);
233 val >>= 1;
234 }
235 return retval;
236}
237
238/* 802.11n related timing definitions */
239
240#define OFDM_PLCP_BITS 22
241#define HT_L_STF 8
242#define HT_L_LTF 8
243#define HT_L_SIG 4
244#define HT_SIG 8
245#define HT_STF 4
246#define HT_LTF(n) ((n) * 4)
247
248#define HT_RC_2_MCS(_rc) ((_rc) & 0xf)
249#define HT_RC_2_STREAMS(_rc) ((((_rc) & 0x78) >> 3) + 1)
250#define IS_HT_RATE(_rc) ( (_rc) & IEEE80211_RATE_MCS)
251
252/*
253 * Calculate the duration of a packet whether it is 11n or legacy.
254 */
255uint32_t
256ath_hal_pkt_txtime(struct ath_hal *ah, const HAL_RATE_TABLE *rates, uint32_t frameLen,
257 uint16_t rateix, HAL_BOOL isht40, HAL_BOOL shortPreamble)
258{
259 uint8_t rc;
260 int numStreams;
261
262 rc = rates->info[rateix].rateCode;
263
264 /* Legacy rate? Return the old way */
265 if (! IS_HT_RATE(rc))
266 return ath_hal_computetxtime(ah, rates, frameLen, rateix, shortPreamble);
267
268 /* 11n frame - extract out the number of spatial streams */
269 numStreams = HT_RC_2_STREAMS(rc);
270 KASSERT(numStreams == 1 || numStreams == 2, ("number of spatial streams needs to be 1 or 2: MCS rate 0x%x!", rateix));
271
272 return ath_computedur_ht(frameLen, rc, numStreams, isht40, shortPreamble);
273}
274
275/*
276 * Calculate the transmit duration of an 11n frame.
277 * This only works for MCS0->MCS15.
278 */
279uint32_t
280ath_computedur_ht(uint32_t frameLen, uint16_t rate, int streams, HAL_BOOL isht40,
281 HAL_BOOL isShortGI)
282{
283 static const uint16_t ht20_bps[16] = {
284 26, 52, 78, 104, 156, 208, 234, 260,
285 52, 104, 156, 208, 312, 416, 468, 520
286 };
287 static const uint16_t ht40_bps[16] = {
288 54, 108, 162, 216, 324, 432, 486, 540,
289 108, 216, 324, 432, 648, 864, 972, 1080,
290 };
291 uint32_t bitsPerSymbol, numBits, numSymbols, txTime;
292
293 KASSERT(rate & IEEE80211_RATE_MCS, ("not mcs %d", rate));
294 KASSERT((rate &~ IEEE80211_RATE_MCS) < 16, ("bad mcs 0x%x", rate));
295
296 if (isht40)
297 bitsPerSymbol = ht40_bps[rate & 0xf];
298 else
299 bitsPerSymbol = ht20_bps[rate & 0xf];
300 numBits = OFDM_PLCP_BITS + (frameLen << 3);
301 numSymbols = howmany(numBits, bitsPerSymbol);
302 if (isShortGI)
303 txTime = ((numSymbols * 18) + 4) / 5; /* 3.6us */
304 else
305 txTime = numSymbols * 4; /* 4us */
306 return txTime + HT_L_STF + HT_L_LTF +
307 HT_L_SIG + HT_SIG + HT_STF + HT_LTF(streams);
308}
309
310/*
311 * Compute the time to transmit a frame of length frameLen bytes
312 * using the specified rate, phy, and short preamble setting.
313 */
314uint16_t
315ath_hal_computetxtime(struct ath_hal *ah,
316 const HAL_RATE_TABLE *rates, uint32_t frameLen, uint16_t rateix,
317 HAL_BOOL shortPreamble)
318{
319 uint32_t bitsPerSymbol, numBits, numSymbols, phyTime, txTime;
320 uint32_t kbps;
321
322 /* Warn if this function is called for 11n rates; it should not be! */
323 if (IS_HT_RATE(rates->info[rateix].rateCode))
324 ath_hal_printf(ah, "%s: MCS rate? (index %d; hwrate 0x%x)\n",
325 __func__, rateix, rates->info[rateix].rateCode);
326
327 kbps = rates->info[rateix].rateKbps;
328 /*
329 * index can be invalid duting dynamic Turbo transitions.
330 * XXX
331 */
332 if (kbps == 0)
333 return 0;
334 switch (rates->info[rateix].phy) {
335 case IEEE80211_T_CCK:
336 phyTime = CCK_PREAMBLE_BITS + CCK_PLCP_BITS;
337 if (shortPreamble && rates->info[rateix].shortPreamble)
338 phyTime >>= 1;
339 numBits = frameLen << 3;
340 txTime = CCK_SIFS_TIME + phyTime
341 + ((numBits * 1000)/kbps);
342 break;
343 case IEEE80211_T_OFDM:
344 bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME) / 1000;
345 HALASSERT(bitsPerSymbol != 0);
346
347 numBits = OFDM_PLCP_BITS + (frameLen << 3);
348 numSymbols = howmany(numBits, bitsPerSymbol);
349 txTime = OFDM_SIFS_TIME
350 + OFDM_PREAMBLE_TIME
351 + (numSymbols * OFDM_SYMBOL_TIME);
352 break;
353 case IEEE80211_T_OFDM_HALF:
354 bitsPerSymbol = (kbps * OFDM_HALF_SYMBOL_TIME) / 1000;
355 HALASSERT(bitsPerSymbol != 0);
356
357 numBits = OFDM_HALF_PLCP_BITS + (frameLen << 3);
358 numSymbols = howmany(numBits, bitsPerSymbol);
359 txTime = OFDM_HALF_SIFS_TIME
360 + OFDM_HALF_PREAMBLE_TIME
361 + (numSymbols * OFDM_HALF_SYMBOL_TIME);
362 break;
363 case IEEE80211_T_OFDM_QUARTER:
364 bitsPerSymbol = (kbps * OFDM_QUARTER_SYMBOL_TIME) / 1000;
365 HALASSERT(bitsPerSymbol != 0);
366
367 numBits = OFDM_QUARTER_PLCP_BITS + (frameLen << 3);
368 numSymbols = howmany(numBits, bitsPerSymbol);
369 txTime = OFDM_QUARTER_SIFS_TIME
370 + OFDM_QUARTER_PREAMBLE_TIME
371 + (numSymbols * OFDM_QUARTER_SYMBOL_TIME);
372 break;
373 case IEEE80211_T_TURBO:
374 bitsPerSymbol = (kbps * TURBO_SYMBOL_TIME) / 1000;
375 HALASSERT(bitsPerSymbol != 0);
376
377 numBits = TURBO_PLCP_BITS + (frameLen << 3);
378 numSymbols = howmany(numBits, bitsPerSymbol);
379 txTime = TURBO_SIFS_TIME
380 + TURBO_PREAMBLE_TIME
381 + (numSymbols * TURBO_SYMBOL_TIME);
382 break;
383 default:
384 HALDEBUG(ah, HAL_DEBUG_PHYIO,
385 "%s: unknown phy %u (rate ix %u)\n",
386 __func__, rates->info[rateix].phy, rateix);
387 txTime = 0;
388 break;
389 }
390 return txTime;
391}
392
393typedef enum {
394 WIRELESS_MODE_11a = 0,
395 WIRELESS_MODE_TURBO = 1,
396 WIRELESS_MODE_11b = 2,
397 WIRELESS_MODE_11g = 3,
398 WIRELESS_MODE_108g = 4,
399
400 WIRELESS_MODE_MAX
401} WIRELESS_MODE;
402
403static WIRELESS_MODE
404ath_hal_chan2wmode(struct ath_hal *ah, const struct ieee80211_channel *chan)
405{
406 if (IEEE80211_IS_CHAN_B(chan))
407 return WIRELESS_MODE_11b;
408 if (IEEE80211_IS_CHAN_G(chan))
409 return WIRELESS_MODE_11g;
410 if (IEEE80211_IS_CHAN_108G(chan))
411 return WIRELESS_MODE_108g;
412 if (IEEE80211_IS_CHAN_TURBO(chan))
413 return WIRELESS_MODE_TURBO;
414 return WIRELESS_MODE_11a;
415}
416
417/*
418 * Convert between microseconds and core system clocks.
419 */
420 /* 11a Turbo 11b 11g 108g */
421static const uint8_t CLOCK_RATE[] = { 40, 80, 22, 44, 88 };
422
423#define CLOCK_FAST_RATE_5GHZ_OFDM 44
424
425u_int
426ath_hal_mac_clks(struct ath_hal *ah, u_int usecs)
427{
428 const struct ieee80211_channel *c = AH_PRIVATE(ah)->ah_curchan;
429 u_int clks;
430
431 /* NB: ah_curchan may be null when called attach time */
432 /* XXX merlin and later specific workaround - 5ghz fast clock is 44 */
433 if (c != AH_NULL && IS_5GHZ_FAST_CLOCK_EN(ah, c)) {
434 clks = usecs * CLOCK_FAST_RATE_5GHZ_OFDM;
435 if (IEEE80211_IS_CHAN_HT40(c))
436 clks <<= 1;
437 } else if (c != AH_NULL) {
438 clks = usecs * CLOCK_RATE[ath_hal_chan2wmode(ah, c)];
439 if (IEEE80211_IS_CHAN_HT40(c))
440 clks <<= 1;
441 } else
442 clks = usecs * CLOCK_RATE[WIRELESS_MODE_11b];
443 return clks;
444}
445
446u_int
447ath_hal_mac_usec(struct ath_hal *ah, u_int clks)
448{
449 const struct ieee80211_channel *c = AH_PRIVATE(ah)->ah_curchan;
450 u_int usec;
451
452 /* NB: ah_curchan may be null when called attach time */
453 /* XXX merlin and later specific workaround - 5ghz fast clock is 44 */
454 if (c != AH_NULL && IS_5GHZ_FAST_CLOCK_EN(ah, c)) {
455 usec = clks / CLOCK_FAST_RATE_5GHZ_OFDM;
456 if (IEEE80211_IS_CHAN_HT40(c))
457 usec >>= 1;
458 } else if (c != AH_NULL) {
459 usec = clks / CLOCK_RATE[ath_hal_chan2wmode(ah, c)];
460 if (IEEE80211_IS_CHAN_HT40(c))
461 usec >>= 1;
462 } else
463 usec = clks / CLOCK_RATE[WIRELESS_MODE_11b];
464 return usec;
465}
466
467/*
468 * Setup a h/w rate table's reverse lookup table and
469 * fill in ack durations. This routine is called for
470 * each rate table returned through the ah_getRateTable
471 * method. The reverse lookup tables are assumed to be
472 * initialized to zero (or at least the first entry).
473 * We use this as a key that indicates whether or not
474 * we've previously setup the reverse lookup table.
475 *
476 * XXX not reentrant, but shouldn't matter
477 */
478void
479ath_hal_setupratetable(struct ath_hal *ah, HAL_RATE_TABLE *rt)
480{
481#define N(a) (sizeof(a)/sizeof(a[0]))
482 int i;
483
484 if (rt->rateCodeToIndex[0] != 0) /* already setup */
485 return;
486 for (i = 0; i < N(rt->rateCodeToIndex); i++)
487 rt->rateCodeToIndex[i] = (uint8_t) -1;
488 for (i = 0; i < rt->rateCount; i++) {
489 uint8_t code = rt->info[i].rateCode;
490 uint8_t cix = rt->info[i].controlRate;
491
492 HALASSERT(code < N(rt->rateCodeToIndex));
493 rt->rateCodeToIndex[code] = i;
494 HALASSERT((code | rt->info[i].shortPreamble) <
495 N(rt->rateCodeToIndex));
496 rt->rateCodeToIndex[code | rt->info[i].shortPreamble] = i;
497 /*
498 * XXX for 11g the control rate to use for 5.5 and 11 Mb/s
499 * depends on whether they are marked as basic rates;
500 * the static tables are setup with an 11b-compatible
501 * 2Mb/s rate which will work but is suboptimal
502 */
503 rt->info[i].lpAckDuration = ath_hal_computetxtime(ah, rt,
504 WLAN_CTRL_FRAME_SIZE, cix, AH_FALSE);
505 rt->info[i].spAckDuration = ath_hal_computetxtime(ah, rt,
506 WLAN_CTRL_FRAME_SIZE, cix, AH_TRUE);
507 }
508#undef N
509}
510
511HAL_STATUS
512ath_hal_getcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
513 uint32_t capability, uint32_t *result)
514{
515 const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
516
517 switch (type) {
518 case HAL_CAP_REG_DMN: /* regulatory domain */
519 *result = AH_PRIVATE(ah)->ah_currentRD;
520 return HAL_OK;
521 case HAL_CAP_CIPHER: /* cipher handled in hardware */
522 case HAL_CAP_TKIP_MIC: /* handle TKIP MIC in hardware */
523 return HAL_ENOTSUPP;
524 case HAL_CAP_TKIP_SPLIT: /* hardware TKIP uses split keys */
525 return HAL_ENOTSUPP;
526 case HAL_CAP_PHYCOUNTERS: /* hardware PHY error counters */
527 return pCap->halHwPhyCounterSupport ? HAL_OK : HAL_ENXIO;
528 case HAL_CAP_WME_TKIPMIC: /* hardware can do TKIP MIC when WMM is turned on */
529 return HAL_ENOTSUPP;
530 case HAL_CAP_DIVERSITY: /* hardware supports fast diversity */
531 return HAL_ENOTSUPP;
532 case HAL_CAP_KEYCACHE_SIZE: /* hardware key cache size */
533 *result = pCap->halKeyCacheSize;
534 return HAL_OK;
535 case HAL_CAP_NUM_TXQUEUES: /* number of hardware tx queues */
536 *result = pCap->halTotalQueues;
537 return HAL_OK;
538 case HAL_CAP_VEOL: /* hardware supports virtual EOL */
539 return pCap->halVEOLSupport ? HAL_OK : HAL_ENOTSUPP;
540 case HAL_CAP_PSPOLL: /* hardware PS-Poll support works */
541 return pCap->halPSPollBroken ? HAL_ENOTSUPP : HAL_OK;
542 case HAL_CAP_COMPRESSION:
543 return pCap->halCompressSupport ? HAL_OK : HAL_ENOTSUPP;
544 case HAL_CAP_BURST:
545 return pCap->halBurstSupport ? HAL_OK : HAL_ENOTSUPP;
546 case HAL_CAP_FASTFRAME:
547 return pCap->halFastFramesSupport ? HAL_OK : HAL_ENOTSUPP;
548 case HAL_CAP_DIAG: /* hardware diagnostic support */
549 *result = AH_PRIVATE(ah)->ah_diagreg;
550 return HAL_OK;
551 case HAL_CAP_TXPOW: /* global tx power limit */
552 switch (capability) {
553 case 0: /* facility is supported */
554 return HAL_OK;
555 case 1: /* current limit */
556 *result = AH_PRIVATE(ah)->ah_powerLimit;
557 return HAL_OK;
558 case 2: /* current max tx power */
559 *result = AH_PRIVATE(ah)->ah_maxPowerLevel;
560 return HAL_OK;
561 case 3: /* scale factor */
562 *result = AH_PRIVATE(ah)->ah_tpScale;
563 return HAL_OK;
564 }
565 return HAL_ENOTSUPP;
566 case HAL_CAP_BSSIDMASK: /* hardware supports bssid mask */
567 return pCap->halBssIdMaskSupport ? HAL_OK : HAL_ENOTSUPP;
568 case HAL_CAP_MCAST_KEYSRCH: /* multicast frame keycache search */
569 return pCap->halMcastKeySrchSupport ? HAL_OK : HAL_ENOTSUPP;
570 case HAL_CAP_TSF_ADJUST: /* hardware has beacon tsf adjust */
571 return HAL_ENOTSUPP;
572 case HAL_CAP_RFSILENT: /* rfsilent support */
573 switch (capability) {
574 case 0: /* facility is supported */
575 return pCap->halRfSilentSupport ? HAL_OK : HAL_ENOTSUPP;
576 case 1: /* current setting */
577 return AH_PRIVATE(ah)->ah_rfkillEnabled ?
578 HAL_OK : HAL_ENOTSUPP;
579 case 2: /* rfsilent config */
580 *result = AH_PRIVATE(ah)->ah_rfsilent;
581 return HAL_OK;
582 }
583 return HAL_ENOTSUPP;
584 case HAL_CAP_11D:
585 return HAL_OK;
586 case HAL_CAP_RXORN_FATAL: /* HAL_INT_RXORN treated as fatal */
587 return AH_PRIVATE(ah)->ah_rxornIsFatal ? HAL_OK : HAL_ENOTSUPP;
588 case HAL_CAP_HT:
589 return pCap->halHTSupport ? HAL_OK : HAL_ENOTSUPP;
590 case HAL_CAP_TX_CHAINMASK: /* mask of TX chains supported */
591 *result = pCap->halTxChainMask;
592 return HAL_OK;
593 case HAL_CAP_RX_CHAINMASK: /* mask of RX chains supported */
594 *result = pCap->halRxChainMask;
595 return HAL_OK;
596 case HAL_CAP_RXTSTAMP_PREC: /* rx desc tstamp precision (bits) */
597 *result = pCap->halTstampPrecision;
598 return HAL_OK;
599 case HAL_CAP_INTRMASK: /* mask of supported interrupts */
600 *result = pCap->halIntrMask;
601 return HAL_OK;
602 case HAL_CAP_BSSIDMATCH: /* hardware has disable bssid match */
603 return pCap->halBssidMatchSupport ? HAL_OK : HAL_ENOTSUPP;
604 case HAL_CAP_STREAMS: /* number of 11n spatial streams */
605 switch (capability) {
606 case 0: /* TX */
607 *result = pCap->halTxStreams;
608 return HAL_OK;
609 case 1: /* RX */
610 *result = pCap->halRxStreams;
611 return HAL_OK;
612 default:
613 return HAL_ENOTSUPP;
614 }
615 case HAL_CAP_SPLIT_4KB_TRANS: /* hardware handles descriptors straddling 4k page boundary */
616 return pCap->hal4kbSplitTransSupport ? HAL_OK : HAL_ENOTSUPP;
617 case HAL_CAP_HAS_PSPOLL: /* hardware has ps-poll support */
618 return pCap->halHasPsPollSupport ? HAL_OK : HAL_ENOTSUPP;
18 */
19#include "opt_ah.h"
20
21#include "ah.h"
22#include "ah_internal.h"
23#include "ah_devid.h"
24#include "ah_eeprom.h" /* for 5ghz fast clock flag */
25
26#include "ar5416/ar5416reg.h" /* NB: includes ar5212reg.h */
27
28/* linker set of registered chips */
29OS_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 */
35const char*
36ath_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 */
55struct ath_hal*
56ath_hal_attach(uint16_t devid, HAL_SOFTC sc,
57 HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, 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, eepromdata, 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
84const char *
85ath_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 */
125u_int
126ath_hal_getwirelessmodes(struct ath_hal*ah)
127{
128 return ath_hal_getWirelessModes(ah);
129}
130
131/* linker set of registered RF backends */
132OS_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 */
138struct ath_hal_rf *
139ath_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
152const char *
153ath_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 */
197HAL_BOOL
198ath_hal_wait(struct ath_hal *ah, u_int reg, uint32_t mask, uint32_t val)
199{
200#define AH_TIMEOUT 1000
201 return ath_hal_waitfor(ah, reg, mask, val, AH_TIMEOUT);
202#undef AH_TIMEOUT
203}
204
205HAL_BOOL
206ath_hal_waitfor(struct ath_hal *ah, u_int reg, uint32_t mask, uint32_t val, uint32_t timeout)
207{
208 int i;
209
210 for (i = 0; i < timeout; i++) {
211 if ((OS_REG_READ(ah, reg) & mask) == val)
212 return AH_TRUE;
213 OS_DELAY(10);
214 }
215 HALDEBUG(ah, HAL_DEBUG_REGIO | HAL_DEBUG_PHYIO,
216 "%s: timeout on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n",
217 __func__, reg, OS_REG_READ(ah, reg), mask, val);
218 return AH_FALSE;
219}
220
221/*
222 * Reverse the bits starting at the low bit for a value of
223 * bit_count in size
224 */
225uint32_t
226ath_hal_reverseBits(uint32_t val, uint32_t n)
227{
228 uint32_t retval;
229 int i;
230
231 for (i = 0, retval = 0; i < n; i++) {
232 retval = (retval << 1) | (val & 1);
233 val >>= 1;
234 }
235 return retval;
236}
237
238/* 802.11n related timing definitions */
239
240#define OFDM_PLCP_BITS 22
241#define HT_L_STF 8
242#define HT_L_LTF 8
243#define HT_L_SIG 4
244#define HT_SIG 8
245#define HT_STF 4
246#define HT_LTF(n) ((n) * 4)
247
248#define HT_RC_2_MCS(_rc) ((_rc) & 0xf)
249#define HT_RC_2_STREAMS(_rc) ((((_rc) & 0x78) >> 3) + 1)
250#define IS_HT_RATE(_rc) ( (_rc) & IEEE80211_RATE_MCS)
251
252/*
253 * Calculate the duration of a packet whether it is 11n or legacy.
254 */
255uint32_t
256ath_hal_pkt_txtime(struct ath_hal *ah, const HAL_RATE_TABLE *rates, uint32_t frameLen,
257 uint16_t rateix, HAL_BOOL isht40, HAL_BOOL shortPreamble)
258{
259 uint8_t rc;
260 int numStreams;
261
262 rc = rates->info[rateix].rateCode;
263
264 /* Legacy rate? Return the old way */
265 if (! IS_HT_RATE(rc))
266 return ath_hal_computetxtime(ah, rates, frameLen, rateix, shortPreamble);
267
268 /* 11n frame - extract out the number of spatial streams */
269 numStreams = HT_RC_2_STREAMS(rc);
270 KASSERT(numStreams == 1 || numStreams == 2, ("number of spatial streams needs to be 1 or 2: MCS rate 0x%x!", rateix));
271
272 return ath_computedur_ht(frameLen, rc, numStreams, isht40, shortPreamble);
273}
274
275/*
276 * Calculate the transmit duration of an 11n frame.
277 * This only works for MCS0->MCS15.
278 */
279uint32_t
280ath_computedur_ht(uint32_t frameLen, uint16_t rate, int streams, HAL_BOOL isht40,
281 HAL_BOOL isShortGI)
282{
283 static const uint16_t ht20_bps[16] = {
284 26, 52, 78, 104, 156, 208, 234, 260,
285 52, 104, 156, 208, 312, 416, 468, 520
286 };
287 static const uint16_t ht40_bps[16] = {
288 54, 108, 162, 216, 324, 432, 486, 540,
289 108, 216, 324, 432, 648, 864, 972, 1080,
290 };
291 uint32_t bitsPerSymbol, numBits, numSymbols, txTime;
292
293 KASSERT(rate & IEEE80211_RATE_MCS, ("not mcs %d", rate));
294 KASSERT((rate &~ IEEE80211_RATE_MCS) < 16, ("bad mcs 0x%x", rate));
295
296 if (isht40)
297 bitsPerSymbol = ht40_bps[rate & 0xf];
298 else
299 bitsPerSymbol = ht20_bps[rate & 0xf];
300 numBits = OFDM_PLCP_BITS + (frameLen << 3);
301 numSymbols = howmany(numBits, bitsPerSymbol);
302 if (isShortGI)
303 txTime = ((numSymbols * 18) + 4) / 5; /* 3.6us */
304 else
305 txTime = numSymbols * 4; /* 4us */
306 return txTime + HT_L_STF + HT_L_LTF +
307 HT_L_SIG + HT_SIG + HT_STF + HT_LTF(streams);
308}
309
310/*
311 * Compute the time to transmit a frame of length frameLen bytes
312 * using the specified rate, phy, and short preamble setting.
313 */
314uint16_t
315ath_hal_computetxtime(struct ath_hal *ah,
316 const HAL_RATE_TABLE *rates, uint32_t frameLen, uint16_t rateix,
317 HAL_BOOL shortPreamble)
318{
319 uint32_t bitsPerSymbol, numBits, numSymbols, phyTime, txTime;
320 uint32_t kbps;
321
322 /* Warn if this function is called for 11n rates; it should not be! */
323 if (IS_HT_RATE(rates->info[rateix].rateCode))
324 ath_hal_printf(ah, "%s: MCS rate? (index %d; hwrate 0x%x)\n",
325 __func__, rateix, rates->info[rateix].rateCode);
326
327 kbps = rates->info[rateix].rateKbps;
328 /*
329 * index can be invalid duting dynamic Turbo transitions.
330 * XXX
331 */
332 if (kbps == 0)
333 return 0;
334 switch (rates->info[rateix].phy) {
335 case IEEE80211_T_CCK:
336 phyTime = CCK_PREAMBLE_BITS + CCK_PLCP_BITS;
337 if (shortPreamble && rates->info[rateix].shortPreamble)
338 phyTime >>= 1;
339 numBits = frameLen << 3;
340 txTime = CCK_SIFS_TIME + phyTime
341 + ((numBits * 1000)/kbps);
342 break;
343 case IEEE80211_T_OFDM:
344 bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME) / 1000;
345 HALASSERT(bitsPerSymbol != 0);
346
347 numBits = OFDM_PLCP_BITS + (frameLen << 3);
348 numSymbols = howmany(numBits, bitsPerSymbol);
349 txTime = OFDM_SIFS_TIME
350 + OFDM_PREAMBLE_TIME
351 + (numSymbols * OFDM_SYMBOL_TIME);
352 break;
353 case IEEE80211_T_OFDM_HALF:
354 bitsPerSymbol = (kbps * OFDM_HALF_SYMBOL_TIME) / 1000;
355 HALASSERT(bitsPerSymbol != 0);
356
357 numBits = OFDM_HALF_PLCP_BITS + (frameLen << 3);
358 numSymbols = howmany(numBits, bitsPerSymbol);
359 txTime = OFDM_HALF_SIFS_TIME
360 + OFDM_HALF_PREAMBLE_TIME
361 + (numSymbols * OFDM_HALF_SYMBOL_TIME);
362 break;
363 case IEEE80211_T_OFDM_QUARTER:
364 bitsPerSymbol = (kbps * OFDM_QUARTER_SYMBOL_TIME) / 1000;
365 HALASSERT(bitsPerSymbol != 0);
366
367 numBits = OFDM_QUARTER_PLCP_BITS + (frameLen << 3);
368 numSymbols = howmany(numBits, bitsPerSymbol);
369 txTime = OFDM_QUARTER_SIFS_TIME
370 + OFDM_QUARTER_PREAMBLE_TIME
371 + (numSymbols * OFDM_QUARTER_SYMBOL_TIME);
372 break;
373 case IEEE80211_T_TURBO:
374 bitsPerSymbol = (kbps * TURBO_SYMBOL_TIME) / 1000;
375 HALASSERT(bitsPerSymbol != 0);
376
377 numBits = TURBO_PLCP_BITS + (frameLen << 3);
378 numSymbols = howmany(numBits, bitsPerSymbol);
379 txTime = TURBO_SIFS_TIME
380 + TURBO_PREAMBLE_TIME
381 + (numSymbols * TURBO_SYMBOL_TIME);
382 break;
383 default:
384 HALDEBUG(ah, HAL_DEBUG_PHYIO,
385 "%s: unknown phy %u (rate ix %u)\n",
386 __func__, rates->info[rateix].phy, rateix);
387 txTime = 0;
388 break;
389 }
390 return txTime;
391}
392
393typedef enum {
394 WIRELESS_MODE_11a = 0,
395 WIRELESS_MODE_TURBO = 1,
396 WIRELESS_MODE_11b = 2,
397 WIRELESS_MODE_11g = 3,
398 WIRELESS_MODE_108g = 4,
399
400 WIRELESS_MODE_MAX
401} WIRELESS_MODE;
402
403static WIRELESS_MODE
404ath_hal_chan2wmode(struct ath_hal *ah, const struct ieee80211_channel *chan)
405{
406 if (IEEE80211_IS_CHAN_B(chan))
407 return WIRELESS_MODE_11b;
408 if (IEEE80211_IS_CHAN_G(chan))
409 return WIRELESS_MODE_11g;
410 if (IEEE80211_IS_CHAN_108G(chan))
411 return WIRELESS_MODE_108g;
412 if (IEEE80211_IS_CHAN_TURBO(chan))
413 return WIRELESS_MODE_TURBO;
414 return WIRELESS_MODE_11a;
415}
416
417/*
418 * Convert between microseconds and core system clocks.
419 */
420 /* 11a Turbo 11b 11g 108g */
421static const uint8_t CLOCK_RATE[] = { 40, 80, 22, 44, 88 };
422
423#define CLOCK_FAST_RATE_5GHZ_OFDM 44
424
425u_int
426ath_hal_mac_clks(struct ath_hal *ah, u_int usecs)
427{
428 const struct ieee80211_channel *c = AH_PRIVATE(ah)->ah_curchan;
429 u_int clks;
430
431 /* NB: ah_curchan may be null when called attach time */
432 /* XXX merlin and later specific workaround - 5ghz fast clock is 44 */
433 if (c != AH_NULL && IS_5GHZ_FAST_CLOCK_EN(ah, c)) {
434 clks = usecs * CLOCK_FAST_RATE_5GHZ_OFDM;
435 if (IEEE80211_IS_CHAN_HT40(c))
436 clks <<= 1;
437 } else if (c != AH_NULL) {
438 clks = usecs * CLOCK_RATE[ath_hal_chan2wmode(ah, c)];
439 if (IEEE80211_IS_CHAN_HT40(c))
440 clks <<= 1;
441 } else
442 clks = usecs * CLOCK_RATE[WIRELESS_MODE_11b];
443 return clks;
444}
445
446u_int
447ath_hal_mac_usec(struct ath_hal *ah, u_int clks)
448{
449 const struct ieee80211_channel *c = AH_PRIVATE(ah)->ah_curchan;
450 u_int usec;
451
452 /* NB: ah_curchan may be null when called attach time */
453 /* XXX merlin and later specific workaround - 5ghz fast clock is 44 */
454 if (c != AH_NULL && IS_5GHZ_FAST_CLOCK_EN(ah, c)) {
455 usec = clks / CLOCK_FAST_RATE_5GHZ_OFDM;
456 if (IEEE80211_IS_CHAN_HT40(c))
457 usec >>= 1;
458 } else if (c != AH_NULL) {
459 usec = clks / CLOCK_RATE[ath_hal_chan2wmode(ah, c)];
460 if (IEEE80211_IS_CHAN_HT40(c))
461 usec >>= 1;
462 } else
463 usec = clks / CLOCK_RATE[WIRELESS_MODE_11b];
464 return usec;
465}
466
467/*
468 * Setup a h/w rate table's reverse lookup table and
469 * fill in ack durations. This routine is called for
470 * each rate table returned through the ah_getRateTable
471 * method. The reverse lookup tables are assumed to be
472 * initialized to zero (or at least the first entry).
473 * We use this as a key that indicates whether or not
474 * we've previously setup the reverse lookup table.
475 *
476 * XXX not reentrant, but shouldn't matter
477 */
478void
479ath_hal_setupratetable(struct ath_hal *ah, HAL_RATE_TABLE *rt)
480{
481#define N(a) (sizeof(a)/sizeof(a[0]))
482 int i;
483
484 if (rt->rateCodeToIndex[0] != 0) /* already setup */
485 return;
486 for (i = 0; i < N(rt->rateCodeToIndex); i++)
487 rt->rateCodeToIndex[i] = (uint8_t) -1;
488 for (i = 0; i < rt->rateCount; i++) {
489 uint8_t code = rt->info[i].rateCode;
490 uint8_t cix = rt->info[i].controlRate;
491
492 HALASSERT(code < N(rt->rateCodeToIndex));
493 rt->rateCodeToIndex[code] = i;
494 HALASSERT((code | rt->info[i].shortPreamble) <
495 N(rt->rateCodeToIndex));
496 rt->rateCodeToIndex[code | rt->info[i].shortPreamble] = i;
497 /*
498 * XXX for 11g the control rate to use for 5.5 and 11 Mb/s
499 * depends on whether they are marked as basic rates;
500 * the static tables are setup with an 11b-compatible
501 * 2Mb/s rate which will work but is suboptimal
502 */
503 rt->info[i].lpAckDuration = ath_hal_computetxtime(ah, rt,
504 WLAN_CTRL_FRAME_SIZE, cix, AH_FALSE);
505 rt->info[i].spAckDuration = ath_hal_computetxtime(ah, rt,
506 WLAN_CTRL_FRAME_SIZE, cix, AH_TRUE);
507 }
508#undef N
509}
510
511HAL_STATUS
512ath_hal_getcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
513 uint32_t capability, uint32_t *result)
514{
515 const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
516
517 switch (type) {
518 case HAL_CAP_REG_DMN: /* regulatory domain */
519 *result = AH_PRIVATE(ah)->ah_currentRD;
520 return HAL_OK;
521 case HAL_CAP_CIPHER: /* cipher handled in hardware */
522 case HAL_CAP_TKIP_MIC: /* handle TKIP MIC in hardware */
523 return HAL_ENOTSUPP;
524 case HAL_CAP_TKIP_SPLIT: /* hardware TKIP uses split keys */
525 return HAL_ENOTSUPP;
526 case HAL_CAP_PHYCOUNTERS: /* hardware PHY error counters */
527 return pCap->halHwPhyCounterSupport ? HAL_OK : HAL_ENXIO;
528 case HAL_CAP_WME_TKIPMIC: /* hardware can do TKIP MIC when WMM is turned on */
529 return HAL_ENOTSUPP;
530 case HAL_CAP_DIVERSITY: /* hardware supports fast diversity */
531 return HAL_ENOTSUPP;
532 case HAL_CAP_KEYCACHE_SIZE: /* hardware key cache size */
533 *result = pCap->halKeyCacheSize;
534 return HAL_OK;
535 case HAL_CAP_NUM_TXQUEUES: /* number of hardware tx queues */
536 *result = pCap->halTotalQueues;
537 return HAL_OK;
538 case HAL_CAP_VEOL: /* hardware supports virtual EOL */
539 return pCap->halVEOLSupport ? HAL_OK : HAL_ENOTSUPP;
540 case HAL_CAP_PSPOLL: /* hardware PS-Poll support works */
541 return pCap->halPSPollBroken ? HAL_ENOTSUPP : HAL_OK;
542 case HAL_CAP_COMPRESSION:
543 return pCap->halCompressSupport ? HAL_OK : HAL_ENOTSUPP;
544 case HAL_CAP_BURST:
545 return pCap->halBurstSupport ? HAL_OK : HAL_ENOTSUPP;
546 case HAL_CAP_FASTFRAME:
547 return pCap->halFastFramesSupport ? HAL_OK : HAL_ENOTSUPP;
548 case HAL_CAP_DIAG: /* hardware diagnostic support */
549 *result = AH_PRIVATE(ah)->ah_diagreg;
550 return HAL_OK;
551 case HAL_CAP_TXPOW: /* global tx power limit */
552 switch (capability) {
553 case 0: /* facility is supported */
554 return HAL_OK;
555 case 1: /* current limit */
556 *result = AH_PRIVATE(ah)->ah_powerLimit;
557 return HAL_OK;
558 case 2: /* current max tx power */
559 *result = AH_PRIVATE(ah)->ah_maxPowerLevel;
560 return HAL_OK;
561 case 3: /* scale factor */
562 *result = AH_PRIVATE(ah)->ah_tpScale;
563 return HAL_OK;
564 }
565 return HAL_ENOTSUPP;
566 case HAL_CAP_BSSIDMASK: /* hardware supports bssid mask */
567 return pCap->halBssIdMaskSupport ? HAL_OK : HAL_ENOTSUPP;
568 case HAL_CAP_MCAST_KEYSRCH: /* multicast frame keycache search */
569 return pCap->halMcastKeySrchSupport ? HAL_OK : HAL_ENOTSUPP;
570 case HAL_CAP_TSF_ADJUST: /* hardware has beacon tsf adjust */
571 return HAL_ENOTSUPP;
572 case HAL_CAP_RFSILENT: /* rfsilent support */
573 switch (capability) {
574 case 0: /* facility is supported */
575 return pCap->halRfSilentSupport ? HAL_OK : HAL_ENOTSUPP;
576 case 1: /* current setting */
577 return AH_PRIVATE(ah)->ah_rfkillEnabled ?
578 HAL_OK : HAL_ENOTSUPP;
579 case 2: /* rfsilent config */
580 *result = AH_PRIVATE(ah)->ah_rfsilent;
581 return HAL_OK;
582 }
583 return HAL_ENOTSUPP;
584 case HAL_CAP_11D:
585 return HAL_OK;
586 case HAL_CAP_RXORN_FATAL: /* HAL_INT_RXORN treated as fatal */
587 return AH_PRIVATE(ah)->ah_rxornIsFatal ? HAL_OK : HAL_ENOTSUPP;
588 case HAL_CAP_HT:
589 return pCap->halHTSupport ? HAL_OK : HAL_ENOTSUPP;
590 case HAL_CAP_TX_CHAINMASK: /* mask of TX chains supported */
591 *result = pCap->halTxChainMask;
592 return HAL_OK;
593 case HAL_CAP_RX_CHAINMASK: /* mask of RX chains supported */
594 *result = pCap->halRxChainMask;
595 return HAL_OK;
596 case HAL_CAP_RXTSTAMP_PREC: /* rx desc tstamp precision (bits) */
597 *result = pCap->halTstampPrecision;
598 return HAL_OK;
599 case HAL_CAP_INTRMASK: /* mask of supported interrupts */
600 *result = pCap->halIntrMask;
601 return HAL_OK;
602 case HAL_CAP_BSSIDMATCH: /* hardware has disable bssid match */
603 return pCap->halBssidMatchSupport ? HAL_OK : HAL_ENOTSUPP;
604 case HAL_CAP_STREAMS: /* number of 11n spatial streams */
605 switch (capability) {
606 case 0: /* TX */
607 *result = pCap->halTxStreams;
608 return HAL_OK;
609 case 1: /* RX */
610 *result = pCap->halRxStreams;
611 return HAL_OK;
612 default:
613 return HAL_ENOTSUPP;
614 }
615 case HAL_CAP_SPLIT_4KB_TRANS: /* hardware handles descriptors straddling 4k page boundary */
616 return pCap->hal4kbSplitTransSupport ? HAL_OK : HAL_ENOTSUPP;
617 case HAL_CAP_HAS_PSPOLL: /* hardware has ps-poll support */
618 return pCap->halHasPsPollSupport ? HAL_OK : HAL_ENOTSUPP;
619 case HAL_CAP_RXDESC_SELFLINK: /* hardware supports self-linked final RX descriptors correctly */
620 return pCap->halHasRxSelfLinkedTail ? HAL_OK : HAL_ENOTSUPP;
619 default:
620 return HAL_EINVAL;
621 }
622}
623
624HAL_BOOL
625ath_hal_setcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
626 uint32_t capability, uint32_t setting, HAL_STATUS *status)
627{
628
629 switch (type) {
630 case HAL_CAP_TXPOW:
631 switch (capability) {
632 case 3:
633 if (setting <= HAL_TP_SCALE_MIN) {
634 AH_PRIVATE(ah)->ah_tpScale = setting;
635 return AH_TRUE;
636 }
637 break;
638 }
639 break;
640 case HAL_CAP_RFSILENT: /* rfsilent support */
641 /*
642 * NB: allow even if halRfSilentSupport is false
643 * in case the EEPROM is misprogrammed.
644 */
645 switch (capability) {
646 case 1: /* current setting */
647 AH_PRIVATE(ah)->ah_rfkillEnabled = (setting != 0);
648 return AH_TRUE;
649 case 2: /* rfsilent config */
650 /* XXX better done per-chip for validation? */
651 AH_PRIVATE(ah)->ah_rfsilent = setting;
652 return AH_TRUE;
653 }
654 break;
655 case HAL_CAP_REG_DMN: /* regulatory domain */
656 AH_PRIVATE(ah)->ah_currentRD = setting;
657 return AH_TRUE;
658 case HAL_CAP_RXORN_FATAL: /* HAL_INT_RXORN treated as fatal */
659 AH_PRIVATE(ah)->ah_rxornIsFatal = setting;
660 return AH_TRUE;
661 default:
662 break;
663 }
664 if (status)
665 *status = HAL_EINVAL;
666 return AH_FALSE;
667}
668
669/*
670 * Common support for getDiagState method.
671 */
672
673static u_int
674ath_hal_getregdump(struct ath_hal *ah, const HAL_REGRANGE *regs,
675 void *dstbuf, int space)
676{
677 uint32_t *dp = dstbuf;
678 int i;
679
680 for (i = 0; space >= 2*sizeof(uint32_t); i++) {
681 u_int r = regs[i].start;
682 u_int e = regs[i].end;
683 *dp++ = (r<<16) | e;
684 space -= sizeof(uint32_t);
685 do {
686 *dp++ = OS_REG_READ(ah, r);
687 r += sizeof(uint32_t);
688 space -= sizeof(uint32_t);
689 } while (r <= e && space >= sizeof(uint32_t));
690 }
691 return (char *) dp - (char *) dstbuf;
692}
693
694static void
695ath_hal_setregs(struct ath_hal *ah, const HAL_REGWRITE *regs, int space)
696{
697 while (space >= sizeof(HAL_REGWRITE)) {
698 OS_REG_WRITE(ah, regs->addr, regs->value);
699 regs++, space -= sizeof(HAL_REGWRITE);
700 }
701}
702
703HAL_BOOL
704ath_hal_getdiagstate(struct ath_hal *ah, int request,
705 const void *args, uint32_t argsize,
706 void **result, uint32_t *resultsize)
707{
708 switch (request) {
709 case HAL_DIAG_REVS:
710 *result = &AH_PRIVATE(ah)->ah_devid;
711 *resultsize = sizeof(HAL_REVS);
712 return AH_TRUE;
713 case HAL_DIAG_REGS:
714 *resultsize = ath_hal_getregdump(ah, args, *result,*resultsize);
715 return AH_TRUE;
716 case HAL_DIAG_SETREGS:
717 ath_hal_setregs(ah, args, argsize);
718 *resultsize = 0;
719 return AH_TRUE;
720 case HAL_DIAG_FATALERR:
721 *result = &AH_PRIVATE(ah)->ah_fatalState[0];
722 *resultsize = sizeof(AH_PRIVATE(ah)->ah_fatalState);
723 return AH_TRUE;
724 case HAL_DIAG_EEREAD:
725 if (argsize != sizeof(uint16_t))
726 return AH_FALSE;
727 if (!ath_hal_eepromRead(ah, *(const uint16_t *)args, *result))
728 return AH_FALSE;
729 *resultsize = sizeof(uint16_t);
730 return AH_TRUE;
731#ifdef AH_PRIVATE_DIAG
732 case HAL_DIAG_SETKEY: {
733 const HAL_DIAG_KEYVAL *dk;
734
735 if (argsize != sizeof(HAL_DIAG_KEYVAL))
736 return AH_FALSE;
737 dk = (const HAL_DIAG_KEYVAL *)args;
738 return ah->ah_setKeyCacheEntry(ah, dk->dk_keyix,
739 &dk->dk_keyval, dk->dk_mac, dk->dk_xor);
740 }
741 case HAL_DIAG_RESETKEY:
742 if (argsize != sizeof(uint16_t))
743 return AH_FALSE;
744 return ah->ah_resetKeyCacheEntry(ah, *(const uint16_t *)args);
745#ifdef AH_SUPPORT_WRITE_EEPROM
746 case HAL_DIAG_EEWRITE: {
747 const HAL_DIAG_EEVAL *ee;
748 if (argsize != sizeof(HAL_DIAG_EEVAL))
749 return AH_FALSE;
750 ee = (const HAL_DIAG_EEVAL *)args;
751 return ath_hal_eepromWrite(ah, ee->ee_off, ee->ee_data);
752 }
753#endif /* AH_SUPPORT_WRITE_EEPROM */
754#endif /* AH_PRIVATE_DIAG */
755 case HAL_DIAG_11NCOMPAT:
756 if (argsize == 0) {
757 *resultsize = sizeof(uint32_t);
758 *((uint32_t *)(*result)) =
759 AH_PRIVATE(ah)->ah_11nCompat;
760 } else if (argsize == sizeof(uint32_t)) {
761 AH_PRIVATE(ah)->ah_11nCompat = *(const uint32_t *)args;
762 } else
763 return AH_FALSE;
764 return AH_TRUE;
765 }
766 return AH_FALSE;
767}
768
769/*
770 * Set the properties of the tx queue with the parameters
771 * from qInfo.
772 */
773HAL_BOOL
774ath_hal_setTxQProps(struct ath_hal *ah,
775 HAL_TX_QUEUE_INFO *qi, const HAL_TXQ_INFO *qInfo)
776{
777 uint32_t cw;
778
779 if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
780 HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
781 "%s: inactive queue\n", __func__);
782 return AH_FALSE;
783 }
784 /* XXX validate parameters */
785 qi->tqi_ver = qInfo->tqi_ver;
786 qi->tqi_subtype = qInfo->tqi_subtype;
787 qi->tqi_qflags = qInfo->tqi_qflags;
788 qi->tqi_priority = qInfo->tqi_priority;
789 if (qInfo->tqi_aifs != HAL_TXQ_USEDEFAULT)
790 qi->tqi_aifs = AH_MIN(qInfo->tqi_aifs, 255);
791 else
792 qi->tqi_aifs = INIT_AIFS;
793 if (qInfo->tqi_cwmin != HAL_TXQ_USEDEFAULT) {
794 cw = AH_MIN(qInfo->tqi_cwmin, 1024);
795 /* make sure that the CWmin is of the form (2^n - 1) */
796 qi->tqi_cwmin = 1;
797 while (qi->tqi_cwmin < cw)
798 qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1;
799 } else
800 qi->tqi_cwmin = qInfo->tqi_cwmin;
801 if (qInfo->tqi_cwmax != HAL_TXQ_USEDEFAULT) {
802 cw = AH_MIN(qInfo->tqi_cwmax, 1024);
803 /* make sure that the CWmax is of the form (2^n - 1) */
804 qi->tqi_cwmax = 1;
805 while (qi->tqi_cwmax < cw)
806 qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1;
807 } else
808 qi->tqi_cwmax = INIT_CWMAX;
809 /* Set retry limit values */
810 if (qInfo->tqi_shretry != 0)
811 qi->tqi_shretry = AH_MIN(qInfo->tqi_shretry, 15);
812 else
813 qi->tqi_shretry = INIT_SH_RETRY;
814 if (qInfo->tqi_lgretry != 0)
815 qi->tqi_lgretry = AH_MIN(qInfo->tqi_lgretry, 15);
816 else
817 qi->tqi_lgretry = INIT_LG_RETRY;
818 qi->tqi_cbrPeriod = qInfo->tqi_cbrPeriod;
819 qi->tqi_cbrOverflowLimit = qInfo->tqi_cbrOverflowLimit;
820 qi->tqi_burstTime = qInfo->tqi_burstTime;
821 qi->tqi_readyTime = qInfo->tqi_readyTime;
822
823 switch (qInfo->tqi_subtype) {
824 case HAL_WME_UPSD:
825 if (qi->tqi_type == HAL_TX_QUEUE_DATA)
826 qi->tqi_intFlags = HAL_TXQ_USE_LOCKOUT_BKOFF_DIS;
827 break;
828 default:
829 break; /* NB: silence compiler */
830 }
831 return AH_TRUE;
832}
833
834HAL_BOOL
835ath_hal_getTxQProps(struct ath_hal *ah,
836 HAL_TXQ_INFO *qInfo, const HAL_TX_QUEUE_INFO *qi)
837{
838 if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
839 HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
840 "%s: inactive queue\n", __func__);
841 return AH_FALSE;
842 }
843
844 qInfo->tqi_qflags = qi->tqi_qflags;
845 qInfo->tqi_ver = qi->tqi_ver;
846 qInfo->tqi_subtype = qi->tqi_subtype;
847 qInfo->tqi_qflags = qi->tqi_qflags;
848 qInfo->tqi_priority = qi->tqi_priority;
849 qInfo->tqi_aifs = qi->tqi_aifs;
850 qInfo->tqi_cwmin = qi->tqi_cwmin;
851 qInfo->tqi_cwmax = qi->tqi_cwmax;
852 qInfo->tqi_shretry = qi->tqi_shretry;
853 qInfo->tqi_lgretry = qi->tqi_lgretry;
854 qInfo->tqi_cbrPeriod = qi->tqi_cbrPeriod;
855 qInfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit;
856 qInfo->tqi_burstTime = qi->tqi_burstTime;
857 qInfo->tqi_readyTime = qi->tqi_readyTime;
858 return AH_TRUE;
859}
860
861 /* 11a Turbo 11b 11g 108g */
862static const int16_t NOISE_FLOOR[] = { -96, -93, -98, -96, -93 };
863
864/*
865 * Read the current channel noise floor and return.
866 * If nf cal hasn't finished, channel noise floor should be 0
867 * and we return a nominal value based on band and frequency.
868 *
869 * NB: This is a private routine used by per-chip code to
870 * implement the ah_getChanNoise method.
871 */
872int16_t
873ath_hal_getChanNoise(struct ath_hal *ah, const struct ieee80211_channel *chan)
874{
875 HAL_CHANNEL_INTERNAL *ichan;
876
877 ichan = ath_hal_checkchannel(ah, chan);
878 if (ichan == AH_NULL) {
879 HALDEBUG(ah, HAL_DEBUG_NFCAL,
880 "%s: invalid channel %u/0x%x; no mapping\n",
881 __func__, chan->ic_freq, chan->ic_flags);
882 return 0;
883 }
884 if (ichan->rawNoiseFloor == 0) {
885 WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan);
886
887 HALASSERT(mode < WIRELESS_MODE_MAX);
888 return NOISE_FLOOR[mode] + ath_hal_getNfAdjust(ah, ichan);
889 } else
890 return ichan->rawNoiseFloor + ichan->noiseFloorAdjust;
891}
892
893/*
894 * Process all valid raw noise floors into the dBm noise floor values.
895 * Though our device has no reference for a dBm noise floor, we perform
896 * a relative minimization of NF's based on the lowest NF found across a
897 * channel scan.
898 */
899void
900ath_hal_process_noisefloor(struct ath_hal *ah)
901{
902 HAL_CHANNEL_INTERNAL *c;
903 int16_t correct2, correct5;
904 int16_t lowest2, lowest5;
905 int i;
906
907 /*
908 * Find the lowest 2GHz and 5GHz noise floor values after adjusting
909 * for statistically recorded NF/channel deviation.
910 */
911 correct2 = lowest2 = 0;
912 correct5 = lowest5 = 0;
913 for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
914 WIRELESS_MODE mode;
915 int16_t nf;
916
917 c = &AH_PRIVATE(ah)->ah_channels[i];
918 if (c->rawNoiseFloor >= 0)
919 continue;
920 /* XXX can't identify proper mode */
921 mode = IS_CHAN_5GHZ(c) ? WIRELESS_MODE_11a : WIRELESS_MODE_11g;
922 nf = c->rawNoiseFloor + NOISE_FLOOR[mode] +
923 ath_hal_getNfAdjust(ah, c);
924 if (IS_CHAN_5GHZ(c)) {
925 if (nf < lowest5) {
926 lowest5 = nf;
927 correct5 = NOISE_FLOOR[mode] -
928 (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
929 }
930 } else {
931 if (nf < lowest2) {
932 lowest2 = nf;
933 correct2 = NOISE_FLOOR[mode] -
934 (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
935 }
936 }
937 }
938
939 /* Correct the channels to reach the expected NF value */
940 for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
941 c = &AH_PRIVATE(ah)->ah_channels[i];
942 if (c->rawNoiseFloor >= 0)
943 continue;
944 /* Apply correction factor */
945 c->noiseFloorAdjust = ath_hal_getNfAdjust(ah, c) +
946 (IS_CHAN_5GHZ(c) ? correct5 : correct2);
947 HALDEBUG(ah, HAL_DEBUG_NFCAL, "%u raw nf %d adjust %d\n",
948 c->channel, c->rawNoiseFloor, c->noiseFloorAdjust);
949 }
950}
951
952/*
953 * INI support routines.
954 */
955
956int
957ath_hal_ini_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
958 int col, int regWr)
959{
960 int r;
961
962 HALASSERT(col < ia->cols);
963 for (r = 0; r < ia->rows; r++) {
964 OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0),
965 HAL_INI_VAL(ia, r, col));
966
967 /* Analog shift register delay seems needed for Merlin - PR kern/154220 */
968 if (HAL_INI_VAL(ia, r, 0) >= 0x7800 && HAL_INI_VAL(ia, r, 0) < 0x78a0)
969 OS_DELAY(100);
970
971 DMA_YIELD(regWr);
972 }
973 return regWr;
974}
975
976void
977ath_hal_ini_bank_setup(uint32_t data[], const HAL_INI_ARRAY *ia, int col)
978{
979 int r;
980
981 HALASSERT(col < ia->cols);
982 for (r = 0; r < ia->rows; r++)
983 data[r] = HAL_INI_VAL(ia, r, col);
984}
985
986int
987ath_hal_ini_bank_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
988 const uint32_t data[], int regWr)
989{
990 int r;
991
992 for (r = 0; r < ia->rows; r++) {
993 OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0), data[r]);
994 DMA_YIELD(regWr);
995 }
996 return regWr;
997}
998
999/*
1000 * These are EEPROM board related routines which should likely live in
1001 * a helper library of some sort.
1002 */
1003
1004/**************************************************************
1005 * ath_ee_getLowerUppderIndex
1006 *
1007 * Return indices surrounding the value in sorted integer lists.
1008 * Requirement: the input list must be monotonically increasing
1009 * and populated up to the list size
1010 * Returns: match is set if an index in the array matches exactly
1011 * or a the target is before or after the range of the array.
1012 */
1013HAL_BOOL
1014ath_ee_getLowerUpperIndex(uint8_t target, uint8_t *pList, uint16_t listSize,
1015 uint16_t *indexL, uint16_t *indexR)
1016{
1017 uint16_t i;
1018
1019 /*
1020 * Check first and last elements for beyond ordered array cases.
1021 */
1022 if (target <= pList[0]) {
1023 *indexL = *indexR = 0;
1024 return AH_TRUE;
1025 }
1026 if (target >= pList[listSize-1]) {
1027 *indexL = *indexR = (uint16_t)(listSize - 1);
1028 return AH_TRUE;
1029 }
1030
1031 /* look for value being near or between 2 values in list */
1032 for (i = 0; i < listSize - 1; i++) {
1033 /*
1034 * If value is close to the current value of the list
1035 * then target is not between values, it is one of the values
1036 */
1037 if (pList[i] == target) {
1038 *indexL = *indexR = i;
1039 return AH_TRUE;
1040 }
1041 /*
1042 * Look for value being between current value and next value
1043 * if so return these 2 values
1044 */
1045 if (target < pList[i + 1]) {
1046 *indexL = i;
1047 *indexR = (uint16_t)(i + 1);
1048 return AH_FALSE;
1049 }
1050 }
1051 HALASSERT(0);
1052 *indexL = *indexR = 0;
1053 return AH_FALSE;
1054}
1055
1056/**************************************************************
1057 * ath_ee_FillVpdTable
1058 *
1059 * Fill the Vpdlist for indices Pmax-Pmin
1060 * Note: pwrMin, pwrMax and Vpdlist are all in dBm * 4
1061 */
1062HAL_BOOL
1063ath_ee_FillVpdTable(uint8_t pwrMin, uint8_t pwrMax, uint8_t *pPwrList,
1064 uint8_t *pVpdList, uint16_t numIntercepts, uint8_t *pRetVpdList)
1065{
1066 uint16_t i, k;
1067 uint8_t currPwr = pwrMin;
1068 uint16_t idxL, idxR;
1069
1070 HALASSERT(pwrMax > pwrMin);
1071 for (i = 0; i <= (pwrMax - pwrMin) / 2; i++) {
1072 ath_ee_getLowerUpperIndex(currPwr, pPwrList, numIntercepts,
1073 &(idxL), &(idxR));
1074 if (idxR < 1)
1075 idxR = 1; /* extrapolate below */
1076 if (idxL == numIntercepts - 1)
1077 idxL = (uint16_t)(numIntercepts - 2); /* extrapolate above */
1078 if (pPwrList[idxL] == pPwrList[idxR])
1079 k = pVpdList[idxL];
1080 else
1081 k = (uint16_t)( ((currPwr - pPwrList[idxL]) * pVpdList[idxR] + (pPwrList[idxR] - currPwr) * pVpdList[idxL]) /
1082 (pPwrList[idxR] - pPwrList[idxL]) );
1083 HALASSERT(k < 256);
1084 pRetVpdList[i] = (uint8_t)k;
1085 currPwr += 2; /* half dB steps */
1086 }
1087
1088 return AH_TRUE;
1089}
1090
1091/**************************************************************************
1092 * ath_ee_interpolate
1093 *
1094 * Returns signed interpolated or the scaled up interpolated value
1095 */
1096int16_t
1097ath_ee_interpolate(uint16_t target, uint16_t srcLeft, uint16_t srcRight,
1098 int16_t targetLeft, int16_t targetRight)
1099{
1100 int16_t rv;
1101
1102 if (srcRight == srcLeft) {
1103 rv = targetLeft;
1104 } else {
1105 rv = (int16_t)( ((target - srcLeft) * targetRight +
1106 (srcRight - target) * targetLeft) / (srcRight - srcLeft) );
1107 }
1108 return rv;
1109}
621 default:
622 return HAL_EINVAL;
623 }
624}
625
626HAL_BOOL
627ath_hal_setcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
628 uint32_t capability, uint32_t setting, HAL_STATUS *status)
629{
630
631 switch (type) {
632 case HAL_CAP_TXPOW:
633 switch (capability) {
634 case 3:
635 if (setting <= HAL_TP_SCALE_MIN) {
636 AH_PRIVATE(ah)->ah_tpScale = setting;
637 return AH_TRUE;
638 }
639 break;
640 }
641 break;
642 case HAL_CAP_RFSILENT: /* rfsilent support */
643 /*
644 * NB: allow even if halRfSilentSupport is false
645 * in case the EEPROM is misprogrammed.
646 */
647 switch (capability) {
648 case 1: /* current setting */
649 AH_PRIVATE(ah)->ah_rfkillEnabled = (setting != 0);
650 return AH_TRUE;
651 case 2: /* rfsilent config */
652 /* XXX better done per-chip for validation? */
653 AH_PRIVATE(ah)->ah_rfsilent = setting;
654 return AH_TRUE;
655 }
656 break;
657 case HAL_CAP_REG_DMN: /* regulatory domain */
658 AH_PRIVATE(ah)->ah_currentRD = setting;
659 return AH_TRUE;
660 case HAL_CAP_RXORN_FATAL: /* HAL_INT_RXORN treated as fatal */
661 AH_PRIVATE(ah)->ah_rxornIsFatal = setting;
662 return AH_TRUE;
663 default:
664 break;
665 }
666 if (status)
667 *status = HAL_EINVAL;
668 return AH_FALSE;
669}
670
671/*
672 * Common support for getDiagState method.
673 */
674
675static u_int
676ath_hal_getregdump(struct ath_hal *ah, const HAL_REGRANGE *regs,
677 void *dstbuf, int space)
678{
679 uint32_t *dp = dstbuf;
680 int i;
681
682 for (i = 0; space >= 2*sizeof(uint32_t); i++) {
683 u_int r = regs[i].start;
684 u_int e = regs[i].end;
685 *dp++ = (r<<16) | e;
686 space -= sizeof(uint32_t);
687 do {
688 *dp++ = OS_REG_READ(ah, r);
689 r += sizeof(uint32_t);
690 space -= sizeof(uint32_t);
691 } while (r <= e && space >= sizeof(uint32_t));
692 }
693 return (char *) dp - (char *) dstbuf;
694}
695
696static void
697ath_hal_setregs(struct ath_hal *ah, const HAL_REGWRITE *regs, int space)
698{
699 while (space >= sizeof(HAL_REGWRITE)) {
700 OS_REG_WRITE(ah, regs->addr, regs->value);
701 regs++, space -= sizeof(HAL_REGWRITE);
702 }
703}
704
705HAL_BOOL
706ath_hal_getdiagstate(struct ath_hal *ah, int request,
707 const void *args, uint32_t argsize,
708 void **result, uint32_t *resultsize)
709{
710 switch (request) {
711 case HAL_DIAG_REVS:
712 *result = &AH_PRIVATE(ah)->ah_devid;
713 *resultsize = sizeof(HAL_REVS);
714 return AH_TRUE;
715 case HAL_DIAG_REGS:
716 *resultsize = ath_hal_getregdump(ah, args, *result,*resultsize);
717 return AH_TRUE;
718 case HAL_DIAG_SETREGS:
719 ath_hal_setregs(ah, args, argsize);
720 *resultsize = 0;
721 return AH_TRUE;
722 case HAL_DIAG_FATALERR:
723 *result = &AH_PRIVATE(ah)->ah_fatalState[0];
724 *resultsize = sizeof(AH_PRIVATE(ah)->ah_fatalState);
725 return AH_TRUE;
726 case HAL_DIAG_EEREAD:
727 if (argsize != sizeof(uint16_t))
728 return AH_FALSE;
729 if (!ath_hal_eepromRead(ah, *(const uint16_t *)args, *result))
730 return AH_FALSE;
731 *resultsize = sizeof(uint16_t);
732 return AH_TRUE;
733#ifdef AH_PRIVATE_DIAG
734 case HAL_DIAG_SETKEY: {
735 const HAL_DIAG_KEYVAL *dk;
736
737 if (argsize != sizeof(HAL_DIAG_KEYVAL))
738 return AH_FALSE;
739 dk = (const HAL_DIAG_KEYVAL *)args;
740 return ah->ah_setKeyCacheEntry(ah, dk->dk_keyix,
741 &dk->dk_keyval, dk->dk_mac, dk->dk_xor);
742 }
743 case HAL_DIAG_RESETKEY:
744 if (argsize != sizeof(uint16_t))
745 return AH_FALSE;
746 return ah->ah_resetKeyCacheEntry(ah, *(const uint16_t *)args);
747#ifdef AH_SUPPORT_WRITE_EEPROM
748 case HAL_DIAG_EEWRITE: {
749 const HAL_DIAG_EEVAL *ee;
750 if (argsize != sizeof(HAL_DIAG_EEVAL))
751 return AH_FALSE;
752 ee = (const HAL_DIAG_EEVAL *)args;
753 return ath_hal_eepromWrite(ah, ee->ee_off, ee->ee_data);
754 }
755#endif /* AH_SUPPORT_WRITE_EEPROM */
756#endif /* AH_PRIVATE_DIAG */
757 case HAL_DIAG_11NCOMPAT:
758 if (argsize == 0) {
759 *resultsize = sizeof(uint32_t);
760 *((uint32_t *)(*result)) =
761 AH_PRIVATE(ah)->ah_11nCompat;
762 } else if (argsize == sizeof(uint32_t)) {
763 AH_PRIVATE(ah)->ah_11nCompat = *(const uint32_t *)args;
764 } else
765 return AH_FALSE;
766 return AH_TRUE;
767 }
768 return AH_FALSE;
769}
770
771/*
772 * Set the properties of the tx queue with the parameters
773 * from qInfo.
774 */
775HAL_BOOL
776ath_hal_setTxQProps(struct ath_hal *ah,
777 HAL_TX_QUEUE_INFO *qi, const HAL_TXQ_INFO *qInfo)
778{
779 uint32_t cw;
780
781 if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
782 HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
783 "%s: inactive queue\n", __func__);
784 return AH_FALSE;
785 }
786 /* XXX validate parameters */
787 qi->tqi_ver = qInfo->tqi_ver;
788 qi->tqi_subtype = qInfo->tqi_subtype;
789 qi->tqi_qflags = qInfo->tqi_qflags;
790 qi->tqi_priority = qInfo->tqi_priority;
791 if (qInfo->tqi_aifs != HAL_TXQ_USEDEFAULT)
792 qi->tqi_aifs = AH_MIN(qInfo->tqi_aifs, 255);
793 else
794 qi->tqi_aifs = INIT_AIFS;
795 if (qInfo->tqi_cwmin != HAL_TXQ_USEDEFAULT) {
796 cw = AH_MIN(qInfo->tqi_cwmin, 1024);
797 /* make sure that the CWmin is of the form (2^n - 1) */
798 qi->tqi_cwmin = 1;
799 while (qi->tqi_cwmin < cw)
800 qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1;
801 } else
802 qi->tqi_cwmin = qInfo->tqi_cwmin;
803 if (qInfo->tqi_cwmax != HAL_TXQ_USEDEFAULT) {
804 cw = AH_MIN(qInfo->tqi_cwmax, 1024);
805 /* make sure that the CWmax is of the form (2^n - 1) */
806 qi->tqi_cwmax = 1;
807 while (qi->tqi_cwmax < cw)
808 qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1;
809 } else
810 qi->tqi_cwmax = INIT_CWMAX;
811 /* Set retry limit values */
812 if (qInfo->tqi_shretry != 0)
813 qi->tqi_shretry = AH_MIN(qInfo->tqi_shretry, 15);
814 else
815 qi->tqi_shretry = INIT_SH_RETRY;
816 if (qInfo->tqi_lgretry != 0)
817 qi->tqi_lgretry = AH_MIN(qInfo->tqi_lgretry, 15);
818 else
819 qi->tqi_lgretry = INIT_LG_RETRY;
820 qi->tqi_cbrPeriod = qInfo->tqi_cbrPeriod;
821 qi->tqi_cbrOverflowLimit = qInfo->tqi_cbrOverflowLimit;
822 qi->tqi_burstTime = qInfo->tqi_burstTime;
823 qi->tqi_readyTime = qInfo->tqi_readyTime;
824
825 switch (qInfo->tqi_subtype) {
826 case HAL_WME_UPSD:
827 if (qi->tqi_type == HAL_TX_QUEUE_DATA)
828 qi->tqi_intFlags = HAL_TXQ_USE_LOCKOUT_BKOFF_DIS;
829 break;
830 default:
831 break; /* NB: silence compiler */
832 }
833 return AH_TRUE;
834}
835
836HAL_BOOL
837ath_hal_getTxQProps(struct ath_hal *ah,
838 HAL_TXQ_INFO *qInfo, const HAL_TX_QUEUE_INFO *qi)
839{
840 if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
841 HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
842 "%s: inactive queue\n", __func__);
843 return AH_FALSE;
844 }
845
846 qInfo->tqi_qflags = qi->tqi_qflags;
847 qInfo->tqi_ver = qi->tqi_ver;
848 qInfo->tqi_subtype = qi->tqi_subtype;
849 qInfo->tqi_qflags = qi->tqi_qflags;
850 qInfo->tqi_priority = qi->tqi_priority;
851 qInfo->tqi_aifs = qi->tqi_aifs;
852 qInfo->tqi_cwmin = qi->tqi_cwmin;
853 qInfo->tqi_cwmax = qi->tqi_cwmax;
854 qInfo->tqi_shretry = qi->tqi_shretry;
855 qInfo->tqi_lgretry = qi->tqi_lgretry;
856 qInfo->tqi_cbrPeriod = qi->tqi_cbrPeriod;
857 qInfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit;
858 qInfo->tqi_burstTime = qi->tqi_burstTime;
859 qInfo->tqi_readyTime = qi->tqi_readyTime;
860 return AH_TRUE;
861}
862
863 /* 11a Turbo 11b 11g 108g */
864static const int16_t NOISE_FLOOR[] = { -96, -93, -98, -96, -93 };
865
866/*
867 * Read the current channel noise floor and return.
868 * If nf cal hasn't finished, channel noise floor should be 0
869 * and we return a nominal value based on band and frequency.
870 *
871 * NB: This is a private routine used by per-chip code to
872 * implement the ah_getChanNoise method.
873 */
874int16_t
875ath_hal_getChanNoise(struct ath_hal *ah, const struct ieee80211_channel *chan)
876{
877 HAL_CHANNEL_INTERNAL *ichan;
878
879 ichan = ath_hal_checkchannel(ah, chan);
880 if (ichan == AH_NULL) {
881 HALDEBUG(ah, HAL_DEBUG_NFCAL,
882 "%s: invalid channel %u/0x%x; no mapping\n",
883 __func__, chan->ic_freq, chan->ic_flags);
884 return 0;
885 }
886 if (ichan->rawNoiseFloor == 0) {
887 WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan);
888
889 HALASSERT(mode < WIRELESS_MODE_MAX);
890 return NOISE_FLOOR[mode] + ath_hal_getNfAdjust(ah, ichan);
891 } else
892 return ichan->rawNoiseFloor + ichan->noiseFloorAdjust;
893}
894
895/*
896 * Process all valid raw noise floors into the dBm noise floor values.
897 * Though our device has no reference for a dBm noise floor, we perform
898 * a relative minimization of NF's based on the lowest NF found across a
899 * channel scan.
900 */
901void
902ath_hal_process_noisefloor(struct ath_hal *ah)
903{
904 HAL_CHANNEL_INTERNAL *c;
905 int16_t correct2, correct5;
906 int16_t lowest2, lowest5;
907 int i;
908
909 /*
910 * Find the lowest 2GHz and 5GHz noise floor values after adjusting
911 * for statistically recorded NF/channel deviation.
912 */
913 correct2 = lowest2 = 0;
914 correct5 = lowest5 = 0;
915 for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
916 WIRELESS_MODE mode;
917 int16_t nf;
918
919 c = &AH_PRIVATE(ah)->ah_channels[i];
920 if (c->rawNoiseFloor >= 0)
921 continue;
922 /* XXX can't identify proper mode */
923 mode = IS_CHAN_5GHZ(c) ? WIRELESS_MODE_11a : WIRELESS_MODE_11g;
924 nf = c->rawNoiseFloor + NOISE_FLOOR[mode] +
925 ath_hal_getNfAdjust(ah, c);
926 if (IS_CHAN_5GHZ(c)) {
927 if (nf < lowest5) {
928 lowest5 = nf;
929 correct5 = NOISE_FLOOR[mode] -
930 (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
931 }
932 } else {
933 if (nf < lowest2) {
934 lowest2 = nf;
935 correct2 = NOISE_FLOOR[mode] -
936 (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
937 }
938 }
939 }
940
941 /* Correct the channels to reach the expected NF value */
942 for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
943 c = &AH_PRIVATE(ah)->ah_channels[i];
944 if (c->rawNoiseFloor >= 0)
945 continue;
946 /* Apply correction factor */
947 c->noiseFloorAdjust = ath_hal_getNfAdjust(ah, c) +
948 (IS_CHAN_5GHZ(c) ? correct5 : correct2);
949 HALDEBUG(ah, HAL_DEBUG_NFCAL, "%u raw nf %d adjust %d\n",
950 c->channel, c->rawNoiseFloor, c->noiseFloorAdjust);
951 }
952}
953
954/*
955 * INI support routines.
956 */
957
958int
959ath_hal_ini_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
960 int col, int regWr)
961{
962 int r;
963
964 HALASSERT(col < ia->cols);
965 for (r = 0; r < ia->rows; r++) {
966 OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0),
967 HAL_INI_VAL(ia, r, col));
968
969 /* Analog shift register delay seems needed for Merlin - PR kern/154220 */
970 if (HAL_INI_VAL(ia, r, 0) >= 0x7800 && HAL_INI_VAL(ia, r, 0) < 0x78a0)
971 OS_DELAY(100);
972
973 DMA_YIELD(regWr);
974 }
975 return regWr;
976}
977
978void
979ath_hal_ini_bank_setup(uint32_t data[], const HAL_INI_ARRAY *ia, int col)
980{
981 int r;
982
983 HALASSERT(col < ia->cols);
984 for (r = 0; r < ia->rows; r++)
985 data[r] = HAL_INI_VAL(ia, r, col);
986}
987
988int
989ath_hal_ini_bank_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
990 const uint32_t data[], int regWr)
991{
992 int r;
993
994 for (r = 0; r < ia->rows; r++) {
995 OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0), data[r]);
996 DMA_YIELD(regWr);
997 }
998 return regWr;
999}
1000
1001/*
1002 * These are EEPROM board related routines which should likely live in
1003 * a helper library of some sort.
1004 */
1005
1006/**************************************************************
1007 * ath_ee_getLowerUppderIndex
1008 *
1009 * Return indices surrounding the value in sorted integer lists.
1010 * Requirement: the input list must be monotonically increasing
1011 * and populated up to the list size
1012 * Returns: match is set if an index in the array matches exactly
1013 * or a the target is before or after the range of the array.
1014 */
1015HAL_BOOL
1016ath_ee_getLowerUpperIndex(uint8_t target, uint8_t *pList, uint16_t listSize,
1017 uint16_t *indexL, uint16_t *indexR)
1018{
1019 uint16_t i;
1020
1021 /*
1022 * Check first and last elements for beyond ordered array cases.
1023 */
1024 if (target <= pList[0]) {
1025 *indexL = *indexR = 0;
1026 return AH_TRUE;
1027 }
1028 if (target >= pList[listSize-1]) {
1029 *indexL = *indexR = (uint16_t)(listSize - 1);
1030 return AH_TRUE;
1031 }
1032
1033 /* look for value being near or between 2 values in list */
1034 for (i = 0; i < listSize - 1; i++) {
1035 /*
1036 * If value is close to the current value of the list
1037 * then target is not between values, it is one of the values
1038 */
1039 if (pList[i] == target) {
1040 *indexL = *indexR = i;
1041 return AH_TRUE;
1042 }
1043 /*
1044 * Look for value being between current value and next value
1045 * if so return these 2 values
1046 */
1047 if (target < pList[i + 1]) {
1048 *indexL = i;
1049 *indexR = (uint16_t)(i + 1);
1050 return AH_FALSE;
1051 }
1052 }
1053 HALASSERT(0);
1054 *indexL = *indexR = 0;
1055 return AH_FALSE;
1056}
1057
1058/**************************************************************
1059 * ath_ee_FillVpdTable
1060 *
1061 * Fill the Vpdlist for indices Pmax-Pmin
1062 * Note: pwrMin, pwrMax and Vpdlist are all in dBm * 4
1063 */
1064HAL_BOOL
1065ath_ee_FillVpdTable(uint8_t pwrMin, uint8_t pwrMax, uint8_t *pPwrList,
1066 uint8_t *pVpdList, uint16_t numIntercepts, uint8_t *pRetVpdList)
1067{
1068 uint16_t i, k;
1069 uint8_t currPwr = pwrMin;
1070 uint16_t idxL, idxR;
1071
1072 HALASSERT(pwrMax > pwrMin);
1073 for (i = 0; i <= (pwrMax - pwrMin) / 2; i++) {
1074 ath_ee_getLowerUpperIndex(currPwr, pPwrList, numIntercepts,
1075 &(idxL), &(idxR));
1076 if (idxR < 1)
1077 idxR = 1; /* extrapolate below */
1078 if (idxL == numIntercepts - 1)
1079 idxL = (uint16_t)(numIntercepts - 2); /* extrapolate above */
1080 if (pPwrList[idxL] == pPwrList[idxR])
1081 k = pVpdList[idxL];
1082 else
1083 k = (uint16_t)( ((currPwr - pPwrList[idxL]) * pVpdList[idxR] + (pPwrList[idxR] - currPwr) * pVpdList[idxL]) /
1084 (pPwrList[idxR] - pPwrList[idxL]) );
1085 HALASSERT(k < 256);
1086 pRetVpdList[i] = (uint8_t)k;
1087 currPwr += 2; /* half dB steps */
1088 }
1089
1090 return AH_TRUE;
1091}
1092
1093/**************************************************************************
1094 * ath_ee_interpolate
1095 *
1096 * Returns signed interpolated or the scaled up interpolated value
1097 */
1098int16_t
1099ath_ee_interpolate(uint16_t target, uint16_t srcLeft, uint16_t srcRight,
1100 int16_t targetLeft, int16_t targetRight)
1101{
1102 int16_t rv;
1103
1104 if (srcRight == srcLeft) {
1105 rv = targetLeft;
1106 } else {
1107 rv = (int16_t)( ((target - srcLeft) * targetRight +
1108 (srcRight - target) * targetLeft) / (srcRight - srcLeft) );
1109 }
1110 return rv;
1111}