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