Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/dev/ath/ath_hal/ah.c
39536 views
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
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
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*
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*
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 *
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
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
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
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 *
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 *
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
1587