1 /*-
2 * SPDX-License-Identifier: ISC
3 *
4 * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
5 * Copyright (c) 2002-2008 Atheros Communications, Inc.
6 *
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
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 #include "ar9003/ar9300_devid.h"
28
29 /* linker set of registered chips */
30 OS_SET_DECLARE(ah_chips, struct ath_hal_chip);
31 TAILQ_HEAD(, ath_hal_chip) ah_chip_list = TAILQ_HEAD_INITIALIZER(ah_chip_list);
32
33 int
ath_hal_add_chip(struct ath_hal_chip * ahc)34 ath_hal_add_chip(struct ath_hal_chip *ahc)
35 {
36
37 TAILQ_INSERT_TAIL(&ah_chip_list, ahc, node);
38 return (0);
39 }
40
41 int
ath_hal_remove_chip(struct ath_hal_chip * ahc)42 ath_hal_remove_chip(struct ath_hal_chip *ahc)
43 {
44
45 TAILQ_REMOVE(&ah_chip_list, ahc, node);
46 return (0);
47 }
48
49 /*
50 * Check the set of registered chips to see if any recognize
51 * the device as one they can support.
52 */
53 const char*
ath_hal_probe(uint16_t vendorid,uint16_t devid)54 ath_hal_probe(uint16_t vendorid, uint16_t devid)
55 {
56 struct ath_hal_chip * const *pchip;
57 struct ath_hal_chip *pc;
58
59 /* Linker set */
60 OS_SET_FOREACH(pchip, ah_chips) {
61 const char *name = (*pchip)->probe(vendorid, devid);
62 if (name != AH_NULL)
63 return name;
64 }
65
66 /* List */
67 TAILQ_FOREACH(pc, &ah_chip_list, node) {
68 const char *name = pc->probe(vendorid, devid);
69 if (name != AH_NULL)
70 return name;
71 }
72
73 return AH_NULL;
74 }
75
76 /*
77 * Attach detects device chip revisions, initializes the hwLayer
78 * function list, reads EEPROM information,
79 * selects reset vectors, and performs a short self test.
80 * Any failures will return an error that should cause a hardware
81 * disable.
82 */
83 struct ath_hal*
ath_hal_attach(uint16_t devid,HAL_SOFTC sc,HAL_BUS_TAG st,HAL_BUS_HANDLE sh,uint16_t * eepromdata,HAL_OPS_CONFIG * ah_config,HAL_STATUS * error)84 ath_hal_attach(uint16_t devid, HAL_SOFTC sc,
85 HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata,
86 HAL_OPS_CONFIG *ah_config,
87 HAL_STATUS *error)
88 {
89 struct ath_hal_chip * const *pchip;
90 struct ath_hal_chip *pc;
91
92 OS_SET_FOREACH(pchip, ah_chips) {
93 struct ath_hal_chip *chip = *pchip;
94 struct ath_hal *ah;
95
96 /* XXX don't have vendorid, assume atheros one works */
97 if (chip->probe(ATHEROS_VENDOR_ID, devid) == AH_NULL)
98 continue;
99 ah = chip->attach(devid, sc, st, sh, eepromdata, ah_config,
100 error);
101 if (ah != AH_NULL) {
102 /* copy back private state to public area */
103 ah->ah_devid = AH_PRIVATE(ah)->ah_devid;
104 ah->ah_subvendorid = AH_PRIVATE(ah)->ah_subvendorid;
105 ah->ah_macVersion = AH_PRIVATE(ah)->ah_macVersion;
106 ah->ah_macRev = AH_PRIVATE(ah)->ah_macRev;
107 ah->ah_phyRev = AH_PRIVATE(ah)->ah_phyRev;
108 ah->ah_analog5GhzRev = AH_PRIVATE(ah)->ah_analog5GhzRev;
109 ah->ah_analog2GhzRev = AH_PRIVATE(ah)->ah_analog2GhzRev;
110 return ah;
111 }
112 }
113
114 /* List */
115 TAILQ_FOREACH(pc, &ah_chip_list, node) {
116 struct ath_hal_chip *chip = pc;
117 struct ath_hal *ah;
118
119 /* XXX don't have vendorid, assume atheros one works */
120 if (chip->probe(ATHEROS_VENDOR_ID, devid) == AH_NULL)
121 continue;
122 ah = chip->attach(devid, sc, st, sh, eepromdata, ah_config,
123 error);
124 if (ah != AH_NULL) {
125 /* copy back private state to public area */
126 ah->ah_devid = AH_PRIVATE(ah)->ah_devid;
127 ah->ah_subvendorid = AH_PRIVATE(ah)->ah_subvendorid;
128 ah->ah_macVersion = AH_PRIVATE(ah)->ah_macVersion;
129 ah->ah_macRev = AH_PRIVATE(ah)->ah_macRev;
130 ah->ah_phyRev = AH_PRIVATE(ah)->ah_phyRev;
131 ah->ah_analog5GhzRev = AH_PRIVATE(ah)->ah_analog5GhzRev;
132 ah->ah_analog2GhzRev = AH_PRIVATE(ah)->ah_analog2GhzRev;
133 return ah;
134 }
135 }
136
137 return AH_NULL;
138 }
139
140 const char *
ath_hal_mac_name(struct ath_hal * ah)141 ath_hal_mac_name(struct ath_hal *ah)
142 {
143 switch (ah->ah_macVersion) {
144 case AR_SREV_VERSION_CRETE:
145 case AR_SREV_VERSION_MAUI_1:
146 return "AR5210";
147 case AR_SREV_VERSION_MAUI_2:
148 case AR_SREV_VERSION_OAHU:
149 return "AR5211";
150 case AR_SREV_VERSION_VENICE:
151 return "AR5212";
152 case AR_SREV_VERSION_GRIFFIN:
153 return "AR2413";
154 case AR_SREV_VERSION_CONDOR:
155 return "AR5424";
156 case AR_SREV_VERSION_EAGLE:
157 return "AR5413";
158 case AR_SREV_VERSION_COBRA:
159 return "AR2415";
160 case AR_SREV_2425: /* Swan */
161 return "AR2425";
162 case AR_SREV_2417: /* Nala */
163 return "AR2417";
164 case AR_XSREV_VERSION_OWL_PCI:
165 return "AR5416";
166 case AR_XSREV_VERSION_OWL_PCIE:
167 return "AR5418";
168 case AR_XSREV_VERSION_HOWL:
169 return "AR9130";
170 case AR_XSREV_VERSION_SOWL:
171 return "AR9160";
172 case AR_XSREV_VERSION_MERLIN:
173 if (AH_PRIVATE(ah)->ah_ispcie)
174 return "AR9280";
175 return "AR9220";
176 case AR_XSREV_VERSION_KITE:
177 return "AR9285";
178 case AR_XSREV_VERSION_KIWI:
179 if (AH_PRIVATE(ah)->ah_ispcie)
180 return "AR9287";
181 return "AR9227";
182 case AR_SREV_VERSION_AR9380:
183 if (ah->ah_macRev >= AR_SREV_REVISION_AR9580_10)
184 return "AR9580";
185 return "AR9380";
186 case AR_SREV_VERSION_AR9460:
187 return "AR9460";
188 case AR_SREV_VERSION_AR9330:
189 return "AR9330";
190 case AR_SREV_VERSION_AR9340:
191 return "AR9340";
192 case AR_SREV_VERSION_QCA9550:
193 return "QCA9550";
194 case AR_SREV_VERSION_AR9485:
195 return "AR9485";
196 case AR_SREV_VERSION_QCA9565:
197 return "QCA9565";
198 case AR_SREV_VERSION_QCA9530:
199 return "QCA9530";
200 }
201 return "????";
202 }
203
204 /*
205 * Return the mask of available modes based on the hardware capabilities.
206 */
207 u_int
ath_hal_getwirelessmodes(struct ath_hal * ah)208 ath_hal_getwirelessmodes(struct ath_hal*ah)
209 {
210 return ath_hal_getWirelessModes(ah);
211 }
212
213 /* linker set of registered RF backends */
214 OS_SET_DECLARE(ah_rfs, struct ath_hal_rf);
215 TAILQ_HEAD(, ath_hal_rf) ah_rf_list = TAILQ_HEAD_INITIALIZER(ah_rf_list);
216
217 int
ath_hal_add_rf(struct ath_hal_rf * arf)218 ath_hal_add_rf(struct ath_hal_rf *arf)
219 {
220
221 TAILQ_INSERT_TAIL(&ah_rf_list, arf, node);
222 return (0);
223 }
224
225 int
ath_hal_remove_rf(struct ath_hal_rf * arf)226 ath_hal_remove_rf(struct ath_hal_rf *arf)
227 {
228
229 TAILQ_REMOVE(&ah_rf_list, arf, node);
230 return (0);
231 }
232
233 /*
234 * Check the set of registered RF backends to see if
235 * any recognize the device as one they can support.
236 */
237 struct ath_hal_rf *
ath_hal_rfprobe(struct ath_hal * ah,HAL_STATUS * ecode)238 ath_hal_rfprobe(struct ath_hal *ah, HAL_STATUS *ecode)
239 {
240 struct ath_hal_rf * const *prf;
241 struct ath_hal_rf * rf;
242
243 OS_SET_FOREACH(prf, ah_rfs) {
244 struct ath_hal_rf *rf = *prf;
245 if (rf->probe(ah))
246 return rf;
247 }
248
249 TAILQ_FOREACH(rf, &ah_rf_list, node) {
250 if (rf->probe(ah))
251 return rf;
252 }
253 *ecode = HAL_ENOTSUPP;
254 return AH_NULL;
255 }
256
257 const char *
ath_hal_rf_name(struct ath_hal * ah)258 ath_hal_rf_name(struct ath_hal *ah)
259 {
260 switch (ah->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) {
261 case 0: /* 5210 */
262 return "5110"; /* NB: made up */
263 case AR_RAD5111_SREV_MAJOR:
264 case AR_RAD5111_SREV_PROD:
265 return "5111";
266 case AR_RAD2111_SREV_MAJOR:
267 return "2111";
268 case AR_RAD5112_SREV_MAJOR:
269 case AR_RAD5112_SREV_2_0:
270 case AR_RAD5112_SREV_2_1:
271 return "5112";
272 case AR_RAD2112_SREV_MAJOR:
273 case AR_RAD2112_SREV_2_0:
274 case AR_RAD2112_SREV_2_1:
275 return "2112";
276 case AR_RAD2413_SREV_MAJOR:
277 return "2413";
278 case AR_RAD5413_SREV_MAJOR:
279 return "5413";
280 case AR_RAD2316_SREV_MAJOR:
281 return "2316";
282 case AR_RAD2317_SREV_MAJOR:
283 return "2317";
284 case AR_RAD5424_SREV_MAJOR:
285 return "5424";
286
287 case AR_RAD5133_SREV_MAJOR:
288 return "5133";
289 case AR_RAD2133_SREV_MAJOR:
290 return "2133";
291 case AR_RAD5122_SREV_MAJOR:
292 return "5122";
293 case AR_RAD2122_SREV_MAJOR:
294 return "2122";
295 }
296 return "????";
297 }
298
299 /*
300 * Poll the register looking for a specific value.
301 */
302 HAL_BOOL
ath_hal_wait(struct ath_hal * ah,u_int reg,uint32_t mask,uint32_t val)303 ath_hal_wait(struct ath_hal *ah, u_int reg, uint32_t mask, uint32_t val)
304 {
305 #define AH_TIMEOUT 5000
306 return ath_hal_waitfor(ah, reg, mask, val, AH_TIMEOUT);
307 #undef AH_TIMEOUT
308 }
309
310 HAL_BOOL
ath_hal_waitfor(struct ath_hal * ah,u_int reg,uint32_t mask,uint32_t val,uint32_t timeout)311 ath_hal_waitfor(struct ath_hal *ah, u_int reg, uint32_t mask, uint32_t val, uint32_t timeout)
312 {
313 int i;
314
315 for (i = 0; i < timeout; i++) {
316 if ((OS_REG_READ(ah, reg) & mask) == val)
317 return AH_TRUE;
318 OS_DELAY(10);
319 }
320 HALDEBUG(ah, HAL_DEBUG_REGIO | HAL_DEBUG_PHYIO,
321 "%s: timeout on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n",
322 __func__, reg, OS_REG_READ(ah, reg), mask, val);
323 return AH_FALSE;
324 }
325
326 /*
327 * Reverse the bits starting at the low bit for a value of
328 * bit_count in size
329 */
330 uint32_t
ath_hal_reverseBits(uint32_t val,uint32_t n)331 ath_hal_reverseBits(uint32_t val, uint32_t n)
332 {
333 uint32_t retval;
334 int i;
335
336 for (i = 0, retval = 0; i < n; i++) {
337 retval = (retval << 1) | (val & 1);
338 val >>= 1;
339 }
340 return retval;
341 }
342
343 /* 802.11n related timing definitions */
344
345 #define OFDM_PLCP_BITS 22
346 #define HT_L_STF 8
347 #define HT_L_LTF 8
348 #define HT_L_SIG 4
349 #define HT_SIG 8
350 #define HT_STF 4
351 #define HT_LTF(n) ((n) * 4)
352
353 #define HT_RC_2_MCS(_rc) ((_rc) & 0x1f)
354 #define HT_RC_2_STREAMS(_rc) ((((_rc) & 0x78) >> 3) + 1)
355 #define IS_HT_RATE(_rc) ( (_rc) & IEEE80211_RATE_MCS)
356
357 /*
358 * Calculate the duration of a packet whether it is 11n or legacy.
359 */
360 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,HAL_BOOL includeSifs)361 ath_hal_pkt_txtime(struct ath_hal *ah, const HAL_RATE_TABLE *rates, uint32_t frameLen,
362 uint16_t rateix, HAL_BOOL isht40, HAL_BOOL shortPreamble,
363 HAL_BOOL includeSifs)
364 {
365 uint8_t rc;
366 int numStreams;
367
368 rc = rates->info[rateix].rateCode;
369
370 /* Legacy rate? Return the old way */
371 if (! IS_HT_RATE(rc))
372 return ath_hal_computetxtime(ah, rates, frameLen, rateix,
373 shortPreamble, includeSifs);
374
375 /* 11n frame - extract out the number of spatial streams */
376 numStreams = HT_RC_2_STREAMS(rc);
377 KASSERT(numStreams > 0 && numStreams <= 4,
378 ("number of spatial streams needs to be 1..3: MCS rate 0x%x!",
379 rateix));
380
381 /* XXX TODO: Add SIFS */
382 return ath_computedur_ht(frameLen, rc, numStreams, isht40,
383 shortPreamble);
384 }
385
386 static const uint16_t ht20_bps[32] = {
387 26, 52, 78, 104, 156, 208, 234, 260,
388 52, 104, 156, 208, 312, 416, 468, 520,
389 78, 156, 234, 312, 468, 624, 702, 780,
390 104, 208, 312, 416, 624, 832, 936, 1040
391 };
392 static const uint16_t ht40_bps[32] = {
393 54, 108, 162, 216, 324, 432, 486, 540,
394 108, 216, 324, 432, 648, 864, 972, 1080,
395 162, 324, 486, 648, 972, 1296, 1458, 1620,
396 216, 432, 648, 864, 1296, 1728, 1944, 2160
397 };
398
399 /*
400 * Calculate the transmit duration of an 11n frame.
401 */
402 uint32_t
ath_computedur_ht(uint32_t frameLen,uint16_t rate,int streams,HAL_BOOL isht40,HAL_BOOL isShortGI)403 ath_computedur_ht(uint32_t frameLen, uint16_t rate, int streams,
404 HAL_BOOL isht40, HAL_BOOL isShortGI)
405 {
406 uint32_t bitsPerSymbol, numBits, numSymbols, txTime;
407
408 KASSERT(rate & IEEE80211_RATE_MCS, ("not mcs %d", rate));
409 KASSERT((rate &~ IEEE80211_RATE_MCS) < 31, ("bad mcs 0x%x", rate));
410
411 if (isht40)
412 bitsPerSymbol = ht40_bps[HT_RC_2_MCS(rate)];
413 else
414 bitsPerSymbol = ht20_bps[HT_RC_2_MCS(rate)];
415 numBits = OFDM_PLCP_BITS + (frameLen << 3);
416 numSymbols = howmany(numBits, bitsPerSymbol);
417 if (isShortGI)
418 txTime = ((numSymbols * 18) + 4) / 5; /* 3.6us */
419 else
420 txTime = numSymbols * 4; /* 4us */
421 return txTime + HT_L_STF + HT_L_LTF +
422 HT_L_SIG + HT_SIG + HT_STF + HT_LTF(streams);
423 }
424
425 /*
426 * Compute the time to transmit a frame of length frameLen bytes
427 * using the specified rate, phy, and short preamble setting.
428 */
429 uint16_t
ath_hal_computetxtime(struct ath_hal * ah,const HAL_RATE_TABLE * rates,uint32_t frameLen,uint16_t rateix,HAL_BOOL shortPreamble,HAL_BOOL includeSifs)430 ath_hal_computetxtime(struct ath_hal *ah,
431 const HAL_RATE_TABLE *rates, uint32_t frameLen, uint16_t rateix,
432 HAL_BOOL shortPreamble, HAL_BOOL includeSifs)
433 {
434 uint32_t bitsPerSymbol, numBits, numSymbols, phyTime, txTime;
435 uint32_t kbps;
436
437 /* Warn if this function is called for 11n rates; it should not be! */
438 if (IS_HT_RATE(rates->info[rateix].rateCode))
439 ath_hal_printf(ah, "%s: MCS rate? (index %d; hwrate 0x%x)\n",
440 __func__, rateix, rates->info[rateix].rateCode);
441
442 kbps = rates->info[rateix].rateKbps;
443 /*
444 * index can be invalid during dynamic Turbo transitions.
445 * XXX
446 */
447 if (kbps == 0)
448 return 0;
449 switch (rates->info[rateix].phy) {
450 case IEEE80211_T_CCK:
451 phyTime = CCK_PREAMBLE_BITS + CCK_PLCP_BITS;
452 if (shortPreamble && rates->info[rateix].shortPreamble)
453 phyTime >>= 1;
454 numBits = frameLen << 3;
455 txTime = phyTime
456 + ((numBits * 1000)/kbps);
457 if (includeSifs)
458 txTime += CCK_SIFS_TIME;
459 break;
460 case IEEE80211_T_OFDM:
461 bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME) / 1000;
462 HALASSERT(bitsPerSymbol != 0);
463
464 numBits = OFDM_PLCP_BITS + (frameLen << 3);
465 numSymbols = howmany(numBits, bitsPerSymbol);
466 txTime = OFDM_PREAMBLE_TIME
467 + (numSymbols * OFDM_SYMBOL_TIME);
468 if (includeSifs)
469 txTime += OFDM_SIFS_TIME;
470 break;
471 case IEEE80211_T_OFDM_HALF:
472 bitsPerSymbol = (kbps * OFDM_HALF_SYMBOL_TIME) / 1000;
473 HALASSERT(bitsPerSymbol != 0);
474
475 numBits = OFDM_HALF_PLCP_BITS + (frameLen << 3);
476 numSymbols = howmany(numBits, bitsPerSymbol);
477 txTime = OFDM_HALF_PREAMBLE_TIME
478 + (numSymbols * OFDM_HALF_SYMBOL_TIME);
479 if (includeSifs)
480 txTime += OFDM_HALF_SIFS_TIME;
481 break;
482 case IEEE80211_T_OFDM_QUARTER:
483 bitsPerSymbol = (kbps * OFDM_QUARTER_SYMBOL_TIME) / 1000;
484 HALASSERT(bitsPerSymbol != 0);
485
486 numBits = OFDM_QUARTER_PLCP_BITS + (frameLen << 3);
487 numSymbols = howmany(numBits, bitsPerSymbol);
488 txTime = OFDM_QUARTER_PREAMBLE_TIME
489 + (numSymbols * OFDM_QUARTER_SYMBOL_TIME);
490 if (includeSifs)
491 txTime += OFDM_QUARTER_SIFS_TIME;
492 break;
493 case IEEE80211_T_TURBO:
494 bitsPerSymbol = (kbps * TURBO_SYMBOL_TIME) / 1000;
495 HALASSERT(bitsPerSymbol != 0);
496
497 numBits = TURBO_PLCP_BITS + (frameLen << 3);
498 numSymbols = howmany(numBits, bitsPerSymbol);
499 txTime = TURBO_PREAMBLE_TIME
500 + (numSymbols * TURBO_SYMBOL_TIME);
501 if (includeSifs)
502 txTime += TURBO_SIFS_TIME;
503 break;
504 default:
505 HALDEBUG(ah, HAL_DEBUG_PHYIO,
506 "%s: unknown phy %u (rate ix %u)\n",
507 __func__, rates->info[rateix].phy, rateix);
508 txTime = 0;
509 break;
510 }
511 return txTime;
512 }
513
514 int
ath_hal_get_curmode(struct ath_hal * ah,const struct ieee80211_channel * chan)515 ath_hal_get_curmode(struct ath_hal *ah, const struct ieee80211_channel *chan)
516 {
517 /*
518 * Pick a default mode at bootup. A channel change is inevitable.
519 */
520 if (!chan)
521 return HAL_MODE_11NG_HT20;
522
523 if (IEEE80211_IS_CHAN_TURBO(chan))
524 return HAL_MODE_TURBO;
525
526 /* check for NA_HT before plain A, since IS_CHAN_A includes NA_HT */
527 if (IEEE80211_IS_CHAN_5GHZ(chan) && IEEE80211_IS_CHAN_HT20(chan))
528 return HAL_MODE_11NA_HT20;
529 if (IEEE80211_IS_CHAN_5GHZ(chan) && IEEE80211_IS_CHAN_HT40U(chan))
530 return HAL_MODE_11NA_HT40PLUS;
531 if (IEEE80211_IS_CHAN_5GHZ(chan) && IEEE80211_IS_CHAN_HT40D(chan))
532 return HAL_MODE_11NA_HT40MINUS;
533 if (IEEE80211_IS_CHAN_A(chan))
534 return HAL_MODE_11A;
535
536 /* check for NG_HT before plain G, since IS_CHAN_G includes NG_HT */
537 if (IEEE80211_IS_CHAN_2GHZ(chan) && IEEE80211_IS_CHAN_HT20(chan))
538 return HAL_MODE_11NG_HT20;
539 if (IEEE80211_IS_CHAN_2GHZ(chan) && IEEE80211_IS_CHAN_HT40U(chan))
540 return HAL_MODE_11NG_HT40PLUS;
541 if (IEEE80211_IS_CHAN_2GHZ(chan) && IEEE80211_IS_CHAN_HT40D(chan))
542 return HAL_MODE_11NG_HT40MINUS;
543
544 /*
545 * XXX For FreeBSD, will this work correctly given the DYN
546 * chan mode (OFDM+CCK dynamic) ? We have pure-G versions DYN-BG..
547 */
548 if (IEEE80211_IS_CHAN_G(chan))
549 return HAL_MODE_11G;
550 if (IEEE80211_IS_CHAN_B(chan))
551 return HAL_MODE_11B;
552
553 HALASSERT(0);
554 return HAL_MODE_11NG_HT20;
555 }
556
557 typedef enum {
558 WIRELESS_MODE_11a = 0,
559 WIRELESS_MODE_TURBO = 1,
560 WIRELESS_MODE_11b = 2,
561 WIRELESS_MODE_11g = 3,
562 WIRELESS_MODE_108g = 4,
563
564 WIRELESS_MODE_MAX
565 } WIRELESS_MODE;
566
567 /*
568 * XXX TODO: for some (?) chips, an 11b mode still runs at 11bg.
569 * Maybe AR5211 has separate 11b and 11g only modes, so 11b is 22MHz
570 * and 11g is 44MHz, but AR5416 and later run 11b in 11bg mode, right?
571 */
572 static WIRELESS_MODE
ath_hal_chan2wmode(struct ath_hal * ah,const struct ieee80211_channel * chan)573 ath_hal_chan2wmode(struct ath_hal *ah, const struct ieee80211_channel *chan)
574 {
575 if (IEEE80211_IS_CHAN_B(chan))
576 return WIRELESS_MODE_11b;
577 if (IEEE80211_IS_CHAN_G(chan))
578 return WIRELESS_MODE_11g;
579 if (IEEE80211_IS_CHAN_108G(chan))
580 return WIRELESS_MODE_108g;
581 if (IEEE80211_IS_CHAN_TURBO(chan))
582 return WIRELESS_MODE_TURBO;
583 return WIRELESS_MODE_11a;
584 }
585
586 /*
587 * Convert between microseconds and core system clocks.
588 */
589 /* 11a Turbo 11b 11g 108g */
590 static const uint8_t CLOCK_RATE[] = { 40, 80, 22, 44, 88 };
591
592 #define CLOCK_FAST_RATE_5GHZ_OFDM 44
593
594 u_int
ath_hal_mac_clks(struct ath_hal * ah,u_int usecs)595 ath_hal_mac_clks(struct ath_hal *ah, u_int usecs)
596 {
597 const struct ieee80211_channel *c = AH_PRIVATE(ah)->ah_curchan;
598 u_int clks;
599
600 /* NB: ah_curchan may be null when called attach time */
601 /* XXX merlin and later specific workaround - 5ghz fast clock is 44 */
602 if (c != AH_NULL && IS_5GHZ_FAST_CLOCK_EN(ah, c)) {
603 clks = usecs * CLOCK_FAST_RATE_5GHZ_OFDM;
604 if (IEEE80211_IS_CHAN_HT40(c))
605 clks <<= 1;
606 } else if (c != AH_NULL) {
607 clks = usecs * CLOCK_RATE[ath_hal_chan2wmode(ah, c)];
608 if (IEEE80211_IS_CHAN_HT40(c))
609 clks <<= 1;
610 } else
611 clks = usecs * CLOCK_RATE[WIRELESS_MODE_11b];
612
613 /* Compensate for half/quarter rate */
614 if (c != AH_NULL && IEEE80211_IS_CHAN_HALF(c))
615 clks = clks / 2;
616 else if (c != AH_NULL && IEEE80211_IS_CHAN_QUARTER(c))
617 clks = clks / 4;
618
619 return clks;
620 }
621
622 u_int
ath_hal_mac_usec(struct ath_hal * ah,u_int clks)623 ath_hal_mac_usec(struct ath_hal *ah, u_int clks)
624 {
625 uint64_t psec;
626
627 psec = ath_hal_mac_psec(ah, clks);
628 return (psec / 1000000);
629 }
630
631 /*
632 * XXX TODO: half, quarter rates.
633 */
634 uint64_t
ath_hal_mac_psec(struct ath_hal * ah,u_int clks)635 ath_hal_mac_psec(struct ath_hal *ah, u_int clks)
636 {
637 const struct ieee80211_channel *c = AH_PRIVATE(ah)->ah_curchan;
638 uint64_t psec;
639
640 /* NB: ah_curchan may be null when called attach time */
641 /* XXX merlin and later specific workaround - 5ghz fast clock is 44 */
642 if (c != AH_NULL && IS_5GHZ_FAST_CLOCK_EN(ah, c)) {
643 psec = (clks * 1000000ULL) / CLOCK_FAST_RATE_5GHZ_OFDM;
644 if (IEEE80211_IS_CHAN_HT40(c))
645 psec >>= 1;
646 } else if (c != AH_NULL) {
647 psec = (clks * 1000000ULL) / CLOCK_RATE[ath_hal_chan2wmode(ah, c)];
648 if (IEEE80211_IS_CHAN_HT40(c))
649 psec >>= 1;
650 } else
651 psec = (clks * 1000000ULL) / CLOCK_RATE[WIRELESS_MODE_11b];
652 return psec;
653 }
654
655 /*
656 * Setup a h/w rate table's reverse lookup table and
657 * fill in ack durations. This routine is called for
658 * each rate table returned through the ah_getRateTable
659 * method. The reverse lookup tables are assumed to be
660 * initialized to zero (or at least the first entry).
661 * We use this as a key that indicates whether or not
662 * we've previously setup the reverse lookup table.
663 *
664 * XXX not reentrant, but shouldn't matter
665 */
666 void
ath_hal_setupratetable(struct ath_hal * ah,HAL_RATE_TABLE * rt)667 ath_hal_setupratetable(struct ath_hal *ah, HAL_RATE_TABLE *rt)
668 {
669 #define N(a) (sizeof(a)/sizeof(a[0]))
670 int i;
671
672 if (rt->rateCodeToIndex[0] != 0) /* already setup */
673 return;
674 for (i = 0; i < N(rt->rateCodeToIndex); i++)
675 rt->rateCodeToIndex[i] = (uint8_t) -1;
676 for (i = 0; i < rt->rateCount; i++) {
677 uint8_t code = rt->info[i].rateCode;
678 uint8_t cix = rt->info[i].controlRate;
679
680 HALASSERT(code < N(rt->rateCodeToIndex));
681 rt->rateCodeToIndex[code] = i;
682 HALASSERT((code | rt->info[i].shortPreamble) <
683 N(rt->rateCodeToIndex));
684 rt->rateCodeToIndex[code | rt->info[i].shortPreamble] = i;
685 /*
686 * XXX for 11g the control rate to use for 5.5 and 11 Mb/s
687 * depends on whether they are marked as basic rates;
688 * the static tables are setup with an 11b-compatible
689 * 2Mb/s rate which will work but is suboptimal
690 */
691 rt->info[i].lpAckDuration = ath_hal_computetxtime(ah, rt,
692 WLAN_CTRL_FRAME_SIZE, cix, AH_FALSE, AH_TRUE);
693 rt->info[i].spAckDuration = ath_hal_computetxtime(ah, rt,
694 WLAN_CTRL_FRAME_SIZE, cix, AH_TRUE, AH_TRUE);
695 }
696 #undef N
697 }
698
699 HAL_STATUS
ath_hal_getcapability(struct ath_hal * ah,HAL_CAPABILITY_TYPE type,uint32_t capability,uint32_t * result)700 ath_hal_getcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
701 uint32_t capability, uint32_t *result)
702 {
703 const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
704
705 switch (type) {
706 case HAL_CAP_REG_DMN: /* regulatory domain */
707 *result = AH_PRIVATE(ah)->ah_currentRD;
708 return HAL_OK;
709 case HAL_CAP_DFS_DMN: /* DFS Domain */
710 *result = AH_PRIVATE(ah)->ah_dfsDomain;
711 return HAL_OK;
712 case HAL_CAP_CIPHER: /* cipher handled in hardware */
713 case HAL_CAP_TKIP_MIC: /* handle TKIP MIC in hardware */
714 return HAL_ENOTSUPP;
715 case HAL_CAP_TKIP_SPLIT: /* hardware TKIP uses split keys */
716 return HAL_ENOTSUPP;
717 case HAL_CAP_PHYCOUNTERS: /* hardware PHY error counters */
718 return pCap->halHwPhyCounterSupport ? HAL_OK : HAL_ENXIO;
719 case HAL_CAP_WME_TKIPMIC: /* hardware can do TKIP MIC when WMM is turned on */
720 return HAL_ENOTSUPP;
721 case HAL_CAP_DIVERSITY: /* hardware supports fast diversity */
722 return HAL_ENOTSUPP;
723 case HAL_CAP_KEYCACHE_SIZE: /* hardware key cache size */
724 *result = pCap->halKeyCacheSize;
725 return HAL_OK;
726 case HAL_CAP_NUM_TXQUEUES: /* number of hardware tx queues */
727 *result = pCap->halTotalQueues;
728 return HAL_OK;
729 case HAL_CAP_VEOL: /* hardware supports virtual EOL */
730 return pCap->halVEOLSupport ? HAL_OK : HAL_ENOTSUPP;
731 case HAL_CAP_PSPOLL: /* hardware PS-Poll support works */
732 return pCap->halPSPollBroken ? HAL_ENOTSUPP : HAL_OK;
733 case HAL_CAP_COMPRESSION:
734 return pCap->halCompressSupport ? HAL_OK : HAL_ENOTSUPP;
735 case HAL_CAP_BURST:
736 return pCap->halBurstSupport ? HAL_OK : HAL_ENOTSUPP;
737 case HAL_CAP_FASTFRAME:
738 return pCap->halFastFramesSupport ? HAL_OK : HAL_ENOTSUPP;
739 case HAL_CAP_DIAG: /* hardware diagnostic support */
740 *result = AH_PRIVATE(ah)->ah_diagreg;
741 return HAL_OK;
742 case HAL_CAP_TXPOW: /* global tx power limit */
743 switch (capability) {
744 case 0: /* facility is supported */
745 return HAL_OK;
746 case 1: /* current limit */
747 *result = AH_PRIVATE(ah)->ah_powerLimit;
748 return HAL_OK;
749 case 2: /* current max tx power */
750 *result = AH_PRIVATE(ah)->ah_maxPowerLevel;
751 return HAL_OK;
752 case 3: /* scale factor */
753 *result = AH_PRIVATE(ah)->ah_tpScale;
754 return HAL_OK;
755 }
756 return HAL_ENOTSUPP;
757 case HAL_CAP_BSSIDMASK: /* hardware supports bssid mask */
758 return pCap->halBssIdMaskSupport ? HAL_OK : HAL_ENOTSUPP;
759 case HAL_CAP_MCAST_KEYSRCH: /* multicast frame keycache search */
760 return pCap->halMcastKeySrchSupport ? HAL_OK : HAL_ENOTSUPP;
761 case HAL_CAP_TSF_ADJUST: /* hardware has beacon tsf adjust */
762 return HAL_ENOTSUPP;
763 case HAL_CAP_RFSILENT: /* rfsilent support */
764 switch (capability) {
765 case 0: /* facility is supported */
766 return pCap->halRfSilentSupport ? HAL_OK : HAL_ENOTSUPP;
767 case 1: /* current setting */
768 return AH_PRIVATE(ah)->ah_rfkillEnabled ?
769 HAL_OK : HAL_ENOTSUPP;
770 case 2: /* rfsilent config */
771 *result = AH_PRIVATE(ah)->ah_rfsilent;
772 return HAL_OK;
773 }
774 return HAL_ENOTSUPP;
775 case HAL_CAP_11D:
776 return HAL_OK;
777
778 case HAL_CAP_HT:
779 return pCap->halHTSupport ? HAL_OK : HAL_ENOTSUPP;
780 case HAL_CAP_GTXTO:
781 return pCap->halGTTSupport ? HAL_OK : HAL_ENOTSUPP;
782 case HAL_CAP_FAST_CC:
783 return pCap->halFastCCSupport ? HAL_OK : HAL_ENOTSUPP;
784 case HAL_CAP_TX_CHAINMASK: /* mask of TX chains supported */
785 *result = pCap->halTxChainMask;
786 return HAL_OK;
787 case HAL_CAP_RX_CHAINMASK: /* mask of RX chains supported */
788 *result = pCap->halRxChainMask;
789 return HAL_OK;
790 case HAL_CAP_NUM_GPIO_PINS:
791 *result = pCap->halNumGpioPins;
792 return HAL_OK;
793 case HAL_CAP_CST:
794 return pCap->halCSTSupport ? HAL_OK : HAL_ENOTSUPP;
795 case HAL_CAP_RTS_AGGR_LIMIT:
796 *result = pCap->halRtsAggrLimit;
797 return HAL_OK;
798 case HAL_CAP_4ADDR_AGGR:
799 return pCap->hal4AddrAggrSupport ? HAL_OK : HAL_ENOTSUPP;
800 case HAL_CAP_EXT_CHAN_DFS:
801 return pCap->halExtChanDfsSupport ? HAL_OK : HAL_ENOTSUPP;
802 case HAL_CAP_RX_STBC:
803 return pCap->halRxStbcSupport ? HAL_OK : HAL_ENOTSUPP;
804 case HAL_CAP_TX_STBC:
805 return pCap->halTxStbcSupport ? HAL_OK : HAL_ENOTSUPP;
806 case HAL_CAP_COMBINED_RADAR_RSSI:
807 return pCap->halUseCombinedRadarRssi ? HAL_OK : HAL_ENOTSUPP;
808 case HAL_CAP_AUTO_SLEEP:
809 return pCap->halAutoSleepSupport ? HAL_OK : HAL_ENOTSUPP;
810 case HAL_CAP_MBSSID_AGGR_SUPPORT:
811 return pCap->halMbssidAggrSupport ? HAL_OK : HAL_ENOTSUPP;
812 case HAL_CAP_SPLIT_4KB_TRANS: /* hardware handles descriptors straddling 4k page boundary */
813 return pCap->hal4kbSplitTransSupport ? HAL_OK : HAL_ENOTSUPP;
814 case HAL_CAP_REG_FLAG:
815 *result = AH_PRIVATE(ah)->ah_currentRDext;
816 return HAL_OK;
817 case HAL_CAP_ENHANCED_DMA_SUPPORT:
818 return pCap->halEnhancedDmaSupport ? HAL_OK : HAL_ENOTSUPP;
819 case HAL_CAP_NUM_TXMAPS:
820 *result = pCap->halNumTxMaps;
821 return HAL_OK;
822 case HAL_CAP_TXDESCLEN:
823 *result = pCap->halTxDescLen;
824 return HAL_OK;
825 case HAL_CAP_TXSTATUSLEN:
826 *result = pCap->halTxStatusLen;
827 return HAL_OK;
828 case HAL_CAP_RXSTATUSLEN:
829 *result = pCap->halRxStatusLen;
830 return HAL_OK;
831 case HAL_CAP_RXFIFODEPTH:
832 switch (capability) {
833 case HAL_RX_QUEUE_HP:
834 *result = pCap->halRxHpFifoDepth;
835 return HAL_OK;
836 case HAL_RX_QUEUE_LP:
837 *result = pCap->halRxLpFifoDepth;
838 return HAL_OK;
839 default:
840 return HAL_ENOTSUPP;
841 }
842 case HAL_CAP_RXBUFSIZE:
843 case HAL_CAP_NUM_MR_RETRIES:
844 *result = pCap->halNumMRRetries;
845 return HAL_OK;
846 case HAL_CAP_BT_COEX:
847 return pCap->halBtCoexSupport ? HAL_OK : HAL_ENOTSUPP;
848 case HAL_CAP_SPECTRAL_SCAN:
849 return pCap->halSpectralScanSupport ? HAL_OK : HAL_ENOTSUPP;
850 case HAL_CAP_HT20_SGI:
851 return pCap->halHTSGI20Support ? HAL_OK : HAL_ENOTSUPP;
852 case HAL_CAP_RXTSTAMP_PREC: /* rx desc tstamp precision (bits) */
853 *result = pCap->halRxTstampPrecision;
854 return HAL_OK;
855 case HAL_CAP_ANT_DIV_COMB: /* AR9285/AR9485 LNA diversity */
856 return pCap->halAntDivCombSupport ? HAL_OK : HAL_ENOTSUPP;
857
858 case HAL_CAP_ENHANCED_DFS_SUPPORT:
859 return pCap->halEnhancedDfsSupport ? HAL_OK : HAL_ENOTSUPP;
860
861 /* FreeBSD-specific entries for now */
862 case HAL_CAP_RXORN_FATAL: /* HAL_INT_RXORN treated as fatal */
863 return AH_PRIVATE(ah)->ah_rxornIsFatal ? HAL_OK : HAL_ENOTSUPP;
864 case HAL_CAP_INTRMASK: /* mask of supported interrupts */
865 *result = pCap->halIntrMask;
866 return HAL_OK;
867 case HAL_CAP_BSSIDMATCH: /* hardware has disable bssid match */
868 return pCap->halBssidMatchSupport ? HAL_OK : HAL_ENOTSUPP;
869 case HAL_CAP_STREAMS: /* number of 11n spatial streams */
870 switch (capability) {
871 case 0: /* TX */
872 *result = pCap->halTxStreams;
873 return HAL_OK;
874 case 1: /* RX */
875 *result = pCap->halRxStreams;
876 return HAL_OK;
877 default:
878 return HAL_ENOTSUPP;
879 }
880 case HAL_CAP_RXDESC_SELFLINK: /* hardware supports self-linked final RX descriptors correctly */
881 return pCap->halHasRxSelfLinkedTail ? HAL_OK : HAL_ENOTSUPP;
882 case HAL_CAP_BB_READ_WAR: /* Baseband read WAR */
883 return pCap->halHasBBReadWar? HAL_OK : HAL_ENOTSUPP;
884 case HAL_CAP_SERIALISE_WAR: /* PCI register serialisation */
885 return pCap->halSerialiseRegWar ? HAL_OK : HAL_ENOTSUPP;
886 case HAL_CAP_MFP: /* Management frame protection setting */
887 *result = pCap->halMfpSupport;
888 return HAL_OK;
889 case HAL_CAP_RX_LNA_MIXING: /* Hardware uses an RX LNA mixer to map 2 antennas to a 1 stream receiver */
890 return pCap->halRxUsingLnaMixing ? HAL_OK : HAL_ENOTSUPP;
891 case HAL_CAP_DO_MYBEACON: /* Hardware supports filtering my-beacons */
892 return pCap->halRxDoMyBeacon ? HAL_OK : HAL_ENOTSUPP;
893 case HAL_CAP_TXTSTAMP_PREC: /* tx desc tstamp precision (bits) */
894 *result = pCap->halTxTstampPrecision;
895 return HAL_OK;
896 default:
897 return HAL_EINVAL;
898 }
899 }
900
901 HAL_BOOL
ath_hal_setcapability(struct ath_hal * ah,HAL_CAPABILITY_TYPE type,uint32_t capability,uint32_t setting,HAL_STATUS * status)902 ath_hal_setcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
903 uint32_t capability, uint32_t setting, HAL_STATUS *status)
904 {
905
906 switch (type) {
907 case HAL_CAP_TXPOW:
908 switch (capability) {
909 case 3:
910 if (setting <= HAL_TP_SCALE_MIN) {
911 AH_PRIVATE(ah)->ah_tpScale = setting;
912 return AH_TRUE;
913 }
914 break;
915 }
916 break;
917 case HAL_CAP_RFSILENT: /* rfsilent support */
918 /*
919 * NB: allow even if halRfSilentSupport is false
920 * in case the EEPROM is misprogrammed.
921 */
922 switch (capability) {
923 case 1: /* current setting */
924 AH_PRIVATE(ah)->ah_rfkillEnabled = (setting != 0);
925 return AH_TRUE;
926 case 2: /* rfsilent config */
927 /* XXX better done per-chip for validation? */
928 AH_PRIVATE(ah)->ah_rfsilent = setting;
929 return AH_TRUE;
930 }
931 break;
932 case HAL_CAP_REG_DMN: /* regulatory domain */
933 AH_PRIVATE(ah)->ah_currentRD = setting;
934 return AH_TRUE;
935 case HAL_CAP_RXORN_FATAL: /* HAL_INT_RXORN treated as fatal */
936 AH_PRIVATE(ah)->ah_rxornIsFatal = setting;
937 return AH_TRUE;
938 default:
939 break;
940 }
941 if (status)
942 *status = HAL_EINVAL;
943 return AH_FALSE;
944 }
945
946 /*
947 * Common support for getDiagState method.
948 */
949
950 static u_int
ath_hal_getregdump(struct ath_hal * ah,const HAL_REGRANGE * regs,void * dstbuf,int space)951 ath_hal_getregdump(struct ath_hal *ah, const HAL_REGRANGE *regs,
952 void *dstbuf, int space)
953 {
954 uint32_t *dp = dstbuf;
955 int i;
956
957 for (i = 0; space >= 2*sizeof(uint32_t); i++) {
958 uint32_t r = regs[i].start;
959 uint32_t e = regs[i].end;
960 *dp++ = r;
961 *dp++ = e;
962 space -= 2*sizeof(uint32_t);
963 do {
964 *dp++ = OS_REG_READ(ah, r);
965 r += sizeof(uint32_t);
966 space -= sizeof(uint32_t);
967 } while (r <= e && space >= sizeof(uint32_t));
968 }
969 return (char *) dp - (char *) dstbuf;
970 }
971
972 static void
ath_hal_setregs(struct ath_hal * ah,const HAL_REGWRITE * regs,int space)973 ath_hal_setregs(struct ath_hal *ah, const HAL_REGWRITE *regs, int space)
974 {
975 while (space >= sizeof(HAL_REGWRITE)) {
976 OS_REG_WRITE(ah, regs->addr, regs->value);
977 regs++, space -= sizeof(HAL_REGWRITE);
978 }
979 }
980
981 HAL_BOOL
ath_hal_getdiagstate(struct ath_hal * ah,int request,const void * args,uint32_t argsize,void ** result,uint32_t * resultsize)982 ath_hal_getdiagstate(struct ath_hal *ah, int request,
983 const void *args, uint32_t argsize,
984 void **result, uint32_t *resultsize)
985 {
986
987 switch (request) {
988 case HAL_DIAG_REVS:
989 *result = &AH_PRIVATE(ah)->ah_devid;
990 *resultsize = sizeof(HAL_REVS);
991 return AH_TRUE;
992 case HAL_DIAG_REGS:
993 *resultsize = ath_hal_getregdump(ah, args, *result,*resultsize);
994 return AH_TRUE;
995 case HAL_DIAG_SETREGS:
996 ath_hal_setregs(ah, args, argsize);
997 *resultsize = 0;
998 return AH_TRUE;
999 case HAL_DIAG_FATALERR:
1000 *result = &AH_PRIVATE(ah)->ah_fatalState[0];
1001 *resultsize = sizeof(AH_PRIVATE(ah)->ah_fatalState);
1002 return AH_TRUE;
1003 case HAL_DIAG_EEREAD:
1004 if (argsize != sizeof(uint16_t))
1005 return AH_FALSE;
1006 if (!ath_hal_eepromRead(ah, *(const uint16_t *)args, *result))
1007 return AH_FALSE;
1008 *resultsize = sizeof(uint16_t);
1009 return AH_TRUE;
1010 #ifdef AH_PRIVATE_DIAG
1011 case HAL_DIAG_SETKEY: {
1012 const HAL_DIAG_KEYVAL *dk;
1013
1014 if (argsize != sizeof(HAL_DIAG_KEYVAL))
1015 return AH_FALSE;
1016 dk = (const HAL_DIAG_KEYVAL *)args;
1017 return ah->ah_setKeyCacheEntry(ah, dk->dk_keyix,
1018 &dk->dk_keyval, dk->dk_mac, dk->dk_xor);
1019 }
1020 case HAL_DIAG_RESETKEY:
1021 if (argsize != sizeof(uint16_t))
1022 return AH_FALSE;
1023 return ah->ah_resetKeyCacheEntry(ah, *(const uint16_t *)args);
1024 #ifdef AH_SUPPORT_WRITE_EEPROM
1025 case HAL_DIAG_EEWRITE: {
1026 const HAL_DIAG_EEVAL *ee;
1027 if (argsize != sizeof(HAL_DIAG_EEVAL))
1028 return AH_FALSE;
1029 ee = (const HAL_DIAG_EEVAL *)args;
1030 return ath_hal_eepromWrite(ah, ee->ee_off, ee->ee_data);
1031 }
1032 #endif /* AH_SUPPORT_WRITE_EEPROM */
1033 #endif /* AH_PRIVATE_DIAG */
1034 case HAL_DIAG_11NCOMPAT:
1035 if (argsize == 0) {
1036 *resultsize = sizeof(uint32_t);
1037 *((uint32_t *)(*result)) =
1038 AH_PRIVATE(ah)->ah_11nCompat;
1039 } else if (argsize == sizeof(uint32_t)) {
1040 AH_PRIVATE(ah)->ah_11nCompat = *(const uint32_t *)args;
1041 } else
1042 return AH_FALSE;
1043 return AH_TRUE;
1044 case HAL_DIAG_CHANSURVEY:
1045 *result = &AH_PRIVATE(ah)->ah_chansurvey;
1046 *resultsize = sizeof(HAL_CHANNEL_SURVEY);
1047 return AH_TRUE;
1048 }
1049 return AH_FALSE;
1050 }
1051
1052 /*
1053 * Set the properties of the tx queue with the parameters
1054 * from qInfo.
1055 */
1056 HAL_BOOL
ath_hal_setTxQProps(struct ath_hal * ah,HAL_TX_QUEUE_INFO * qi,const HAL_TXQ_INFO * qInfo)1057 ath_hal_setTxQProps(struct ath_hal *ah,
1058 HAL_TX_QUEUE_INFO *qi, const HAL_TXQ_INFO *qInfo)
1059 {
1060 uint32_t cw;
1061
1062 if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
1063 HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
1064 "%s: inactive queue\n", __func__);
1065 return AH_FALSE;
1066 }
1067 /* XXX validate parameters */
1068 qi->tqi_ver = qInfo->tqi_ver;
1069 qi->tqi_subtype = qInfo->tqi_subtype;
1070 qi->tqi_qflags = qInfo->tqi_qflags;
1071 qi->tqi_priority = qInfo->tqi_priority;
1072 if (qInfo->tqi_aifs != HAL_TXQ_USEDEFAULT)
1073 qi->tqi_aifs = AH_MIN(qInfo->tqi_aifs, 255);
1074 else
1075 qi->tqi_aifs = INIT_AIFS;
1076 if (qInfo->tqi_cwmin != HAL_TXQ_USEDEFAULT) {
1077 cw = AH_MIN(qInfo->tqi_cwmin, 1024);
1078 /* make sure that the CWmin is of the form (2^n - 1) */
1079 qi->tqi_cwmin = 1;
1080 while (qi->tqi_cwmin < cw)
1081 qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1;
1082 } else
1083 qi->tqi_cwmin = qInfo->tqi_cwmin;
1084 if (qInfo->tqi_cwmax != HAL_TXQ_USEDEFAULT) {
1085 cw = AH_MIN(qInfo->tqi_cwmax, 1024);
1086 /* make sure that the CWmax is of the form (2^n - 1) */
1087 qi->tqi_cwmax = 1;
1088 while (qi->tqi_cwmax < cw)
1089 qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1;
1090 } else
1091 qi->tqi_cwmax = INIT_CWMAX;
1092 /* Set retry limit values */
1093 if (qInfo->tqi_shretry != 0)
1094 qi->tqi_shretry = AH_MIN(qInfo->tqi_shretry, 15);
1095 else
1096 qi->tqi_shretry = INIT_SH_RETRY;
1097 if (qInfo->tqi_lgretry != 0)
1098 qi->tqi_lgretry = AH_MIN(qInfo->tqi_lgretry, 15);
1099 else
1100 qi->tqi_lgretry = INIT_LG_RETRY;
1101 qi->tqi_cbrPeriod = qInfo->tqi_cbrPeriod;
1102 qi->tqi_cbrOverflowLimit = qInfo->tqi_cbrOverflowLimit;
1103 qi->tqi_burstTime = qInfo->tqi_burstTime;
1104 qi->tqi_readyTime = qInfo->tqi_readyTime;
1105
1106 switch (qInfo->tqi_subtype) {
1107 case HAL_WME_UPSD:
1108 if (qi->tqi_type == HAL_TX_QUEUE_DATA)
1109 qi->tqi_intFlags = HAL_TXQ_USE_LOCKOUT_BKOFF_DIS;
1110 break;
1111 default:
1112 break; /* NB: silence compiler */
1113 }
1114 return AH_TRUE;
1115 }
1116
1117 HAL_BOOL
ath_hal_getTxQProps(struct ath_hal * ah,HAL_TXQ_INFO * qInfo,const HAL_TX_QUEUE_INFO * qi)1118 ath_hal_getTxQProps(struct ath_hal *ah,
1119 HAL_TXQ_INFO *qInfo, const HAL_TX_QUEUE_INFO *qi)
1120 {
1121 if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
1122 HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
1123 "%s: inactive queue\n", __func__);
1124 return AH_FALSE;
1125 }
1126
1127 qInfo->tqi_ver = qi->tqi_ver;
1128 qInfo->tqi_subtype = qi->tqi_subtype;
1129 qInfo->tqi_qflags = qi->tqi_qflags;
1130 qInfo->tqi_priority = qi->tqi_priority;
1131 qInfo->tqi_aifs = qi->tqi_aifs;
1132 qInfo->tqi_cwmin = qi->tqi_cwmin;
1133 qInfo->tqi_cwmax = qi->tqi_cwmax;
1134 qInfo->tqi_shretry = qi->tqi_shretry;
1135 qInfo->tqi_lgretry = qi->tqi_lgretry;
1136 qInfo->tqi_cbrPeriod = qi->tqi_cbrPeriod;
1137 qInfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit;
1138 qInfo->tqi_burstTime = qi->tqi_burstTime;
1139 qInfo->tqi_readyTime = qi->tqi_readyTime;
1140 qInfo->tqi_compBuf = qi->tqi_physCompBuf;
1141 return AH_TRUE;
1142 }
1143
1144 /* 11a Turbo 11b 11g 108g */
1145 static const int16_t NOISE_FLOOR[] = { -96, -93, -98, -96, -93 };
1146
1147 /*
1148 * Read the current channel noise floor and return.
1149 * If nf cal hasn't finished, channel noise floor should be 0
1150 * and we return a nominal value based on band and frequency.
1151 *
1152 * NB: This is a private routine used by per-chip code to
1153 * implement the ah_getChanNoise method.
1154 */
1155 int16_t
ath_hal_getChanNoise(struct ath_hal * ah,const struct ieee80211_channel * chan)1156 ath_hal_getChanNoise(struct ath_hal *ah, const struct ieee80211_channel *chan)
1157 {
1158 HAL_CHANNEL_INTERNAL *ichan;
1159
1160 ichan = ath_hal_checkchannel(ah, chan);
1161 if (ichan == AH_NULL) {
1162 HALDEBUG(ah, HAL_DEBUG_NFCAL,
1163 "%s: invalid channel %u/0x%x; no mapping\n",
1164 __func__, chan->ic_freq, chan->ic_flags);
1165 return 0;
1166 }
1167 if (ichan->rawNoiseFloor == 0) {
1168 WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan);
1169
1170 HALASSERT(mode < WIRELESS_MODE_MAX);
1171 return NOISE_FLOOR[mode] + ath_hal_getNfAdjust(ah, ichan);
1172 } else
1173 return ichan->rawNoiseFloor + ichan->noiseFloorAdjust;
1174 }
1175
1176 /*
1177 * Fetch the current setup of ctl/ext noise floor values.
1178 *
1179 * If the CHANNEL_MIMO_NF_VALID flag isn't set, the array is simply
1180 * populated with values from NOISE_FLOOR[] + ath_hal_getNfAdjust().
1181 *
1182 * The caller must supply ctl/ext NF arrays which are at least
1183 * AH_MAX_CHAINS entries long.
1184 */
1185 int
ath_hal_get_mimo_chan_noise(struct ath_hal * ah,const struct ieee80211_channel * chan,int16_t * nf_ctl,int16_t * nf_ext)1186 ath_hal_get_mimo_chan_noise(struct ath_hal *ah,
1187 const struct ieee80211_channel *chan, int16_t *nf_ctl,
1188 int16_t *nf_ext)
1189 {
1190 HAL_CHANNEL_INTERNAL *ichan;
1191 int i;
1192
1193 ichan = ath_hal_checkchannel(ah, chan);
1194 if (ichan == AH_NULL) {
1195 HALDEBUG(ah, HAL_DEBUG_NFCAL,
1196 "%s: invalid channel %u/0x%x; no mapping\n",
1197 __func__, chan->ic_freq, chan->ic_flags);
1198 for (i = 0; i < AH_MAX_CHAINS; i++) {
1199 nf_ctl[i] = nf_ext[i] = 0;
1200 }
1201 return 0;
1202 }
1203
1204 /* Return 0 if there's no valid MIMO values (yet) */
1205 if (! (ichan->privFlags & CHANNEL_MIMO_NF_VALID)) {
1206 for (i = 0; i < AH_MAX_CHAINS; i++) {
1207 nf_ctl[i] = nf_ext[i] = 0;
1208 }
1209 return 0;
1210 }
1211 if (ichan->rawNoiseFloor == 0) {
1212 WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan);
1213 HALASSERT(mode < WIRELESS_MODE_MAX);
1214 /*
1215 * See the comment below - this could cause issues for
1216 * stations which have a very low RSSI, below the
1217 * 'normalised' NF values in NOISE_FLOOR[].
1218 */
1219 for (i = 0; i < AH_MAX_CHAINS; i++) {
1220 nf_ctl[i] = nf_ext[i] = NOISE_FLOOR[mode] +
1221 ath_hal_getNfAdjust(ah, ichan);
1222 }
1223 return 1;
1224 } else {
1225 /*
1226 * The value returned here from a MIMO radio is presumed to be
1227 * "good enough" as a NF calculation. As RSSI values are calculated
1228 * against this, an adjusted NF may be higher than the RSSI value
1229 * returned from a vary weak station, resulting in an obscenely
1230 * high signal strength calculation being returned.
1231 *
1232 * This should be re-evaluated at a later date, along with any
1233 * signal strength calculations which are made. Quite likely the
1234 * RSSI values will need to be adjusted to ensure the calculations
1235 * don't "wrap" when RSSI is less than the "adjusted" NF value.
1236 * ("Adjust" here is via ichan->noiseFloorAdjust.)
1237 */
1238 for (i = 0; i < AH_MAX_CHAINS; i++) {
1239 nf_ctl[i] = ichan->noiseFloorCtl[i] + ath_hal_getNfAdjust(ah, ichan);
1240 nf_ext[i] = ichan->noiseFloorExt[i] + ath_hal_getNfAdjust(ah, ichan);
1241 }
1242 return 1;
1243 }
1244 }
1245
1246 /*
1247 * Process all valid raw noise floors into the dBm noise floor values.
1248 * Though our device has no reference for a dBm noise floor, we perform
1249 * a relative minimization of NF's based on the lowest NF found across a
1250 * channel scan.
1251 */
1252 void
ath_hal_process_noisefloor(struct ath_hal * ah)1253 ath_hal_process_noisefloor(struct ath_hal *ah)
1254 {
1255 HAL_CHANNEL_INTERNAL *c;
1256 int16_t correct2, correct5;
1257 int16_t lowest2, lowest5;
1258 int i;
1259
1260 /*
1261 * Find the lowest 2GHz and 5GHz noise floor values after adjusting
1262 * for statistically recorded NF/channel deviation.
1263 */
1264 correct2 = lowest2 = 0;
1265 correct5 = lowest5 = 0;
1266 for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
1267 WIRELESS_MODE mode;
1268 int16_t nf;
1269
1270 c = &AH_PRIVATE(ah)->ah_channels[i];
1271 if (c->rawNoiseFloor >= 0)
1272 continue;
1273 /* XXX can't identify proper mode */
1274 mode = IS_CHAN_5GHZ(c) ? WIRELESS_MODE_11a : WIRELESS_MODE_11g;
1275 nf = c->rawNoiseFloor + NOISE_FLOOR[mode] +
1276 ath_hal_getNfAdjust(ah, c);
1277 if (IS_CHAN_5GHZ(c)) {
1278 if (nf < lowest5) {
1279 lowest5 = nf;
1280 correct5 = NOISE_FLOOR[mode] -
1281 (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
1282 }
1283 } else {
1284 if (nf < lowest2) {
1285 lowest2 = nf;
1286 correct2 = NOISE_FLOOR[mode] -
1287 (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
1288 }
1289 }
1290 }
1291
1292 /* Correct the channels to reach the expected NF value */
1293 for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
1294 c = &AH_PRIVATE(ah)->ah_channels[i];
1295 if (c->rawNoiseFloor >= 0)
1296 continue;
1297 /* Apply correction factor */
1298 c->noiseFloorAdjust = ath_hal_getNfAdjust(ah, c) +
1299 (IS_CHAN_5GHZ(c) ? correct5 : correct2);
1300 HALDEBUG(ah, HAL_DEBUG_NFCAL, "%u raw nf %d adjust %d\n",
1301 c->channel, c->rawNoiseFloor, c->noiseFloorAdjust);
1302 }
1303 }
1304
1305 /*
1306 * INI support routines.
1307 */
1308
1309 int
ath_hal_ini_write(struct ath_hal * ah,const HAL_INI_ARRAY * ia,int col,int regWr)1310 ath_hal_ini_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
1311 int col, int regWr)
1312 {
1313 int r;
1314
1315 HALASSERT(col < ia->cols);
1316 for (r = 0; r < ia->rows; r++) {
1317 OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0),
1318 HAL_INI_VAL(ia, r, col));
1319
1320 /* Analog shift register delay seems needed for Merlin - PR kern/154220 */
1321 if (HAL_INI_VAL(ia, r, 0) >= 0x7800 && HAL_INI_VAL(ia, r, 0) < 0x7900)
1322 OS_DELAY(100);
1323
1324 DMA_YIELD(regWr);
1325 }
1326 return regWr;
1327 }
1328
1329 void
ath_hal_ini_bank_setup(uint32_t data[],const HAL_INI_ARRAY * ia,int col)1330 ath_hal_ini_bank_setup(uint32_t data[], const HAL_INI_ARRAY *ia, int col)
1331 {
1332 int r;
1333
1334 HALASSERT(col < ia->cols);
1335 for (r = 0; r < ia->rows; r++)
1336 data[r] = HAL_INI_VAL(ia, r, col);
1337 }
1338
1339 int
ath_hal_ini_bank_write(struct ath_hal * ah,const HAL_INI_ARRAY * ia,const uint32_t data[],int regWr)1340 ath_hal_ini_bank_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
1341 const uint32_t data[], int regWr)
1342 {
1343 int r;
1344
1345 for (r = 0; r < ia->rows; r++) {
1346 OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0), data[r]);
1347 DMA_YIELD(regWr);
1348 }
1349 return regWr;
1350 }
1351
1352 /*
1353 * These are EEPROM board related routines which should likely live in
1354 * a helper library of some sort.
1355 */
1356
1357 /**************************************************************
1358 * ath_ee_getLowerUppderIndex
1359 *
1360 * Return indices surrounding the value in sorted integer lists.
1361 * Requirement: the input list must be monotonically increasing
1362 * and populated up to the list size
1363 * Returns: match is set if an index in the array matches exactly
1364 * or a the target is before or after the range of the array.
1365 */
1366 HAL_BOOL
ath_ee_getLowerUpperIndex(uint8_t target,uint8_t * pList,uint16_t listSize,uint16_t * indexL,uint16_t * indexR)1367 ath_ee_getLowerUpperIndex(uint8_t target, uint8_t *pList, uint16_t listSize,
1368 uint16_t *indexL, uint16_t *indexR)
1369 {
1370 uint16_t i;
1371
1372 /*
1373 * Check first and last elements for beyond ordered array cases.
1374 */
1375 if (target <= pList[0]) {
1376 *indexL = *indexR = 0;
1377 return AH_TRUE;
1378 }
1379 if (target >= pList[listSize-1]) {
1380 *indexL = *indexR = (uint16_t)(listSize - 1);
1381 return AH_TRUE;
1382 }
1383
1384 /* look for value being near or between 2 values in list */
1385 for (i = 0; i < listSize - 1; i++) {
1386 /*
1387 * If value is close to the current value of the list
1388 * then target is not between values, it is one of the values
1389 */
1390 if (pList[i] == target) {
1391 *indexL = *indexR = i;
1392 return AH_TRUE;
1393 }
1394 /*
1395 * Look for value being between current value and next value
1396 * if so return these 2 values
1397 */
1398 if (target < pList[i + 1]) {
1399 *indexL = i;
1400 *indexR = (uint16_t)(i + 1);
1401 return AH_FALSE;
1402 }
1403 }
1404 HALASSERT(0);
1405 *indexL = *indexR = 0;
1406 return AH_FALSE;
1407 }
1408
1409 /**************************************************************
1410 * ath_ee_FillVpdTable
1411 *
1412 * Fill the Vpdlist for indices Pmax-Pmin
1413 * Note: pwrMin, pwrMax and Vpdlist are all in dBm * 4
1414 */
1415 HAL_BOOL
ath_ee_FillVpdTable(uint8_t pwrMin,uint8_t pwrMax,uint8_t * pPwrList,uint8_t * pVpdList,uint16_t numIntercepts,uint8_t * pRetVpdList)1416 ath_ee_FillVpdTable(uint8_t pwrMin, uint8_t pwrMax, uint8_t *pPwrList,
1417 uint8_t *pVpdList, uint16_t numIntercepts, uint8_t *pRetVpdList)
1418 {
1419 uint16_t i, k;
1420 uint8_t currPwr = pwrMin;
1421 uint16_t idxL, idxR;
1422
1423 HALASSERT(pwrMax > pwrMin);
1424 for (i = 0; i <= (pwrMax - pwrMin) / 2; i++) {
1425 ath_ee_getLowerUpperIndex(currPwr, pPwrList, numIntercepts,
1426 &(idxL), &(idxR));
1427 if (idxR < 1)
1428 idxR = 1; /* extrapolate below */
1429 if (idxL == numIntercepts - 1)
1430 idxL = (uint16_t)(numIntercepts - 2); /* extrapolate above */
1431 if (pPwrList[idxL] == pPwrList[idxR])
1432 k = pVpdList[idxL];
1433 else
1434 k = (uint16_t)( ((currPwr - pPwrList[idxL]) * pVpdList[idxR] + (pPwrList[idxR] - currPwr) * pVpdList[idxL]) /
1435 (pPwrList[idxR] - pPwrList[idxL]) );
1436 HALASSERT(k < 256);
1437 pRetVpdList[i] = (uint8_t)k;
1438 currPwr += 2; /* half dB steps */
1439 }
1440
1441 return AH_TRUE;
1442 }
1443
1444 /**************************************************************************
1445 * ath_ee_interpolate
1446 *
1447 * Returns signed interpolated or the scaled up interpolated value
1448 */
1449 int16_t
ath_ee_interpolate(uint16_t target,uint16_t srcLeft,uint16_t srcRight,int16_t targetLeft,int16_t targetRight)1450 ath_ee_interpolate(uint16_t target, uint16_t srcLeft, uint16_t srcRight,
1451 int16_t targetLeft, int16_t targetRight)
1452 {
1453 int16_t rv;
1454
1455 if (srcRight == srcLeft) {
1456 rv = targetLeft;
1457 } else {
1458 rv = (int16_t)( ((target - srcLeft) * targetRight +
1459 (srcRight - target) * targetLeft) / (srcRight - srcLeft) );
1460 }
1461 return rv;
1462 }
1463
1464 /*
1465 * Adjust the TSF.
1466 */
1467 void
ath_hal_adjusttsf(struct ath_hal * ah,int32_t tsfdelta)1468 ath_hal_adjusttsf(struct ath_hal *ah, int32_t tsfdelta)
1469 {
1470 /* XXX handle wrap/overflow */
1471 OS_REG_WRITE(ah, AR_TSF_L32, OS_REG_READ(ah, AR_TSF_L32) + tsfdelta);
1472 }
1473
1474 /*
1475 * Enable or disable CCA.
1476 */
1477 void
ath_hal_setcca(struct ath_hal * ah,int ena)1478 ath_hal_setcca(struct ath_hal *ah, int ena)
1479 {
1480 /*
1481 * NB: fill me in; this is not provided by default because disabling
1482 * CCA in most locales violates regulatory.
1483 */
1484 }
1485
1486 /*
1487 * Get CCA setting.
1488 *
1489 * XXX TODO: turn this and the above function into methods
1490 * in case there are chipset differences in handling CCA.
1491 */
1492 int
ath_hal_getcca(struct ath_hal * ah)1493 ath_hal_getcca(struct ath_hal *ah)
1494 {
1495 u_int32_t diag;
1496 if (ath_hal_getcapability(ah, HAL_CAP_DIAG, 0, &diag) != HAL_OK)
1497 return 1;
1498 return ((diag & 0x500000) == 0);
1499 }
1500
1501 /*
1502 * Set the current state of self-generated ACK and RTS/CTS frames.
1503 *
1504 * For correct DFS operation, the device should not even /ACK/ frames
1505 * that are sent to it during CAC or CSA.
1506 */
1507 void
ath_hal_set_dfs_cac_tx_quiet(struct ath_hal * ah,HAL_BOOL ena)1508 ath_hal_set_dfs_cac_tx_quiet(struct ath_hal *ah, HAL_BOOL ena)
1509 {
1510
1511 if (ah->ah_setDfsCacTxQuiet == NULL)
1512 return;
1513 ah->ah_setDfsCacTxQuiet(ah, ena);
1514 }
1515
1516 /*
1517 * This routine is only needed when supporting EEPROM-in-RAM setups
1518 * (eg embedded SoCs and on-board PCI/PCIe devices.)
1519 */
1520 /* NB: This is in 16 bit words; not bytes */
1521 /* XXX This doesn't belong here! */
1522 #define ATH_DATA_EEPROM_SIZE 2048
1523
1524 HAL_BOOL
ath_hal_EepromDataRead(struct ath_hal * ah,u_int off,uint16_t * data)1525 ath_hal_EepromDataRead(struct ath_hal *ah, u_int off, uint16_t *data)
1526 {
1527 if (ah->ah_eepromdata == AH_NULL) {
1528 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: no eeprom data!\n", __func__);
1529 return AH_FALSE;
1530 }
1531 if (off > ATH_DATA_EEPROM_SIZE) {
1532 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: offset %x > %x\n",
1533 __func__, off, ATH_DATA_EEPROM_SIZE);
1534 return AH_FALSE;
1535 }
1536 (*data) = ah->ah_eepromdata[off];
1537 return AH_TRUE;
1538 }
1539
1540 /*
1541 * Do a 2GHz specific MHz->IEEE based on the hardware
1542 * frequency.
1543 *
1544 * This is the unmapped frequency which is programmed into the hardware.
1545 */
1546 int
ath_hal_mhz2ieee_2ghz(struct ath_hal * ah,int freq)1547 ath_hal_mhz2ieee_2ghz(struct ath_hal *ah, int freq)
1548 {
1549
1550 if (freq == 2484)
1551 return 14;
1552 if (freq < 2484)
1553 return ((int) freq - 2407) / 5;
1554 else
1555 return 15 + ((freq - 2512) / 20);
1556 }
1557
1558 /*
1559 * Clear the current survey data.
1560 *
1561 * This should be done during a channel change.
1562 */
1563 void
ath_hal_survey_clear(struct ath_hal * ah)1564 ath_hal_survey_clear(struct ath_hal *ah)
1565 {
1566
1567 OS_MEMZERO(&AH_PRIVATE(ah)->ah_chansurvey,
1568 sizeof(AH_PRIVATE(ah)->ah_chansurvey));
1569 }
1570
1571 /*
1572 * Add a sample to the channel survey.
1573 */
1574 void
ath_hal_survey_add_sample(struct ath_hal * ah,HAL_SURVEY_SAMPLE * hs)1575 ath_hal_survey_add_sample(struct ath_hal *ah, HAL_SURVEY_SAMPLE *hs)
1576 {
1577 HAL_CHANNEL_SURVEY *cs;
1578
1579 cs = &AH_PRIVATE(ah)->ah_chansurvey;
1580
1581 OS_MEMCPY(&cs->samples[cs->cur_sample], hs, sizeof(*hs));
1582 cs->samples[cs->cur_sample].seq_num = cs->cur_seq;
1583 cs->cur_sample = (cs->cur_sample + 1) % CHANNEL_SURVEY_SAMPLE_COUNT;
1584 cs->cur_seq++;
1585 }
1586