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: stable/9/sys/dev/ath/ath_hal/ah.c 225444 2011-09-08 01:23:05Z 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 */
29 OS_SET_DECLARE(ah_chips, struct ath_hal_chip);
30
31 /*
32 * Check the set of registered chips to see if any recognize
33 * the device as one they can support.
34 */
35 const char*
ath_hal_probe(uint16_t vendorid,uint16_t devid)36 ath_hal_probe(uint16_t vendorid, uint16_t devid)
37 {
38 struct ath_hal_chip * const *pchip;
39
40 OS_SET_FOREACH(pchip, ah_chips) {
41 const char *name = (*pchip)->probe(vendorid, devid);
42 if (name != AH_NULL)
43 return name;
44 }
45 return AH_NULL;
46 }
47
48 /*
49 * Attach detects device chip revisions, initializes the hwLayer
50 * function list, reads EEPROM information,
51 * selects reset vectors, and performs a short self test.
52 * Any failures will return an error that should cause a hardware
53 * disable.
54 */
55 struct ath_hal*
ath_hal_attach(uint16_t devid,HAL_SOFTC sc,HAL_BUS_TAG st,HAL_BUS_HANDLE sh,uint16_t * eepromdata,HAL_STATUS * error)56 ath_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
84 const char *
ath_hal_mac_name(struct ath_hal * ah)85 ath_hal_mac_name(struct ath_hal *ah)
86 {
87 switch (ah->ah_macVersion) {
88 case AR_SREV_VERSION_CRETE:
89 case AR_SREV_VERSION_MAUI_1:
90 return "5210";
91 case AR_SREV_VERSION_MAUI_2:
92 case AR_SREV_VERSION_OAHU:
93 return "5211";
94 case AR_SREV_VERSION_VENICE:
95 return "5212";
96 case AR_SREV_VERSION_GRIFFIN:
97 return "2413";
98 case AR_SREV_VERSION_CONDOR:
99 return "5424";
100 case AR_SREV_VERSION_EAGLE:
101 return "5413";
102 case AR_SREV_VERSION_COBRA:
103 return "2415";
104 case AR_SREV_2425:
105 return "2425";
106 case AR_SREV_2417:
107 return "2417";
108 case AR_XSREV_VERSION_OWL_PCI:
109 return "5416";
110 case AR_XSREV_VERSION_OWL_PCIE:
111 return "5418";
112 case AR_XSREV_VERSION_HOWL:
113 return "9130";
114 case AR_XSREV_VERSION_SOWL:
115 return "9160";
116 case AR_XSREV_VERSION_MERLIN:
117 return "9280";
118 case AR_XSREV_VERSION_KITE:
119 return "9285";
120 case AR_XSREV_VERSION_KIWI:
121 return "9287";
122 }
123 return "????";
124 }
125
126 /*
127 * Return the mask of available modes based on the hardware capabilities.
128 */
129 u_int
ath_hal_getwirelessmodes(struct ath_hal * ah)130 ath_hal_getwirelessmodes(struct ath_hal*ah)
131 {
132 return ath_hal_getWirelessModes(ah);
133 }
134
135 /* linker set of registered RF backends */
136 OS_SET_DECLARE(ah_rfs, struct ath_hal_rf);
137
138 /*
139 * Check the set of registered RF backends to see if
140 * any recognize the device as one they can support.
141 */
142 struct ath_hal_rf *
ath_hal_rfprobe(struct ath_hal * ah,HAL_STATUS * ecode)143 ath_hal_rfprobe(struct ath_hal *ah, HAL_STATUS *ecode)
144 {
145 struct ath_hal_rf * const *prf;
146
147 OS_SET_FOREACH(prf, ah_rfs) {
148 struct ath_hal_rf *rf = *prf;
149 if (rf->probe(ah))
150 return rf;
151 }
152 *ecode = HAL_ENOTSUPP;
153 return AH_NULL;
154 }
155
156 const char *
ath_hal_rf_name(struct ath_hal * ah)157 ath_hal_rf_name(struct ath_hal *ah)
158 {
159 switch (ah->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) {
160 case 0: /* 5210 */
161 return "5110"; /* NB: made up */
162 case AR_RAD5111_SREV_MAJOR:
163 case AR_RAD5111_SREV_PROD:
164 return "5111";
165 case AR_RAD2111_SREV_MAJOR:
166 return "2111";
167 case AR_RAD5112_SREV_MAJOR:
168 case AR_RAD5112_SREV_2_0:
169 case AR_RAD5112_SREV_2_1:
170 return "5112";
171 case AR_RAD2112_SREV_MAJOR:
172 case AR_RAD2112_SREV_2_0:
173 case AR_RAD2112_SREV_2_1:
174 return "2112";
175 case AR_RAD2413_SREV_MAJOR:
176 return "2413";
177 case AR_RAD5413_SREV_MAJOR:
178 return "5413";
179 case AR_RAD2316_SREV_MAJOR:
180 return "2316";
181 case AR_RAD2317_SREV_MAJOR:
182 return "2317";
183 case AR_RAD5424_SREV_MAJOR:
184 return "5424";
185
186 case AR_RAD5133_SREV_MAJOR:
187 return "5133";
188 case AR_RAD2133_SREV_MAJOR:
189 return "2133";
190 case AR_RAD5122_SREV_MAJOR:
191 return "5122";
192 case AR_RAD2122_SREV_MAJOR:
193 return "2122";
194 }
195 return "????";
196 }
197
198 /*
199 * Poll the register looking for a specific value.
200 */
201 HAL_BOOL
ath_hal_wait(struct ath_hal * ah,u_int reg,uint32_t mask,uint32_t val)202 ath_hal_wait(struct ath_hal *ah, u_int reg, uint32_t mask, uint32_t val)
203 {
204 #define AH_TIMEOUT 1000
205 return ath_hal_waitfor(ah, reg, mask, val, AH_TIMEOUT);
206 #undef AH_TIMEOUT
207 }
208
209 HAL_BOOL
ath_hal_waitfor(struct ath_hal * ah,u_int reg,uint32_t mask,uint32_t val,uint32_t timeout)210 ath_hal_waitfor(struct ath_hal *ah, u_int reg, uint32_t mask, uint32_t val, uint32_t timeout)
211 {
212 int i;
213
214 for (i = 0; i < timeout; i++) {
215 if ((OS_REG_READ(ah, reg) & mask) == val)
216 return AH_TRUE;
217 OS_DELAY(10);
218 }
219 HALDEBUG(ah, HAL_DEBUG_REGIO | HAL_DEBUG_PHYIO,
220 "%s: timeout on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n",
221 __func__, reg, OS_REG_READ(ah, reg), mask, val);
222 return AH_FALSE;
223 }
224
225 /*
226 * Reverse the bits starting at the low bit for a value of
227 * bit_count in size
228 */
229 uint32_t
ath_hal_reverseBits(uint32_t val,uint32_t n)230 ath_hal_reverseBits(uint32_t val, uint32_t n)
231 {
232 uint32_t retval;
233 int i;
234
235 for (i = 0, retval = 0; i < n; i++) {
236 retval = (retval << 1) | (val & 1);
237 val >>= 1;
238 }
239 return retval;
240 }
241
242 /* 802.11n related timing definitions */
243
244 #define OFDM_PLCP_BITS 22
245 #define HT_L_STF 8
246 #define HT_L_LTF 8
247 #define HT_L_SIG 4
248 #define HT_SIG 8
249 #define HT_STF 4
250 #define HT_LTF(n) ((n) * 4)
251
252 #define HT_RC_2_MCS(_rc) ((_rc) & 0xf)
253 #define HT_RC_2_STREAMS(_rc) ((((_rc) & 0x78) >> 3) + 1)
254 #define IS_HT_RATE(_rc) ( (_rc) & IEEE80211_RATE_MCS)
255
256 /*
257 * Calculate the duration of a packet whether it is 11n or legacy.
258 */
259 uint32_t
ath_hal_pkt_txtime(struct ath_hal * ah,const HAL_RATE_TABLE * rates,uint32_t frameLen,uint16_t rateix,HAL_BOOL isht40,HAL_BOOL shortPreamble)260 ath_hal_pkt_txtime(struct ath_hal *ah, const HAL_RATE_TABLE *rates, uint32_t frameLen,
261 uint16_t rateix, HAL_BOOL isht40, HAL_BOOL shortPreamble)
262 {
263 uint8_t rc;
264 int numStreams;
265
266 rc = rates->info[rateix].rateCode;
267
268 /* Legacy rate? Return the old way */
269 if (! IS_HT_RATE(rc))
270 return ath_hal_computetxtime(ah, rates, frameLen, rateix, shortPreamble);
271
272 /* 11n frame - extract out the number of spatial streams */
273 numStreams = HT_RC_2_STREAMS(rc);
274 KASSERT(numStreams == 1 || numStreams == 2, ("number of spatial streams needs to be 1 or 2: MCS rate 0x%x!", rateix));
275
276 return ath_computedur_ht(frameLen, rc, numStreams, isht40, shortPreamble);
277 }
278
279 /*
280 * Calculate the transmit duration of an 11n frame.
281 * This only works for MCS0->MCS15.
282 */
283 uint32_t
ath_computedur_ht(uint32_t frameLen,uint16_t rate,int streams,HAL_BOOL isht40,HAL_BOOL isShortGI)284 ath_computedur_ht(uint32_t frameLen, uint16_t rate, int streams, HAL_BOOL isht40,
285 HAL_BOOL isShortGI)
286 {
287 static const uint16_t ht20_bps[16] = {
288 26, 52, 78, 104, 156, 208, 234, 260,
289 52, 104, 156, 208, 312, 416, 468, 520
290 };
291 static const uint16_t ht40_bps[16] = {
292 54, 108, 162, 216, 324, 432, 486, 540,
293 108, 216, 324, 432, 648, 864, 972, 1080,
294 };
295 uint32_t bitsPerSymbol, numBits, numSymbols, txTime;
296
297 KASSERT(rate & IEEE80211_RATE_MCS, ("not mcs %d", rate));
298 KASSERT((rate &~ IEEE80211_RATE_MCS) < 16, ("bad mcs 0x%x", rate));
299
300 if (isht40)
301 bitsPerSymbol = ht40_bps[rate & 0xf];
302 else
303 bitsPerSymbol = ht20_bps[rate & 0xf];
304 numBits = OFDM_PLCP_BITS + (frameLen << 3);
305 numSymbols = howmany(numBits, bitsPerSymbol);
306 if (isShortGI)
307 txTime = ((numSymbols * 18) + 4) / 5; /* 3.6us */
308 else
309 txTime = numSymbols * 4; /* 4us */
310 return txTime + HT_L_STF + HT_L_LTF +
311 HT_L_SIG + HT_SIG + HT_STF + HT_LTF(streams);
312 }
313
314 /*
315 * Compute the time to transmit a frame of length frameLen bytes
316 * using the specified rate, phy, and short preamble setting.
317 */
318 uint16_t
ath_hal_computetxtime(struct ath_hal * ah,const HAL_RATE_TABLE * rates,uint32_t frameLen,uint16_t rateix,HAL_BOOL shortPreamble)319 ath_hal_computetxtime(struct ath_hal *ah,
320 const HAL_RATE_TABLE *rates, uint32_t frameLen, uint16_t rateix,
321 HAL_BOOL shortPreamble)
322 {
323 uint32_t bitsPerSymbol, numBits, numSymbols, phyTime, txTime;
324 uint32_t kbps;
325
326 /* Warn if this function is called for 11n rates; it should not be! */
327 if (IS_HT_RATE(rates->info[rateix].rateCode))
328 ath_hal_printf(ah, "%s: MCS rate? (index %d; hwrate 0x%x)\n",
329 __func__, rateix, rates->info[rateix].rateCode);
330
331 kbps = rates->info[rateix].rateKbps;
332 /*
333 * index can be invalid duting dynamic Turbo transitions.
334 * XXX
335 */
336 if (kbps == 0)
337 return 0;
338 switch (rates->info[rateix].phy) {
339 case IEEE80211_T_CCK:
340 phyTime = CCK_PREAMBLE_BITS + CCK_PLCP_BITS;
341 if (shortPreamble && rates->info[rateix].shortPreamble)
342 phyTime >>= 1;
343 numBits = frameLen << 3;
344 txTime = CCK_SIFS_TIME + phyTime
345 + ((numBits * 1000)/kbps);
346 break;
347 case IEEE80211_T_OFDM:
348 bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME) / 1000;
349 HALASSERT(bitsPerSymbol != 0);
350
351 numBits = OFDM_PLCP_BITS + (frameLen << 3);
352 numSymbols = howmany(numBits, bitsPerSymbol);
353 txTime = OFDM_SIFS_TIME
354 + OFDM_PREAMBLE_TIME
355 + (numSymbols * OFDM_SYMBOL_TIME);
356 break;
357 case IEEE80211_T_OFDM_HALF:
358 bitsPerSymbol = (kbps * OFDM_HALF_SYMBOL_TIME) / 1000;
359 HALASSERT(bitsPerSymbol != 0);
360
361 numBits = OFDM_HALF_PLCP_BITS + (frameLen << 3);
362 numSymbols = howmany(numBits, bitsPerSymbol);
363 txTime = OFDM_HALF_SIFS_TIME
364 + OFDM_HALF_PREAMBLE_TIME
365 + (numSymbols * OFDM_HALF_SYMBOL_TIME);
366 break;
367 case IEEE80211_T_OFDM_QUARTER:
368 bitsPerSymbol = (kbps * OFDM_QUARTER_SYMBOL_TIME) / 1000;
369 HALASSERT(bitsPerSymbol != 0);
370
371 numBits = OFDM_QUARTER_PLCP_BITS + (frameLen << 3);
372 numSymbols = howmany(numBits, bitsPerSymbol);
373 txTime = OFDM_QUARTER_SIFS_TIME
374 + OFDM_QUARTER_PREAMBLE_TIME
375 + (numSymbols * OFDM_QUARTER_SYMBOL_TIME);
376 break;
377 case IEEE80211_T_TURBO:
378 bitsPerSymbol = (kbps * TURBO_SYMBOL_TIME) / 1000;
379 HALASSERT(bitsPerSymbol != 0);
380
381 numBits = TURBO_PLCP_BITS + (frameLen << 3);
382 numSymbols = howmany(numBits, bitsPerSymbol);
383 txTime = TURBO_SIFS_TIME
384 + TURBO_PREAMBLE_TIME
385 + (numSymbols * TURBO_SYMBOL_TIME);
386 break;
387 default:
388 HALDEBUG(ah, HAL_DEBUG_PHYIO,
389 "%s: unknown phy %u (rate ix %u)\n",
390 __func__, rates->info[rateix].phy, rateix);
391 txTime = 0;
392 break;
393 }
394 return txTime;
395 }
396
397 typedef enum {
398 WIRELESS_MODE_11a = 0,
399 WIRELESS_MODE_TURBO = 1,
400 WIRELESS_MODE_11b = 2,
401 WIRELESS_MODE_11g = 3,
402 WIRELESS_MODE_108g = 4,
403
404 WIRELESS_MODE_MAX
405 } WIRELESS_MODE;
406
407 static WIRELESS_MODE
ath_hal_chan2wmode(struct ath_hal * ah,const struct ieee80211_channel * chan)408 ath_hal_chan2wmode(struct ath_hal *ah, const struct ieee80211_channel *chan)
409 {
410 if (IEEE80211_IS_CHAN_B(chan))
411 return WIRELESS_MODE_11b;
412 if (IEEE80211_IS_CHAN_G(chan))
413 return WIRELESS_MODE_11g;
414 if (IEEE80211_IS_CHAN_108G(chan))
415 return WIRELESS_MODE_108g;
416 if (IEEE80211_IS_CHAN_TURBO(chan))
417 return WIRELESS_MODE_TURBO;
418 return WIRELESS_MODE_11a;
419 }
420
421 /*
422 * Convert between microseconds and core system clocks.
423 */
424 /* 11a Turbo 11b 11g 108g */
425 static const uint8_t CLOCK_RATE[] = { 40, 80, 22, 44, 88 };
426
427 #define CLOCK_FAST_RATE_5GHZ_OFDM 44
428
429 u_int
ath_hal_mac_clks(struct ath_hal * ah,u_int usecs)430 ath_hal_mac_clks(struct ath_hal *ah, u_int usecs)
431 {
432 const struct ieee80211_channel *c = AH_PRIVATE(ah)->ah_curchan;
433 u_int clks;
434
435 /* NB: ah_curchan may be null when called attach time */
436 /* XXX merlin and later specific workaround - 5ghz fast clock is 44 */
437 if (c != AH_NULL && IS_5GHZ_FAST_CLOCK_EN(ah, c)) {
438 clks = usecs * CLOCK_FAST_RATE_5GHZ_OFDM;
439 if (IEEE80211_IS_CHAN_HT40(c))
440 clks <<= 1;
441 } else if (c != AH_NULL) {
442 clks = usecs * CLOCK_RATE[ath_hal_chan2wmode(ah, c)];
443 if (IEEE80211_IS_CHAN_HT40(c))
444 clks <<= 1;
445 } else
446 clks = usecs * CLOCK_RATE[WIRELESS_MODE_11b];
447 return clks;
448 }
449
450 u_int
ath_hal_mac_usec(struct ath_hal * ah,u_int clks)451 ath_hal_mac_usec(struct ath_hal *ah, u_int clks)
452 {
453 const struct ieee80211_channel *c = AH_PRIVATE(ah)->ah_curchan;
454 u_int usec;
455
456 /* NB: ah_curchan may be null when called attach time */
457 /* XXX merlin and later specific workaround - 5ghz fast clock is 44 */
458 if (c != AH_NULL && IS_5GHZ_FAST_CLOCK_EN(ah, c)) {
459 usec = clks / CLOCK_FAST_RATE_5GHZ_OFDM;
460 if (IEEE80211_IS_CHAN_HT40(c))
461 usec >>= 1;
462 } else if (c != AH_NULL) {
463 usec = clks / CLOCK_RATE[ath_hal_chan2wmode(ah, c)];
464 if (IEEE80211_IS_CHAN_HT40(c))
465 usec >>= 1;
466 } else
467 usec = clks / CLOCK_RATE[WIRELESS_MODE_11b];
468 return usec;
469 }
470
471 /*
472 * Setup a h/w rate table's reverse lookup table and
473 * fill in ack durations. This routine is called for
474 * each rate table returned through the ah_getRateTable
475 * method. The reverse lookup tables are assumed to be
476 * initialized to zero (or at least the first entry).
477 * We use this as a key that indicates whether or not
478 * we've previously setup the reverse lookup table.
479 *
480 * XXX not reentrant, but shouldn't matter
481 */
482 void
ath_hal_setupratetable(struct ath_hal * ah,HAL_RATE_TABLE * rt)483 ath_hal_setupratetable(struct ath_hal *ah, HAL_RATE_TABLE *rt)
484 {
485 #define N(a) (sizeof(a)/sizeof(a[0]))
486 int i;
487
488 if (rt->rateCodeToIndex[0] != 0) /* already setup */
489 return;
490 for (i = 0; i < N(rt->rateCodeToIndex); i++)
491 rt->rateCodeToIndex[i] = (uint8_t) -1;
492 for (i = 0; i < rt->rateCount; i++) {
493 uint8_t code = rt->info[i].rateCode;
494 uint8_t cix = rt->info[i].controlRate;
495
496 HALASSERT(code < N(rt->rateCodeToIndex));
497 rt->rateCodeToIndex[code] = i;
498 HALASSERT((code | rt->info[i].shortPreamble) <
499 N(rt->rateCodeToIndex));
500 rt->rateCodeToIndex[code | rt->info[i].shortPreamble] = i;
501 /*
502 * XXX for 11g the control rate to use for 5.5 and 11 Mb/s
503 * depends on whether they are marked as basic rates;
504 * the static tables are setup with an 11b-compatible
505 * 2Mb/s rate which will work but is suboptimal
506 */
507 rt->info[i].lpAckDuration = ath_hal_computetxtime(ah, rt,
508 WLAN_CTRL_FRAME_SIZE, cix, AH_FALSE);
509 rt->info[i].spAckDuration = ath_hal_computetxtime(ah, rt,
510 WLAN_CTRL_FRAME_SIZE, cix, AH_TRUE);
511 }
512 #undef N
513 }
514
515 HAL_STATUS
ath_hal_getcapability(struct ath_hal * ah,HAL_CAPABILITY_TYPE type,uint32_t capability,uint32_t * result)516 ath_hal_getcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
517 uint32_t capability, uint32_t *result)
518 {
519 const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
520
521 switch (type) {
522 case HAL_CAP_REG_DMN: /* regulatory domain */
523 *result = AH_PRIVATE(ah)->ah_currentRD;
524 return HAL_OK;
525 case HAL_CAP_DFS_DMN: /* DFS Domain */
526 *result = AH_PRIVATE(ah)->ah_dfsDomain;
527 return HAL_OK;
528 case HAL_CAP_CIPHER: /* cipher handled in hardware */
529 case HAL_CAP_TKIP_MIC: /* handle TKIP MIC in hardware */
530 return HAL_ENOTSUPP;
531 case HAL_CAP_TKIP_SPLIT: /* hardware TKIP uses split keys */
532 return HAL_ENOTSUPP;
533 case HAL_CAP_PHYCOUNTERS: /* hardware PHY error counters */
534 return pCap->halHwPhyCounterSupport ? HAL_OK : HAL_ENXIO;
535 case HAL_CAP_WME_TKIPMIC: /* hardware can do TKIP MIC when WMM is turned on */
536 return HAL_ENOTSUPP;
537 case HAL_CAP_DIVERSITY: /* hardware supports fast diversity */
538 return HAL_ENOTSUPP;
539 case HAL_CAP_KEYCACHE_SIZE: /* hardware key cache size */
540 *result = pCap->halKeyCacheSize;
541 return HAL_OK;
542 case HAL_CAP_NUM_TXQUEUES: /* number of hardware tx queues */
543 *result = pCap->halTotalQueues;
544 return HAL_OK;
545 case HAL_CAP_VEOL: /* hardware supports virtual EOL */
546 return pCap->halVEOLSupport ? HAL_OK : HAL_ENOTSUPP;
547 case HAL_CAP_PSPOLL: /* hardware PS-Poll support works */
548 return pCap->halPSPollBroken ? HAL_ENOTSUPP : HAL_OK;
549 case HAL_CAP_COMPRESSION:
550 return pCap->halCompressSupport ? HAL_OK : HAL_ENOTSUPP;
551 case HAL_CAP_BURST:
552 return pCap->halBurstSupport ? HAL_OK : HAL_ENOTSUPP;
553 case HAL_CAP_FASTFRAME:
554 return pCap->halFastFramesSupport ? HAL_OK : HAL_ENOTSUPP;
555 case HAL_CAP_DIAG: /* hardware diagnostic support */
556 *result = AH_PRIVATE(ah)->ah_diagreg;
557 return HAL_OK;
558 case HAL_CAP_TXPOW: /* global tx power limit */
559 switch (capability) {
560 case 0: /* facility is supported */
561 return HAL_OK;
562 case 1: /* current limit */
563 *result = AH_PRIVATE(ah)->ah_powerLimit;
564 return HAL_OK;
565 case 2: /* current max tx power */
566 *result = AH_PRIVATE(ah)->ah_maxPowerLevel;
567 return HAL_OK;
568 case 3: /* scale factor */
569 *result = AH_PRIVATE(ah)->ah_tpScale;
570 return HAL_OK;
571 }
572 return HAL_ENOTSUPP;
573 case HAL_CAP_BSSIDMASK: /* hardware supports bssid mask */
574 return pCap->halBssIdMaskSupport ? HAL_OK : HAL_ENOTSUPP;
575 case HAL_CAP_MCAST_KEYSRCH: /* multicast frame keycache search */
576 return pCap->halMcastKeySrchSupport ? HAL_OK : HAL_ENOTSUPP;
577 case HAL_CAP_TSF_ADJUST: /* hardware has beacon tsf adjust */
578 return HAL_ENOTSUPP;
579 case HAL_CAP_RFSILENT: /* rfsilent support */
580 switch (capability) {
581 case 0: /* facility is supported */
582 return pCap->halRfSilentSupport ? HAL_OK : HAL_ENOTSUPP;
583 case 1: /* current setting */
584 return AH_PRIVATE(ah)->ah_rfkillEnabled ?
585 HAL_OK : HAL_ENOTSUPP;
586 case 2: /* rfsilent config */
587 *result = AH_PRIVATE(ah)->ah_rfsilent;
588 return HAL_OK;
589 }
590 return HAL_ENOTSUPP;
591 case HAL_CAP_11D:
592 return HAL_OK;
593
594 case HAL_CAP_HT:
595 return pCap->halHTSupport ? HAL_OK : HAL_ENOTSUPP;
596 case HAL_CAP_GTXTO:
597 return pCap->halGTTSupport ? HAL_OK : HAL_ENOTSUPP;
598 case HAL_CAP_FAST_CC:
599 return pCap->halFastCCSupport ? HAL_OK : HAL_ENOTSUPP;
600 case HAL_CAP_TX_CHAINMASK: /* mask of TX chains supported */
601 *result = pCap->halTxChainMask;
602 return HAL_OK;
603 case HAL_CAP_RX_CHAINMASK: /* mask of RX chains supported */
604 *result = pCap->halRxChainMask;
605 return HAL_OK;
606 case HAL_CAP_NUM_GPIO_PINS:
607 *result = pCap->halNumGpioPins;
608 return HAL_OK;
609 case HAL_CAP_CST:
610 return pCap->halCSTSupport ? HAL_OK : HAL_ENOTSUPP;
611 case HAL_CAP_RTS_AGGR_LIMIT:
612 *result = pCap->halRtsAggrLimit;
613 return HAL_OK;
614 case HAL_CAP_4ADDR_AGGR:
615 return pCap->hal4AddrAggrSupport ? HAL_OK : HAL_ENOTSUPP;
616 case HAL_CAP_EXT_CHAN_DFS:
617 return pCap->halExtChanDfsSupport ? HAL_OK : HAL_ENOTSUPP;
618 case HAL_CAP_COMBINED_RADAR_RSSI:
619 return pCap->halUseCombinedRadarRssi ? HAL_OK : HAL_ENOTSUPP;
620 case HAL_CAP_AUTO_SLEEP:
621 return pCap->halAutoSleepSupport ? HAL_OK : HAL_ENOTSUPP;
622 case HAL_CAP_MBSSID_AGGR_SUPPORT:
623 return pCap->halMbssidAggrSupport ? HAL_OK : HAL_ENOTSUPP;
624 case HAL_CAP_SPLIT_4KB_TRANS: /* hardware handles descriptors straddling 4k page boundary */
625 return pCap->hal4kbSplitTransSupport ? HAL_OK : HAL_ENOTSUPP;
626 case HAL_CAP_REG_FLAG:
627 *result = AH_PRIVATE(ah)->ah_currentRDext;
628 return HAL_OK;
629 case HAL_CAP_BT_COEX:
630 return pCap->halBtCoexSupport ? HAL_OK : HAL_ENOTSUPP;
631 case HAL_CAP_HT20_SGI:
632 return pCap->halHTSGI20Support ? HAL_OK : HAL_ENOTSUPP;
633 case HAL_CAP_RXTSTAMP_PREC: /* rx desc tstamp precision (bits) */
634 *result = pCap->halTstampPrecision;
635 return HAL_OK;
636 case HAL_CAP_ENHANCED_DFS_SUPPORT:
637 return pCap->halEnhancedDfsSupport ? HAL_OK : HAL_ENOTSUPP;
638
639 /* FreeBSD-specific entries for now */
640 case HAL_CAP_RXORN_FATAL: /* HAL_INT_RXORN treated as fatal */
641 return AH_PRIVATE(ah)->ah_rxornIsFatal ? HAL_OK : HAL_ENOTSUPP;
642 case HAL_CAP_INTRMASK: /* mask of supported interrupts */
643 *result = pCap->halIntrMask;
644 return HAL_OK;
645 case HAL_CAP_BSSIDMATCH: /* hardware has disable bssid match */
646 return pCap->halBssidMatchSupport ? HAL_OK : HAL_ENOTSUPP;
647 case HAL_CAP_STREAMS: /* number of 11n spatial streams */
648 switch (capability) {
649 case 0: /* TX */
650 *result = pCap->halTxStreams;
651 return HAL_OK;
652 case 1: /* RX */
653 *result = pCap->halRxStreams;
654 return HAL_OK;
655 default:
656 return HAL_ENOTSUPP;
657 }
658 case HAL_CAP_RXDESC_SELFLINK: /* hardware supports self-linked final RX descriptors correctly */
659 return pCap->halHasRxSelfLinkedTail ? HAL_OK : HAL_ENOTSUPP;
660 case HAL_CAP_LONG_RXDESC_TSF: /* 32 bit TSF in RX descriptor? */
661 return pCap->halHasLongRxDescTsf ? HAL_OK : HAL_ENOTSUPP;
662 default:
663 return HAL_EINVAL;
664 }
665 }
666
667 HAL_BOOL
ath_hal_setcapability(struct ath_hal * ah,HAL_CAPABILITY_TYPE type,uint32_t capability,uint32_t setting,HAL_STATUS * status)668 ath_hal_setcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
669 uint32_t capability, uint32_t setting, HAL_STATUS *status)
670 {
671
672 switch (type) {
673 case HAL_CAP_TXPOW:
674 switch (capability) {
675 case 3:
676 if (setting <= HAL_TP_SCALE_MIN) {
677 AH_PRIVATE(ah)->ah_tpScale = setting;
678 return AH_TRUE;
679 }
680 break;
681 }
682 break;
683 case HAL_CAP_RFSILENT: /* rfsilent support */
684 /*
685 * NB: allow even if halRfSilentSupport is false
686 * in case the EEPROM is misprogrammed.
687 */
688 switch (capability) {
689 case 1: /* current setting */
690 AH_PRIVATE(ah)->ah_rfkillEnabled = (setting != 0);
691 return AH_TRUE;
692 case 2: /* rfsilent config */
693 /* XXX better done per-chip for validation? */
694 AH_PRIVATE(ah)->ah_rfsilent = setting;
695 return AH_TRUE;
696 }
697 break;
698 case HAL_CAP_REG_DMN: /* regulatory domain */
699 AH_PRIVATE(ah)->ah_currentRD = setting;
700 return AH_TRUE;
701 case HAL_CAP_RXORN_FATAL: /* HAL_INT_RXORN treated as fatal */
702 AH_PRIVATE(ah)->ah_rxornIsFatal = setting;
703 return AH_TRUE;
704 default:
705 break;
706 }
707 if (status)
708 *status = HAL_EINVAL;
709 return AH_FALSE;
710 }
711
712 /*
713 * Common support for getDiagState method.
714 */
715
716 static u_int
ath_hal_getregdump(struct ath_hal * ah,const HAL_REGRANGE * regs,void * dstbuf,int space)717 ath_hal_getregdump(struct ath_hal *ah, const HAL_REGRANGE *regs,
718 void *dstbuf, int space)
719 {
720 uint32_t *dp = dstbuf;
721 int i;
722
723 for (i = 0; space >= 2*sizeof(uint32_t); i++) {
724 u_int r = regs[i].start;
725 u_int e = regs[i].end;
726 *dp++ = (r<<16) | e;
727 space -= sizeof(uint32_t);
728 do {
729 *dp++ = OS_REG_READ(ah, r);
730 r += sizeof(uint32_t);
731 space -= sizeof(uint32_t);
732 } while (r <= e && space >= sizeof(uint32_t));
733 }
734 return (char *) dp - (char *) dstbuf;
735 }
736
737 static void
ath_hal_setregs(struct ath_hal * ah,const HAL_REGWRITE * regs,int space)738 ath_hal_setregs(struct ath_hal *ah, const HAL_REGWRITE *regs, int space)
739 {
740 while (space >= sizeof(HAL_REGWRITE)) {
741 OS_REG_WRITE(ah, regs->addr, regs->value);
742 regs++, space -= sizeof(HAL_REGWRITE);
743 }
744 }
745
746 HAL_BOOL
ath_hal_getdiagstate(struct ath_hal * ah,int request,const void * args,uint32_t argsize,void ** result,uint32_t * resultsize)747 ath_hal_getdiagstate(struct ath_hal *ah, int request,
748 const void *args, uint32_t argsize,
749 void **result, uint32_t *resultsize)
750 {
751 switch (request) {
752 case HAL_DIAG_REVS:
753 *result = &AH_PRIVATE(ah)->ah_devid;
754 *resultsize = sizeof(HAL_REVS);
755 return AH_TRUE;
756 case HAL_DIAG_REGS:
757 *resultsize = ath_hal_getregdump(ah, args, *result,*resultsize);
758 return AH_TRUE;
759 case HAL_DIAG_SETREGS:
760 ath_hal_setregs(ah, args, argsize);
761 *resultsize = 0;
762 return AH_TRUE;
763 case HAL_DIAG_FATALERR:
764 *result = &AH_PRIVATE(ah)->ah_fatalState[0];
765 *resultsize = sizeof(AH_PRIVATE(ah)->ah_fatalState);
766 return AH_TRUE;
767 case HAL_DIAG_EEREAD:
768 if (argsize != sizeof(uint16_t))
769 return AH_FALSE;
770 if (!ath_hal_eepromRead(ah, *(const uint16_t *)args, *result))
771 return AH_FALSE;
772 *resultsize = sizeof(uint16_t);
773 return AH_TRUE;
774 #ifdef AH_PRIVATE_DIAG
775 case HAL_DIAG_SETKEY: {
776 const HAL_DIAG_KEYVAL *dk;
777
778 if (argsize != sizeof(HAL_DIAG_KEYVAL))
779 return AH_FALSE;
780 dk = (const HAL_DIAG_KEYVAL *)args;
781 return ah->ah_setKeyCacheEntry(ah, dk->dk_keyix,
782 &dk->dk_keyval, dk->dk_mac, dk->dk_xor);
783 }
784 case HAL_DIAG_RESETKEY:
785 if (argsize != sizeof(uint16_t))
786 return AH_FALSE;
787 return ah->ah_resetKeyCacheEntry(ah, *(const uint16_t *)args);
788 #ifdef AH_SUPPORT_WRITE_EEPROM
789 case HAL_DIAG_EEWRITE: {
790 const HAL_DIAG_EEVAL *ee;
791 if (argsize != sizeof(HAL_DIAG_EEVAL))
792 return AH_FALSE;
793 ee = (const HAL_DIAG_EEVAL *)args;
794 return ath_hal_eepromWrite(ah, ee->ee_off, ee->ee_data);
795 }
796 #endif /* AH_SUPPORT_WRITE_EEPROM */
797 #endif /* AH_PRIVATE_DIAG */
798 case HAL_DIAG_11NCOMPAT:
799 if (argsize == 0) {
800 *resultsize = sizeof(uint32_t);
801 *((uint32_t *)(*result)) =
802 AH_PRIVATE(ah)->ah_11nCompat;
803 } else if (argsize == sizeof(uint32_t)) {
804 AH_PRIVATE(ah)->ah_11nCompat = *(const uint32_t *)args;
805 } else
806 return AH_FALSE;
807 return AH_TRUE;
808 }
809 return AH_FALSE;
810 }
811
812 /*
813 * Set the properties of the tx queue with the parameters
814 * from qInfo.
815 */
816 HAL_BOOL
ath_hal_setTxQProps(struct ath_hal * ah,HAL_TX_QUEUE_INFO * qi,const HAL_TXQ_INFO * qInfo)817 ath_hal_setTxQProps(struct ath_hal *ah,
818 HAL_TX_QUEUE_INFO *qi, const HAL_TXQ_INFO *qInfo)
819 {
820 uint32_t cw;
821
822 if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
823 HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
824 "%s: inactive queue\n", __func__);
825 return AH_FALSE;
826 }
827 /* XXX validate parameters */
828 qi->tqi_ver = qInfo->tqi_ver;
829 qi->tqi_subtype = qInfo->tqi_subtype;
830 qi->tqi_qflags = qInfo->tqi_qflags;
831 qi->tqi_priority = qInfo->tqi_priority;
832 if (qInfo->tqi_aifs != HAL_TXQ_USEDEFAULT)
833 qi->tqi_aifs = AH_MIN(qInfo->tqi_aifs, 255);
834 else
835 qi->tqi_aifs = INIT_AIFS;
836 if (qInfo->tqi_cwmin != HAL_TXQ_USEDEFAULT) {
837 cw = AH_MIN(qInfo->tqi_cwmin, 1024);
838 /* make sure that the CWmin is of the form (2^n - 1) */
839 qi->tqi_cwmin = 1;
840 while (qi->tqi_cwmin < cw)
841 qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1;
842 } else
843 qi->tqi_cwmin = qInfo->tqi_cwmin;
844 if (qInfo->tqi_cwmax != HAL_TXQ_USEDEFAULT) {
845 cw = AH_MIN(qInfo->tqi_cwmax, 1024);
846 /* make sure that the CWmax is of the form (2^n - 1) */
847 qi->tqi_cwmax = 1;
848 while (qi->tqi_cwmax < cw)
849 qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1;
850 } else
851 qi->tqi_cwmax = INIT_CWMAX;
852 /* Set retry limit values */
853 if (qInfo->tqi_shretry != 0)
854 qi->tqi_shretry = AH_MIN(qInfo->tqi_shretry, 15);
855 else
856 qi->tqi_shretry = INIT_SH_RETRY;
857 if (qInfo->tqi_lgretry != 0)
858 qi->tqi_lgretry = AH_MIN(qInfo->tqi_lgretry, 15);
859 else
860 qi->tqi_lgretry = INIT_LG_RETRY;
861 qi->tqi_cbrPeriod = qInfo->tqi_cbrPeriod;
862 qi->tqi_cbrOverflowLimit = qInfo->tqi_cbrOverflowLimit;
863 qi->tqi_burstTime = qInfo->tqi_burstTime;
864 qi->tqi_readyTime = qInfo->tqi_readyTime;
865
866 switch (qInfo->tqi_subtype) {
867 case HAL_WME_UPSD:
868 if (qi->tqi_type == HAL_TX_QUEUE_DATA)
869 qi->tqi_intFlags = HAL_TXQ_USE_LOCKOUT_BKOFF_DIS;
870 break;
871 default:
872 break; /* NB: silence compiler */
873 }
874 return AH_TRUE;
875 }
876
877 HAL_BOOL
ath_hal_getTxQProps(struct ath_hal * ah,HAL_TXQ_INFO * qInfo,const HAL_TX_QUEUE_INFO * qi)878 ath_hal_getTxQProps(struct ath_hal *ah,
879 HAL_TXQ_INFO *qInfo, const HAL_TX_QUEUE_INFO *qi)
880 {
881 if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
882 HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
883 "%s: inactive queue\n", __func__);
884 return AH_FALSE;
885 }
886
887 qInfo->tqi_qflags = qi->tqi_qflags;
888 qInfo->tqi_ver = qi->tqi_ver;
889 qInfo->tqi_subtype = qi->tqi_subtype;
890 qInfo->tqi_qflags = qi->tqi_qflags;
891 qInfo->tqi_priority = qi->tqi_priority;
892 qInfo->tqi_aifs = qi->tqi_aifs;
893 qInfo->tqi_cwmin = qi->tqi_cwmin;
894 qInfo->tqi_cwmax = qi->tqi_cwmax;
895 qInfo->tqi_shretry = qi->tqi_shretry;
896 qInfo->tqi_lgretry = qi->tqi_lgretry;
897 qInfo->tqi_cbrPeriod = qi->tqi_cbrPeriod;
898 qInfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit;
899 qInfo->tqi_burstTime = qi->tqi_burstTime;
900 qInfo->tqi_readyTime = qi->tqi_readyTime;
901 return AH_TRUE;
902 }
903
904 /* 11a Turbo 11b 11g 108g */
905 static const int16_t NOISE_FLOOR[] = { -96, -93, -98, -96, -93 };
906
907 /*
908 * Read the current channel noise floor and return.
909 * If nf cal hasn't finished, channel noise floor should be 0
910 * and we return a nominal value based on band and frequency.
911 *
912 * NB: This is a private routine used by per-chip code to
913 * implement the ah_getChanNoise method.
914 */
915 int16_t
ath_hal_getChanNoise(struct ath_hal * ah,const struct ieee80211_channel * chan)916 ath_hal_getChanNoise(struct ath_hal *ah, const struct ieee80211_channel *chan)
917 {
918 HAL_CHANNEL_INTERNAL *ichan;
919
920 ichan = ath_hal_checkchannel(ah, chan);
921 if (ichan == AH_NULL) {
922 HALDEBUG(ah, HAL_DEBUG_NFCAL,
923 "%s: invalid channel %u/0x%x; no mapping\n",
924 __func__, chan->ic_freq, chan->ic_flags);
925 return 0;
926 }
927 if (ichan->rawNoiseFloor == 0) {
928 WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan);
929
930 HALASSERT(mode < WIRELESS_MODE_MAX);
931 return NOISE_FLOOR[mode] + ath_hal_getNfAdjust(ah, ichan);
932 } else
933 return ichan->rawNoiseFloor + ichan->noiseFloorAdjust;
934 }
935
936 /*
937 * Fetch the current setup of ctl/ext noise floor values.
938 *
939 * If the CHANNEL_MIMO_NF_VALID flag isn't set, the array is simply
940 * populated with values from NOISE_FLOOR[] + ath_hal_getNfAdjust().
941 *
942 * The caller must supply ctl/ext NF arrays which are at least
943 * AH_MIMO_MAX_CHAINS entries long.
944 */
945 int
ath_hal_get_mimo_chan_noise(struct ath_hal * ah,const struct ieee80211_channel * chan,int16_t * nf_ctl,int16_t * nf_ext)946 ath_hal_get_mimo_chan_noise(struct ath_hal *ah,
947 const struct ieee80211_channel *chan, int16_t *nf_ctl,
948 int16_t *nf_ext)
949 {
950 #ifdef AH_SUPPORT_AR5416
951 HAL_CHANNEL_INTERNAL *ichan;
952 int i;
953
954 ichan = ath_hal_checkchannel(ah, chan);
955 if (ichan == AH_NULL) {
956 HALDEBUG(ah, HAL_DEBUG_NFCAL,
957 "%s: invalid channel %u/0x%x; no mapping\n",
958 __func__, chan->ic_freq, chan->ic_flags);
959 for (i = 0; i < AH_MIMO_MAX_CHAINS; i++) {
960 nf_ctl[i] = nf_ext[i] = 0;
961 }
962 return 0;
963 }
964
965 /* Return 0 if there's no valid MIMO values (yet) */
966 if (! (ichan->privFlags & CHANNEL_MIMO_NF_VALID)) {
967 for (i = 0; i < AH_MIMO_MAX_CHAINS; i++) {
968 nf_ctl[i] = nf_ext[i] = 0;
969 }
970 return 0;
971 }
972 if (ichan->rawNoiseFloor == 0) {
973 WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan);
974 HALASSERT(mode < WIRELESS_MODE_MAX);
975 /*
976 * See the comment below - this could cause issues for
977 * stations which have a very low RSSI, below the
978 * 'normalised' NF values in NOISE_FLOOR[].
979 */
980 for (i = 0; i < AH_MIMO_MAX_CHAINS; i++) {
981 nf_ctl[i] = nf_ext[i] = NOISE_FLOOR[mode] +
982 ath_hal_getNfAdjust(ah, ichan);
983 }
984 return 1;
985 } else {
986 /*
987 * The value returned here from a MIMO radio is presumed to be
988 * "good enough" as a NF calculation. As RSSI values are calculated
989 * against this, an adjusted NF may be higher than the RSSI value
990 * returned from a vary weak station, resulting in an obscenely
991 * high signal strength calculation being returned.
992 *
993 * This should be re-evaluated at a later date, along with any
994 * signal strength calculations which are made. Quite likely the
995 * RSSI values will need to be adjusted to ensure the calculations
996 * don't "wrap" when RSSI is less than the "adjusted" NF value.
997 * ("Adjust" here is via ichan->noiseFloorAdjust.)
998 */
999 for (i = 0; i < AH_MIMO_MAX_CHAINS; i++) {
1000 nf_ctl[i] = ichan->noiseFloorCtl[i] + ath_hal_getNfAdjust(ah, ichan);
1001 nf_ext[i] = ichan->noiseFloorExt[i] + ath_hal_getNfAdjust(ah, ichan);
1002 }
1003 return 1;
1004 }
1005 #else
1006 return 0;
1007 #endif /* AH_SUPPORT_AR5416 */
1008 }
1009
1010 /*
1011 * Process all valid raw noise floors into the dBm noise floor values.
1012 * Though our device has no reference for a dBm noise floor, we perform
1013 * a relative minimization of NF's based on the lowest NF found across a
1014 * channel scan.
1015 */
1016 void
ath_hal_process_noisefloor(struct ath_hal * ah)1017 ath_hal_process_noisefloor(struct ath_hal *ah)
1018 {
1019 HAL_CHANNEL_INTERNAL *c;
1020 int16_t correct2, correct5;
1021 int16_t lowest2, lowest5;
1022 int i;
1023
1024 /*
1025 * Find the lowest 2GHz and 5GHz noise floor values after adjusting
1026 * for statistically recorded NF/channel deviation.
1027 */
1028 correct2 = lowest2 = 0;
1029 correct5 = lowest5 = 0;
1030 for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
1031 WIRELESS_MODE mode;
1032 int16_t nf;
1033
1034 c = &AH_PRIVATE(ah)->ah_channels[i];
1035 if (c->rawNoiseFloor >= 0)
1036 continue;
1037 /* XXX can't identify proper mode */
1038 mode = IS_CHAN_5GHZ(c) ? WIRELESS_MODE_11a : WIRELESS_MODE_11g;
1039 nf = c->rawNoiseFloor + NOISE_FLOOR[mode] +
1040 ath_hal_getNfAdjust(ah, c);
1041 if (IS_CHAN_5GHZ(c)) {
1042 if (nf < lowest5) {
1043 lowest5 = nf;
1044 correct5 = NOISE_FLOOR[mode] -
1045 (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
1046 }
1047 } else {
1048 if (nf < lowest2) {
1049 lowest2 = nf;
1050 correct2 = NOISE_FLOOR[mode] -
1051 (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
1052 }
1053 }
1054 }
1055
1056 /* Correct the channels to reach the expected NF value */
1057 for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
1058 c = &AH_PRIVATE(ah)->ah_channels[i];
1059 if (c->rawNoiseFloor >= 0)
1060 continue;
1061 /* Apply correction factor */
1062 c->noiseFloorAdjust = ath_hal_getNfAdjust(ah, c) +
1063 (IS_CHAN_5GHZ(c) ? correct5 : correct2);
1064 HALDEBUG(ah, HAL_DEBUG_NFCAL, "%u raw nf %d adjust %d\n",
1065 c->channel, c->rawNoiseFloor, c->noiseFloorAdjust);
1066 }
1067 }
1068
1069 /*
1070 * INI support routines.
1071 */
1072
1073 int
ath_hal_ini_write(struct ath_hal * ah,const HAL_INI_ARRAY * ia,int col,int regWr)1074 ath_hal_ini_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
1075 int col, int regWr)
1076 {
1077 int r;
1078
1079 HALASSERT(col < ia->cols);
1080 for (r = 0; r < ia->rows; r++) {
1081 OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0),
1082 HAL_INI_VAL(ia, r, col));
1083
1084 /* Analog shift register delay seems needed for Merlin - PR kern/154220 */
1085 if (HAL_INI_VAL(ia, r, 0) >= 0x7800 && HAL_INI_VAL(ia, r, 0) < 0x7900)
1086 OS_DELAY(100);
1087
1088 DMA_YIELD(regWr);
1089 }
1090 return regWr;
1091 }
1092
1093 void
ath_hal_ini_bank_setup(uint32_t data[],const HAL_INI_ARRAY * ia,int col)1094 ath_hal_ini_bank_setup(uint32_t data[], const HAL_INI_ARRAY *ia, int col)
1095 {
1096 int r;
1097
1098 HALASSERT(col < ia->cols);
1099 for (r = 0; r < ia->rows; r++)
1100 data[r] = HAL_INI_VAL(ia, r, col);
1101 }
1102
1103 int
ath_hal_ini_bank_write(struct ath_hal * ah,const HAL_INI_ARRAY * ia,const uint32_t data[],int regWr)1104 ath_hal_ini_bank_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
1105 const uint32_t data[], int regWr)
1106 {
1107 int r;
1108
1109 for (r = 0; r < ia->rows; r++) {
1110 OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0), data[r]);
1111 DMA_YIELD(regWr);
1112 }
1113 return regWr;
1114 }
1115
1116 /*
1117 * These are EEPROM board related routines which should likely live in
1118 * a helper library of some sort.
1119 */
1120
1121 /**************************************************************
1122 * ath_ee_getLowerUppderIndex
1123 *
1124 * Return indices surrounding the value in sorted integer lists.
1125 * Requirement: the input list must be monotonically increasing
1126 * and populated up to the list size
1127 * Returns: match is set if an index in the array matches exactly
1128 * or a the target is before or after the range of the array.
1129 */
1130 HAL_BOOL
ath_ee_getLowerUpperIndex(uint8_t target,uint8_t * pList,uint16_t listSize,uint16_t * indexL,uint16_t * indexR)1131 ath_ee_getLowerUpperIndex(uint8_t target, uint8_t *pList, uint16_t listSize,
1132 uint16_t *indexL, uint16_t *indexR)
1133 {
1134 uint16_t i;
1135
1136 /*
1137 * Check first and last elements for beyond ordered array cases.
1138 */
1139 if (target <= pList[0]) {
1140 *indexL = *indexR = 0;
1141 return AH_TRUE;
1142 }
1143 if (target >= pList[listSize-1]) {
1144 *indexL = *indexR = (uint16_t)(listSize - 1);
1145 return AH_TRUE;
1146 }
1147
1148 /* look for value being near or between 2 values in list */
1149 for (i = 0; i < listSize - 1; i++) {
1150 /*
1151 * If value is close to the current value of the list
1152 * then target is not between values, it is one of the values
1153 */
1154 if (pList[i] == target) {
1155 *indexL = *indexR = i;
1156 return AH_TRUE;
1157 }
1158 /*
1159 * Look for value being between current value and next value
1160 * if so return these 2 values
1161 */
1162 if (target < pList[i + 1]) {
1163 *indexL = i;
1164 *indexR = (uint16_t)(i + 1);
1165 return AH_FALSE;
1166 }
1167 }
1168 HALASSERT(0);
1169 *indexL = *indexR = 0;
1170 return AH_FALSE;
1171 }
1172
1173 /**************************************************************
1174 * ath_ee_FillVpdTable
1175 *
1176 * Fill the Vpdlist for indices Pmax-Pmin
1177 * Note: pwrMin, pwrMax and Vpdlist are all in dBm * 4
1178 */
1179 HAL_BOOL
ath_ee_FillVpdTable(uint8_t pwrMin,uint8_t pwrMax,uint8_t * pPwrList,uint8_t * pVpdList,uint16_t numIntercepts,uint8_t * pRetVpdList)1180 ath_ee_FillVpdTable(uint8_t pwrMin, uint8_t pwrMax, uint8_t *pPwrList,
1181 uint8_t *pVpdList, uint16_t numIntercepts, uint8_t *pRetVpdList)
1182 {
1183 uint16_t i, k;
1184 uint8_t currPwr = pwrMin;
1185 uint16_t idxL, idxR;
1186
1187 HALASSERT(pwrMax > pwrMin);
1188 for (i = 0; i <= (pwrMax - pwrMin) / 2; i++) {
1189 ath_ee_getLowerUpperIndex(currPwr, pPwrList, numIntercepts,
1190 &(idxL), &(idxR));
1191 if (idxR < 1)
1192 idxR = 1; /* extrapolate below */
1193 if (idxL == numIntercepts - 1)
1194 idxL = (uint16_t)(numIntercepts - 2); /* extrapolate above */
1195 if (pPwrList[idxL] == pPwrList[idxR])
1196 k = pVpdList[idxL];
1197 else
1198 k = (uint16_t)( ((currPwr - pPwrList[idxL]) * pVpdList[idxR] + (pPwrList[idxR] - currPwr) * pVpdList[idxL]) /
1199 (pPwrList[idxR] - pPwrList[idxL]) );
1200 HALASSERT(k < 256);
1201 pRetVpdList[i] = (uint8_t)k;
1202 currPwr += 2; /* half dB steps */
1203 }
1204
1205 return AH_TRUE;
1206 }
1207
1208 /**************************************************************************
1209 * ath_ee_interpolate
1210 *
1211 * Returns signed interpolated or the scaled up interpolated value
1212 */
1213 int16_t
ath_ee_interpolate(uint16_t target,uint16_t srcLeft,uint16_t srcRight,int16_t targetLeft,int16_t targetRight)1214 ath_ee_interpolate(uint16_t target, uint16_t srcLeft, uint16_t srcRight,
1215 int16_t targetLeft, int16_t targetRight)
1216 {
1217 int16_t rv;
1218
1219 if (srcRight == srcLeft) {
1220 rv = targetLeft;
1221 } else {
1222 rv = (int16_t)( ((target - srcLeft) * targetRight +
1223 (srcRight - target) * targetLeft) / (srcRight - srcLeft) );
1224 }
1225 return rv;
1226 }
1227
1228 /*
1229 * Adjust the TSF.
1230 */
1231 void
ath_hal_adjusttsf(struct ath_hal * ah,int32_t tsfdelta)1232 ath_hal_adjusttsf(struct ath_hal *ah, int32_t tsfdelta)
1233 {
1234 /* XXX handle wrap/overflow */
1235 OS_REG_WRITE(ah, AR_TSF_L32, OS_REG_READ(ah, AR_TSF_L32) + tsfdelta);
1236 }
1237
1238 /*
1239 * Enable or disable CCA.
1240 */
1241 void
ath_hal_setcca(struct ath_hal * ah,int ena)1242 ath_hal_setcca(struct ath_hal *ah, int ena)
1243 {
1244 /*
1245 * NB: fill me in; this is not provided by default because disabling
1246 * CCA in most locales violates regulatory.
1247 */
1248 }
1249
1250 /*
1251 * Get CCA setting.
1252 */
1253 int
ath_hal_getcca(struct ath_hal * ah)1254 ath_hal_getcca(struct ath_hal *ah)
1255 {
1256 u_int32_t diag;
1257 if (ath_hal_getcapability(ah, HAL_CAP_DIAG, 0, &diag) != HAL_OK)
1258 return 1;
1259 return ((diag & 0x500000) == 0);
1260 }
1261