Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/dev/ath/ath_hal/ar5212/ar5212_misc.c
39566 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_desc.h" /* NB: for HAL_PHYERR* */
25
26
#include "ar5212/ar5212.h"
27
#include "ar5212/ar5212reg.h"
28
#include "ar5212/ar5212phy.h"
29
30
#include "ah_eeprom_v3.h"
31
32
#define AR_NUM_GPIO 6 /* 6 GPIO pins */
33
#define AR_GPIOD_MASK 0x0000002F /* GPIO data reg r/w mask */
34
35
void
36
ar5212GetMacAddress(struct ath_hal *ah, uint8_t *mac)
37
{
38
struct ath_hal_5212 *ahp = AH5212(ah);
39
40
OS_MEMCPY(mac, ahp->ah_macaddr, IEEE80211_ADDR_LEN);
41
}
42
43
HAL_BOOL
44
ar5212SetMacAddress(struct ath_hal *ah, const uint8_t *mac)
45
{
46
struct ath_hal_5212 *ahp = AH5212(ah);
47
48
OS_MEMCPY(ahp->ah_macaddr, mac, IEEE80211_ADDR_LEN);
49
return AH_TRUE;
50
}
51
52
void
53
ar5212GetBssIdMask(struct ath_hal *ah, uint8_t *mask)
54
{
55
struct ath_hal_5212 *ahp = AH5212(ah);
56
57
OS_MEMCPY(mask, ahp->ah_bssidmask, IEEE80211_ADDR_LEN);
58
}
59
60
HAL_BOOL
61
ar5212SetBssIdMask(struct ath_hal *ah, const uint8_t *mask)
62
{
63
struct ath_hal_5212 *ahp = AH5212(ah);
64
65
/* save it since it must be rewritten on reset */
66
OS_MEMCPY(ahp->ah_bssidmask, mask, IEEE80211_ADDR_LEN);
67
68
OS_REG_WRITE(ah, AR_BSSMSKL, LE_READ_4(ahp->ah_bssidmask));
69
OS_REG_WRITE(ah, AR_BSSMSKU, LE_READ_2(ahp->ah_bssidmask + 4));
70
return AH_TRUE;
71
}
72
73
/*
74
* Attempt to change the cards operating regulatory domain to the given value
75
*/
76
HAL_BOOL
77
ar5212SetRegulatoryDomain(struct ath_hal *ah,
78
uint16_t regDomain, HAL_STATUS *status)
79
{
80
HAL_STATUS ecode;
81
82
if (AH_PRIVATE(ah)->ah_currentRD == regDomain) {
83
ecode = HAL_EINVAL;
84
goto bad;
85
}
86
if (ath_hal_eepromGetFlag(ah, AR_EEP_WRITEPROTECT)) {
87
ecode = HAL_EEWRITE;
88
goto bad;
89
}
90
#ifdef AH_SUPPORT_WRITE_REGDOMAIN
91
if (ath_hal_eepromWrite(ah, AR_EEPROM_REG_DOMAIN, regDomain)) {
92
HALDEBUG(ah, HAL_DEBUG_ANY,
93
"%s: set regulatory domain to %u (0x%x)\n",
94
__func__, regDomain, regDomain);
95
AH_PRIVATE(ah)->ah_currentRD = regDomain;
96
return AH_TRUE;
97
}
98
#endif
99
ecode = HAL_EIO;
100
bad:
101
if (status)
102
*status = ecode;
103
return AH_FALSE;
104
}
105
106
/*
107
* Return the wireless modes (a,b,g,t) supported by hardware.
108
*
109
* This value is what is actually supported by the hardware
110
* and is unaffected by regulatory/country code settings.
111
*/
112
u_int
113
ar5212GetWirelessModes(struct ath_hal *ah)
114
{
115
u_int mode = 0;
116
117
if (ath_hal_eepromGetFlag(ah, AR_EEP_AMODE)) {
118
mode = HAL_MODE_11A;
119
if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO5DISABLE))
120
mode |= HAL_MODE_TURBO | HAL_MODE_108A;
121
if (AH_PRIVATE(ah)->ah_caps.halChanHalfRate)
122
mode |= HAL_MODE_11A_HALF_RATE;
123
if (AH_PRIVATE(ah)->ah_caps.halChanQuarterRate)
124
mode |= HAL_MODE_11A_QUARTER_RATE;
125
}
126
if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE))
127
mode |= HAL_MODE_11B;
128
if (ath_hal_eepromGetFlag(ah, AR_EEP_GMODE) &&
129
AH_PRIVATE(ah)->ah_subvendorid != AR_SUBVENDOR_ID_NOG) {
130
mode |= HAL_MODE_11G;
131
if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO2DISABLE))
132
mode |= HAL_MODE_108G;
133
if (AH_PRIVATE(ah)->ah_caps.halChanHalfRate)
134
mode |= HAL_MODE_11G_HALF_RATE;
135
if (AH_PRIVATE(ah)->ah_caps.halChanQuarterRate)
136
mode |= HAL_MODE_11G_QUARTER_RATE;
137
}
138
return mode;
139
}
140
141
/*
142
* Set the interrupt and GPIO values so the ISR can disable RF
143
* on a switch signal. Assumes GPIO port and interrupt polarity
144
* are set prior to call.
145
*/
146
void
147
ar5212EnableRfKill(struct ath_hal *ah)
148
{
149
uint16_t rfsilent = AH_PRIVATE(ah)->ah_rfsilent;
150
int select = MS(rfsilent, AR_EEPROM_RFSILENT_GPIO_SEL);
151
int polarity = MS(rfsilent, AR_EEPROM_RFSILENT_POLARITY);
152
153
/*
154
* Configure the desired GPIO port for input
155
* and enable baseband rf silence.
156
*/
157
ath_hal_gpioCfgInput(ah, select);
158
OS_REG_SET_BIT(ah, AR_PHY(0), 0x00002000);
159
/*
160
* If radio disable switch connection to GPIO bit x is enabled
161
* program GPIO interrupt.
162
* If rfkill bit on eeprom is 1, setupeeprommap routine has already
163
* verified that it is a later version of eeprom, it has a place for
164
* rfkill bit and it is set to 1, indicating that GPIO bit x hardware
165
* connection is present.
166
*/
167
ath_hal_gpioSetIntr(ah, select,
168
(ath_hal_gpioGet(ah, select) == polarity ? !polarity : polarity));
169
}
170
171
/*
172
* Change the LED blinking pattern to correspond to the connectivity
173
*/
174
void
175
ar5212SetLedState(struct ath_hal *ah, HAL_LED_STATE state)
176
{
177
static const uint32_t ledbits[8] = {
178
AR_PCICFG_LEDCTL_NONE, /* HAL_LED_INIT */
179
AR_PCICFG_LEDCTL_PEND, /* HAL_LED_SCAN */
180
AR_PCICFG_LEDCTL_PEND, /* HAL_LED_AUTH */
181
AR_PCICFG_LEDCTL_ASSOC, /* HAL_LED_ASSOC*/
182
AR_PCICFG_LEDCTL_ASSOC, /* HAL_LED_RUN */
183
AR_PCICFG_LEDCTL_NONE,
184
AR_PCICFG_LEDCTL_NONE,
185
AR_PCICFG_LEDCTL_NONE,
186
};
187
uint32_t bits;
188
189
bits = OS_REG_READ(ah, AR_PCICFG);
190
if (IS_2417(ah)) {
191
/*
192
* Enable LED for Nala. There is a bit marked reserved
193
* that must be set and we also turn on the power led.
194
* Because we mark s/w LED control setting the control
195
* status bits below is meangless (the driver must flash
196
* the LED(s) using the GPIO lines).
197
*/
198
bits = (bits &~ AR_PCICFG_LEDMODE)
199
| SM(AR_PCICFG_LEDMODE_POWON, AR_PCICFG_LEDMODE)
200
#if 0
201
| SM(AR_PCICFG_LEDMODE_NETON, AR_PCICFG_LEDMODE)
202
#endif
203
| 0x08000000;
204
}
205
bits = (bits &~ AR_PCICFG_LEDCTL)
206
| SM(ledbits[state & 0x7], AR_PCICFG_LEDCTL);
207
OS_REG_WRITE(ah, AR_PCICFG, bits);
208
}
209
210
/*
211
* Change association related fields programmed into the hardware.
212
* Writing a valid BSSID to the hardware effectively enables the hardware
213
* to synchronize its TSF to the correct beacons and receive frames coming
214
* from that BSSID. It is called by the SME JOIN operation.
215
*/
216
void
217
ar5212WriteAssocid(struct ath_hal *ah, const uint8_t *bssid, uint16_t assocId)
218
{
219
struct ath_hal_5212 *ahp = AH5212(ah);
220
221
/* save bssid for possible re-use on reset */
222
OS_MEMCPY(ahp->ah_bssid, bssid, IEEE80211_ADDR_LEN);
223
ahp->ah_assocId = assocId;
224
OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid));
225
OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid+4) |
226
((assocId & 0x3fff)<<AR_BSS_ID1_AID_S));
227
}
228
229
/*
230
* Get the current hardware tsf for stamlme
231
*/
232
uint64_t
233
ar5212GetTsf64(struct ath_hal *ah)
234
{
235
uint32_t low1, low2, u32;
236
237
/* sync multi-word read */
238
low1 = OS_REG_READ(ah, AR_TSF_L32);
239
u32 = OS_REG_READ(ah, AR_TSF_U32);
240
low2 = OS_REG_READ(ah, AR_TSF_L32);
241
if (low2 < low1) { /* roll over */
242
/*
243
* If we are not preempted this will work. If we are
244
* then we re-reading AR_TSF_U32 does no good as the
245
* low bits will be meaningless. Likewise reading
246
* L32, U32, U32, then comparing the last two reads
247
* to check for rollover doesn't help if preempted--so
248
* we take this approach as it costs one less PCI read
249
* which can be noticeable when doing things like
250
* timestamping packets in monitor mode.
251
*/
252
u32++;
253
}
254
return (((uint64_t) u32) << 32) | ((uint64_t) low2);
255
}
256
257
/*
258
* Get the current hardware tsf for stamlme
259
*/
260
uint32_t
261
ar5212GetTsf32(struct ath_hal *ah)
262
{
263
return OS_REG_READ(ah, AR_TSF_L32);
264
}
265
266
void
267
ar5212SetTsf64(struct ath_hal *ah, uint64_t tsf64)
268
{
269
OS_REG_WRITE(ah, AR_TSF_L32, tsf64 & 0xffffffff);
270
OS_REG_WRITE(ah, AR_TSF_U32, (tsf64 >> 32) & 0xffffffff);
271
}
272
273
/*
274
* Reset the current hardware tsf for stamlme.
275
*/
276
void
277
ar5212ResetTsf(struct ath_hal *ah)
278
{
279
280
uint32_t val = OS_REG_READ(ah, AR_BEACON);
281
282
OS_REG_WRITE(ah, AR_BEACON, val | AR_BEACON_RESET_TSF);
283
/*
284
* When resetting the TSF, write twice to the
285
* corresponding register; each write to the RESET_TSF bit toggles
286
* the internal signal to cause a reset of the TSF - but if the signal
287
* is left high, it will reset the TSF on the next chip reset also!
288
* writing the bit an even number of times fixes this issue
289
*/
290
OS_REG_WRITE(ah, AR_BEACON, val | AR_BEACON_RESET_TSF);
291
}
292
293
/*
294
* Set or clear hardware basic rate bit
295
* Set hardware basic rate set if basic rate is found
296
* and basic rate is equal or less than 2Mbps
297
*/
298
void
299
ar5212SetBasicRate(struct ath_hal *ah, HAL_RATE_SET *rs)
300
{
301
const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan;
302
uint32_t reg;
303
uint8_t xset;
304
int i;
305
306
if (chan == AH_NULL || !IEEE80211_IS_CHAN_CCK(chan))
307
return;
308
xset = 0;
309
for (i = 0; i < rs->rs_count; i++) {
310
uint8_t rset = rs->rs_rates[i];
311
/* Basic rate defined? */
312
if ((rset & 0x80) && (rset &= 0x7f) >= xset)
313
xset = rset;
314
}
315
/*
316
* Set the h/w bit to reflect whether or not the basic
317
* rate is found to be equal or less than 2Mbps.
318
*/
319
reg = OS_REG_READ(ah, AR_STA_ID1);
320
if (xset && xset/2 <= 2)
321
OS_REG_WRITE(ah, AR_STA_ID1, reg | AR_STA_ID1_BASE_RATE_11B);
322
else
323
OS_REG_WRITE(ah, AR_STA_ID1, reg &~ AR_STA_ID1_BASE_RATE_11B);
324
}
325
326
/*
327
* Grab a semi-random value from hardware registers - may not
328
* change often
329
*/
330
uint32_t
331
ar5212GetRandomSeed(struct ath_hal *ah)
332
{
333
uint32_t nf;
334
335
nf = (OS_REG_READ(ah, AR_PHY(25)) >> 19) & 0x1ff;
336
if (nf & 0x100)
337
nf = 0 - ((nf ^ 0x1ff) + 1);
338
return (OS_REG_READ(ah, AR_TSF_U32) ^
339
OS_REG_READ(ah, AR_TSF_L32) ^ nf);
340
}
341
342
/*
343
* Detect if our card is present
344
*/
345
HAL_BOOL
346
ar5212DetectCardPresent(struct ath_hal *ah)
347
{
348
uint16_t macVersion, macRev;
349
uint32_t v;
350
351
/*
352
* Read the Silicon Revision register and compare that
353
* to what we read at attach time. If the same, we say
354
* a card/device is present.
355
*/
356
v = OS_REG_READ(ah, AR_SREV) & AR_SREV_ID;
357
macVersion = v >> AR_SREV_ID_S;
358
macRev = v & AR_SREV_REVISION;
359
return (AH_PRIVATE(ah)->ah_macVersion == macVersion &&
360
AH_PRIVATE(ah)->ah_macRev == macRev);
361
}
362
363
void
364
ar5212EnableMibCounters(struct ath_hal *ah)
365
{
366
/* NB: this just resets the mib counter machinery */
367
OS_REG_WRITE(ah, AR_MIBC,
368
~(AR_MIBC_COW | AR_MIBC_FMC | AR_MIBC_CMC | AR_MIBC_MCS) & 0x0f);
369
}
370
371
void
372
ar5212DisableMibCounters(struct ath_hal *ah)
373
{
374
OS_REG_WRITE(ah, AR_MIBC, AR_MIBC | AR_MIBC_CMC);
375
}
376
377
/*
378
* Update MIB Counters
379
*/
380
void
381
ar5212UpdateMibCounters(struct ath_hal *ah, HAL_MIB_STATS* stats)
382
{
383
stats->ackrcv_bad += OS_REG_READ(ah, AR_ACK_FAIL);
384
stats->rts_bad += OS_REG_READ(ah, AR_RTS_FAIL);
385
stats->fcs_bad += OS_REG_READ(ah, AR_FCS_FAIL);
386
stats->rts_good += OS_REG_READ(ah, AR_RTS_OK);
387
stats->beacons += OS_REG_READ(ah, AR_BEACON_CNT);
388
}
389
390
/*
391
* Detect if the HW supports spreading a CCK signal on channel 14
392
*/
393
HAL_BOOL
394
ar5212IsJapanChannelSpreadSupported(struct ath_hal *ah)
395
{
396
return AH_TRUE;
397
}
398
399
/*
400
* Get the rssi of frame curently being received.
401
*/
402
uint32_t
403
ar5212GetCurRssi(struct ath_hal *ah)
404
{
405
return (OS_REG_READ(ah, AR_PHY_CURRENT_RSSI) & 0xff);
406
}
407
408
u_int
409
ar5212GetDefAntenna(struct ath_hal *ah)
410
{
411
return (OS_REG_READ(ah, AR_DEF_ANTENNA) & 0x7);
412
}
413
414
void
415
ar5212SetDefAntenna(struct ath_hal *ah, u_int antenna)
416
{
417
OS_REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7));
418
}
419
420
HAL_ANT_SETTING
421
ar5212GetAntennaSwitch(struct ath_hal *ah)
422
{
423
return AH5212(ah)->ah_antControl;
424
}
425
426
HAL_BOOL
427
ar5212SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING setting)
428
{
429
struct ath_hal_5212 *ahp = AH5212(ah);
430
const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan;
431
432
if (!ahp->ah_phyPowerOn || chan == AH_NULL) {
433
/* PHY powered off, just stash settings */
434
ahp->ah_antControl = setting;
435
ahp->ah_diversity = (setting == HAL_ANT_VARIABLE);
436
return AH_TRUE;
437
}
438
return ar5212SetAntennaSwitchInternal(ah, setting, chan);
439
}
440
441
HAL_BOOL
442
ar5212IsSleepAfterBeaconBroken(struct ath_hal *ah)
443
{
444
return AH_TRUE;
445
}
446
447
HAL_BOOL
448
ar5212SetSifsTime(struct ath_hal *ah, u_int us)
449
{
450
struct ath_hal_5212 *ahp = AH5212(ah);
451
452
if (us > ath_hal_mac_usec(ah, 0xffff)) {
453
HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad SIFS time %u\n",
454
__func__, us);
455
ahp->ah_sifstime = (u_int) -1; /* restore default handling */
456
return AH_FALSE;
457
} else {
458
/* convert to system clocks */
459
OS_REG_WRITE(ah, AR_D_GBL_IFS_SIFS, ath_hal_mac_clks(ah, us-2));
460
ahp->ah_sifstime = us;
461
return AH_TRUE;
462
}
463
}
464
465
u_int
466
ar5212GetSifsTime(struct ath_hal *ah)
467
{
468
u_int clks = OS_REG_READ(ah, AR_D_GBL_IFS_SIFS) & 0xffff;
469
return ath_hal_mac_usec(ah, clks)+2; /* convert from system clocks */
470
}
471
472
HAL_BOOL
473
ar5212SetSlotTime(struct ath_hal *ah, u_int us)
474
{
475
struct ath_hal_5212 *ahp = AH5212(ah);
476
477
if (us < HAL_SLOT_TIME_6 || us > ath_hal_mac_usec(ah, 0xffff)) {
478
HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad slot time %u\n",
479
__func__, us);
480
ahp->ah_slottime = (u_int) -1; /* restore default handling */
481
return AH_FALSE;
482
} else {
483
/* convert to system clocks */
484
OS_REG_WRITE(ah, AR_D_GBL_IFS_SLOT, ath_hal_mac_clks(ah, us));
485
ahp->ah_slottime = us;
486
return AH_TRUE;
487
}
488
}
489
490
u_int
491
ar5212GetSlotTime(struct ath_hal *ah)
492
{
493
u_int clks = OS_REG_READ(ah, AR_D_GBL_IFS_SLOT) & 0xffff;
494
return ath_hal_mac_usec(ah, clks); /* convert from system clocks */
495
}
496
497
HAL_BOOL
498
ar5212SetAckTimeout(struct ath_hal *ah, u_int us)
499
{
500
struct ath_hal_5212 *ahp = AH5212(ah);
501
502
if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) {
503
HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad ack timeout %u\n",
504
__func__, us);
505
ahp->ah_acktimeout = (u_int) -1; /* restore default handling */
506
return AH_FALSE;
507
} else {
508
/* convert to system clocks */
509
OS_REG_RMW_FIELD(ah, AR_TIME_OUT,
510
AR_TIME_OUT_ACK, ath_hal_mac_clks(ah, us));
511
ahp->ah_acktimeout = us;
512
return AH_TRUE;
513
}
514
}
515
516
u_int
517
ar5212GetAckTimeout(struct ath_hal *ah)
518
{
519
u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_ACK);
520
return ath_hal_mac_usec(ah, clks); /* convert from system clocks */
521
}
522
523
u_int
524
ar5212GetAckCTSRate(struct ath_hal *ah)
525
{
526
return ((AH5212(ah)->ah_staId1Defaults & AR_STA_ID1_ACKCTS_6MB) == 0);
527
}
528
529
HAL_BOOL
530
ar5212SetAckCTSRate(struct ath_hal *ah, u_int high)
531
{
532
struct ath_hal_5212 *ahp = AH5212(ah);
533
534
if (high) {
535
OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB);
536
ahp->ah_staId1Defaults &= ~AR_STA_ID1_ACKCTS_6MB;
537
} else {
538
OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB);
539
ahp->ah_staId1Defaults |= AR_STA_ID1_ACKCTS_6MB;
540
}
541
return AH_TRUE;
542
}
543
544
HAL_BOOL
545
ar5212SetCTSTimeout(struct ath_hal *ah, u_int us)
546
{
547
struct ath_hal_5212 *ahp = AH5212(ah);
548
549
if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) {
550
HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad cts timeout %u\n",
551
__func__, us);
552
ahp->ah_ctstimeout = (u_int) -1; /* restore default handling */
553
return AH_FALSE;
554
} else {
555
/* convert to system clocks */
556
OS_REG_RMW_FIELD(ah, AR_TIME_OUT,
557
AR_TIME_OUT_CTS, ath_hal_mac_clks(ah, us));
558
ahp->ah_ctstimeout = us;
559
return AH_TRUE;
560
}
561
}
562
563
u_int
564
ar5212GetCTSTimeout(struct ath_hal *ah)
565
{
566
u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_CTS);
567
return ath_hal_mac_usec(ah, clks); /* convert from system clocks */
568
}
569
570
/* Setup decompression for given key index */
571
HAL_BOOL
572
ar5212SetDecompMask(struct ath_hal *ah, uint16_t keyidx, int en)
573
{
574
struct ath_hal_5212 *ahp = AH5212(ah);
575
576
if (keyidx >= HAL_DECOMP_MASK_SIZE)
577
return AH_FALSE;
578
OS_REG_WRITE(ah, AR_DCM_A, keyidx);
579
OS_REG_WRITE(ah, AR_DCM_D, en ? AR_DCM_D_EN : 0);
580
ahp->ah_decompMask[keyidx] = en;
581
582
return AH_TRUE;
583
}
584
585
/* Setup coverage class */
586
void
587
ar5212SetCoverageClass(struct ath_hal *ah, uint8_t coverageclass, int now)
588
{
589
uint32_t slot, timeout, eifs;
590
u_int clkRate;
591
592
AH_PRIVATE(ah)->ah_coverageClass = coverageclass;
593
594
if (now) {
595
if (AH_PRIVATE(ah)->ah_coverageClass == 0)
596
return;
597
598
/* Don't apply coverage class to non A channels */
599
if (!IEEE80211_IS_CHAN_A(AH_PRIVATE(ah)->ah_curchan))
600
return;
601
602
/* Get core clock rate */
603
clkRate = ath_hal_mac_clks(ah, 1);
604
605
/* Compute EIFS */
606
slot = coverageclass * 3 * clkRate;
607
eifs = coverageclass * 6 * clkRate;
608
if (IEEE80211_IS_CHAN_HALF(AH_PRIVATE(ah)->ah_curchan)) {
609
slot += IFS_SLOT_HALF_RATE;
610
eifs += IFS_EIFS_HALF_RATE;
611
} else if (IEEE80211_IS_CHAN_QUARTER(AH_PRIVATE(ah)->ah_curchan)) {
612
slot += IFS_SLOT_QUARTER_RATE;
613
eifs += IFS_EIFS_QUARTER_RATE;
614
} else { /* full rate */
615
slot += IFS_SLOT_FULL_RATE;
616
eifs += IFS_EIFS_FULL_RATE;
617
}
618
619
/*
620
* Add additional time for air propagation for ACK and CTS
621
* timeouts. This value is in core clocks.
622
*/
623
timeout = ACK_CTS_TIMEOUT_11A + (coverageclass * 3 * clkRate);
624
625
/*
626
* Write the values: slot, eifs, ack/cts timeouts.
627
*/
628
OS_REG_WRITE(ah, AR_D_GBL_IFS_SLOT, slot);
629
OS_REG_WRITE(ah, AR_D_GBL_IFS_EIFS, eifs);
630
OS_REG_WRITE(ah, AR_TIME_OUT,
631
SM(timeout, AR_TIME_OUT_CTS)
632
| SM(timeout, AR_TIME_OUT_ACK));
633
}
634
}
635
636
HAL_STATUS
637
ar5212SetQuiet(struct ath_hal *ah, uint32_t period, uint32_t duration,
638
uint32_t nextStart, HAL_QUIET_FLAG flag)
639
{
640
OS_REG_WRITE(ah, AR_QUIET2, period | (duration << AR_QUIET2_QUIET_DUR_S));
641
if (flag & HAL_QUIET_ENABLE) {
642
OS_REG_WRITE(ah, AR_QUIET1, nextStart | (1 << 16));
643
}
644
else {
645
OS_REG_WRITE(ah, AR_QUIET1, nextStart);
646
}
647
return HAL_OK;
648
}
649
650
void
651
ar5212SetPCUConfig(struct ath_hal *ah)
652
{
653
ar5212SetOperatingMode(ah, AH_PRIVATE(ah)->ah_opmode);
654
}
655
656
/*
657
* Return whether an external 32KHz crystal should be used
658
* to reduce power consumption when sleeping. We do so if
659
* the crystal is present (obtained from EEPROM) and if we
660
* are not running as an AP and are configured to use it.
661
*/
662
HAL_BOOL
663
ar5212Use32KHzclock(struct ath_hal *ah, HAL_OPMODE opmode)
664
{
665
if (opmode != HAL_M_HOSTAP) {
666
struct ath_hal_5212 *ahp = AH5212(ah);
667
return ath_hal_eepromGetFlag(ah, AR_EEP_32KHZCRYSTAL) &&
668
(ahp->ah_enable32kHzClock == USE_32KHZ ||
669
ahp->ah_enable32kHzClock == AUTO_32KHZ);
670
} else
671
return AH_FALSE;
672
}
673
674
/*
675
* If 32KHz clock exists, use it to lower power consumption during sleep
676
*
677
* Note: If clock is set to 32 KHz, delays on accessing certain
678
* baseband registers (27-31, 124-127) are required.
679
*/
680
void
681
ar5212SetupClock(struct ath_hal *ah, HAL_OPMODE opmode)
682
{
683
if (ar5212Use32KHzclock(ah, opmode)) {
684
/*
685
* Enable clocks to be turned OFF in BB during sleep
686
* and also enable turning OFF 32MHz/40MHz Refclk
687
* from A2.
688
*/
689
OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f);
690
OS_REG_WRITE(ah, AR_PHY_REFCLKPD,
691
IS_RAD5112_ANY(ah) || IS_5413(ah) ? 0x14 : 0x18);
692
OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32, 1);
693
OS_REG_WRITE(ah, AR_TSF_PARM, 61); /* 32 KHz TSF incr */
694
OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_SEL, 1);
695
696
if (IS_2413(ah) || IS_5413(ah) || IS_2417(ah)) {
697
OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT, 0x26);
698
OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0d);
699
OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x07);
700
OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0x3f);
701
/* # Set sleep clock rate to 32 KHz. */
702
OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0x2);
703
} else {
704
OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT, 0x0a);
705
OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0c);
706
OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x03);
707
OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0x20);
708
OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0x3);
709
}
710
} else {
711
OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0x0);
712
OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_SEL, 0);
713
714
OS_REG_WRITE(ah, AR_TSF_PARM, 1); /* 32MHz TSF inc */
715
716
OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f);
717
OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT, 0x7f);
718
719
if (IS_2417(ah))
720
OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0a);
721
else if (IS_HB63(ah))
722
OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x32);
723
else
724
OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e);
725
OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x0c);
726
OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0xff);
727
OS_REG_WRITE(ah, AR_PHY_REFCLKPD,
728
IS_RAD5112_ANY(ah) || IS_5413(ah) || IS_2417(ah) ? 0x14 : 0x18);
729
OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32,
730
IS_RAD5112_ANY(ah) || IS_5413(ah) ? 39 : 31);
731
}
732
}
733
734
/*
735
* If 32KHz clock exists, turn it off and turn back on the 32Mhz
736
*/
737
void
738
ar5212RestoreClock(struct ath_hal *ah, HAL_OPMODE opmode)
739
{
740
if (ar5212Use32KHzclock(ah, opmode)) {
741
/* # Set sleep clock rate back to 32 MHz. */
742
OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0);
743
OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_SEL, 0);
744
745
OS_REG_WRITE(ah, AR_TSF_PARM, 1); /* 32 MHz TSF incr */
746
OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32,
747
IS_RAD5112_ANY(ah) || IS_5413(ah) ? 39 : 31);
748
749
/*
750
* Restore BB registers to power-on defaults
751
*/
752
OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f);
753
OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT, 0x7f);
754
OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e);
755
OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x0c);
756
OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0xff);
757
OS_REG_WRITE(ah, AR_PHY_REFCLKPD,
758
IS_RAD5112_ANY(ah) || IS_5413(ah) ? 0x14 : 0x18);
759
}
760
}
761
762
/*
763
* Adjust NF based on statistical values for 5GHz frequencies.
764
* Default method: this may be overridden by the rf backend.
765
*/
766
int16_t
767
ar5212GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c)
768
{
769
static const struct {
770
uint16_t freqLow;
771
int16_t adjust;
772
} adjustDef[] = {
773
{ 5790, 11 }, /* NB: ordered high -> low */
774
{ 5730, 10 },
775
{ 5690, 9 },
776
{ 5660, 8 },
777
{ 5610, 7 },
778
{ 5530, 5 },
779
{ 5450, 4 },
780
{ 5379, 2 },
781
{ 5209, 0 },
782
{ 3000, 1 },
783
{ 0, 0 },
784
};
785
int i;
786
787
for (i = 0; c->channel <= adjustDef[i].freqLow; i++)
788
;
789
return adjustDef[i].adjust;
790
}
791
792
HAL_STATUS
793
ar5212GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
794
uint32_t capability, uint32_t *result)
795
{
796
#define MACVERSION(ah) AH_PRIVATE(ah)->ah_macVersion
797
struct ath_hal_5212 *ahp = AH5212(ah);
798
const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
799
const struct ar5212AniState *ani;
800
801
switch (type) {
802
case HAL_CAP_CIPHER: /* cipher handled in hardware */
803
switch (capability) {
804
case HAL_CIPHER_AES_CCM:
805
return pCap->halCipherAesCcmSupport ?
806
HAL_OK : HAL_ENOTSUPP;
807
case HAL_CIPHER_AES_OCB:
808
case HAL_CIPHER_TKIP:
809
case HAL_CIPHER_WEP:
810
case HAL_CIPHER_MIC:
811
case HAL_CIPHER_CLR:
812
return HAL_OK;
813
default:
814
return HAL_ENOTSUPP;
815
}
816
case HAL_CAP_TKIP_MIC: /* handle TKIP MIC in hardware */
817
switch (capability) {
818
case 0: /* hardware capability */
819
return HAL_OK;
820
case 1:
821
return (ahp->ah_staId1Defaults &
822
AR_STA_ID1_CRPT_MIC_ENABLE) ? HAL_OK : HAL_ENXIO;
823
}
824
return HAL_EINVAL;
825
case HAL_CAP_TKIP_SPLIT: /* hardware TKIP uses split keys */
826
switch (capability) {
827
case 0: /* hardware capability */
828
return pCap->halTkipMicTxRxKeySupport ?
829
HAL_ENXIO : HAL_OK;
830
case 1: /* current setting */
831
return (ahp->ah_miscMode &
832
AR_MISC_MODE_MIC_NEW_LOC_ENABLE) ? HAL_ENXIO : HAL_OK;
833
}
834
return HAL_EINVAL;
835
case HAL_CAP_WME_TKIPMIC: /* hardware can do TKIP MIC w/ WMM */
836
/* XXX move to capability bit */
837
return MACVERSION(ah) > AR_SREV_VERSION_VENICE ||
838
(MACVERSION(ah) == AR_SREV_VERSION_VENICE &&
839
AH_PRIVATE(ah)->ah_macRev >= 8) ? HAL_OK : HAL_ENOTSUPP;
840
case HAL_CAP_DIVERSITY: /* hardware supports fast diversity */
841
switch (capability) {
842
case 0: /* hardware capability */
843
return HAL_OK;
844
case 1: /* current setting */
845
return ahp->ah_diversity ? HAL_OK : HAL_ENXIO;
846
case HAL_CAP_STRONG_DIV:
847
*result = OS_REG_READ(ah, AR_PHY_RESTART);
848
*result = MS(*result, AR_PHY_RESTART_DIV_GC);
849
return HAL_OK;
850
}
851
return HAL_EINVAL;
852
case HAL_CAP_DIAG:
853
*result = AH_PRIVATE(ah)->ah_diagreg;
854
return HAL_OK;
855
case HAL_CAP_TPC:
856
switch (capability) {
857
case 0: /* hardware capability */
858
return HAL_OK;
859
case 1:
860
return ahp->ah_tpcEnabled ? HAL_OK : HAL_ENXIO;
861
}
862
return HAL_OK;
863
case HAL_CAP_PHYDIAG: /* radar pulse detection capability */
864
switch (capability) {
865
case HAL_CAP_RADAR:
866
return ath_hal_eepromGetFlag(ah, AR_EEP_AMODE) ?
867
HAL_OK: HAL_ENXIO;
868
case HAL_CAP_AR:
869
return (ath_hal_eepromGetFlag(ah, AR_EEP_GMODE) ||
870
ath_hal_eepromGetFlag(ah, AR_EEP_BMODE)) ?
871
HAL_OK: HAL_ENXIO;
872
}
873
return HAL_ENXIO;
874
case HAL_CAP_MCAST_KEYSRCH: /* multicast frame keycache search */
875
switch (capability) {
876
case 0: /* hardware capability */
877
return pCap->halMcastKeySrchSupport ? HAL_OK : HAL_ENXIO;
878
case 1:
879
return (ahp->ah_staId1Defaults &
880
AR_STA_ID1_MCAST_KSRCH) ? HAL_OK : HAL_ENXIO;
881
}
882
return HAL_EINVAL;
883
case HAL_CAP_TSF_ADJUST: /* hardware has beacon tsf adjust */
884
switch (capability) {
885
case 0: /* hardware capability */
886
return pCap->halTsfAddSupport ? HAL_OK : HAL_ENOTSUPP;
887
case 1:
888
return (ahp->ah_miscMode & AR_MISC_MODE_TX_ADD_TSF) ?
889
HAL_OK : HAL_ENXIO;
890
}
891
return HAL_EINVAL;
892
case HAL_CAP_TPC_ACK:
893
*result = MS(ahp->ah_macTPC, AR_TPC_ACK);
894
return HAL_OK;
895
case HAL_CAP_TPC_CTS:
896
*result = MS(ahp->ah_macTPC, AR_TPC_CTS);
897
return HAL_OK;
898
case HAL_CAP_INTMIT: /* interference mitigation */
899
switch (capability) {
900
case HAL_CAP_INTMIT_PRESENT: /* hardware capability */
901
return HAL_OK;
902
case HAL_CAP_INTMIT_ENABLE:
903
return (ahp->ah_procPhyErr & HAL_ANI_ENA) ?
904
HAL_OK : HAL_ENXIO;
905
case HAL_CAP_INTMIT_NOISE_IMMUNITY_LEVEL:
906
case HAL_CAP_INTMIT_OFDM_WEAK_SIGNAL_LEVEL:
907
case HAL_CAP_INTMIT_CCK_WEAK_SIGNAL_THR:
908
case HAL_CAP_INTMIT_FIRSTEP_LEVEL:
909
case HAL_CAP_INTMIT_SPUR_IMMUNITY_LEVEL:
910
ani = ar5212AniGetCurrentState(ah);
911
if (ani == AH_NULL)
912
return HAL_ENXIO;
913
switch (capability) {
914
case 2: *result = ani->noiseImmunityLevel; break;
915
case 3: *result = !ani->ofdmWeakSigDetectOff; break;
916
case 4: *result = ani->cckWeakSigThreshold; break;
917
case 5: *result = ani->firstepLevel; break;
918
case 6: *result = ani->spurImmunityLevel; break;
919
}
920
return HAL_OK;
921
}
922
return HAL_EINVAL;
923
default:
924
return ath_hal_getcapability(ah, type, capability, result);
925
}
926
#undef MACVERSION
927
}
928
929
HAL_BOOL
930
ar5212SetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
931
uint32_t capability, uint32_t setting, HAL_STATUS *status)
932
{
933
#define N(a) (sizeof(a)/sizeof(a[0]))
934
struct ath_hal_5212 *ahp = AH5212(ah);
935
const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
936
uint32_t v;
937
938
switch (type) {
939
case HAL_CAP_TKIP_MIC: /* handle TKIP MIC in hardware */
940
if (setting)
941
ahp->ah_staId1Defaults |= AR_STA_ID1_CRPT_MIC_ENABLE;
942
else
943
ahp->ah_staId1Defaults &= ~AR_STA_ID1_CRPT_MIC_ENABLE;
944
return AH_TRUE;
945
case HAL_CAP_TKIP_SPLIT: /* hardware TKIP uses split keys */
946
if (!pCap->halTkipMicTxRxKeySupport)
947
return AH_FALSE;
948
/* NB: true =>'s use split key cache layout */
949
if (setting)
950
ahp->ah_miscMode &= ~AR_MISC_MODE_MIC_NEW_LOC_ENABLE;
951
else
952
ahp->ah_miscMode |= AR_MISC_MODE_MIC_NEW_LOC_ENABLE;
953
/* NB: write here so keys can be setup w/o a reset */
954
OS_REG_WRITE(ah, AR_MISC_MODE, OS_REG_READ(ah, AR_MISC_MODE) | ahp->ah_miscMode);
955
return AH_TRUE;
956
case HAL_CAP_DIVERSITY:
957
switch (capability) {
958
case 0:
959
return AH_FALSE;
960
case 1: /* setting */
961
if (ahp->ah_phyPowerOn) {
962
if (capability == HAL_CAP_STRONG_DIV) {
963
v = OS_REG_READ(ah, AR_PHY_CCK_DETECT);
964
if (setting)
965
v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
966
else
967
v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
968
OS_REG_WRITE(ah, AR_PHY_CCK_DETECT, v);
969
}
970
}
971
ahp->ah_diversity = (setting != 0);
972
return AH_TRUE;
973
974
case HAL_CAP_STRONG_DIV:
975
if (! ahp->ah_phyPowerOn)
976
return AH_FALSE;
977
v = OS_REG_READ(ah, AR_PHY_RESTART);
978
v &= ~AR_PHY_RESTART_DIV_GC;
979
v |= SM(setting, AR_PHY_RESTART_DIV_GC);
980
OS_REG_WRITE(ah, AR_PHY_RESTART, v);
981
return AH_TRUE;
982
default:
983
return AH_FALSE;
984
}
985
case HAL_CAP_DIAG: /* hardware diagnostic support */
986
/*
987
* NB: could split this up into virtual capabilities,
988
* (e.g. 1 => ACK, 2 => CTS, etc.) but it hardly
989
* seems worth the additional complexity.
990
*/
991
AH_PRIVATE(ah)->ah_diagreg = setting;
992
OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg);
993
return AH_TRUE;
994
case HAL_CAP_TPC:
995
ahp->ah_tpcEnabled = (setting != 0);
996
return AH_TRUE;
997
case HAL_CAP_MCAST_KEYSRCH: /* multicast frame keycache search */
998
if (setting)
999
ahp->ah_staId1Defaults |= AR_STA_ID1_MCAST_KSRCH;
1000
else
1001
ahp->ah_staId1Defaults &= ~AR_STA_ID1_MCAST_KSRCH;
1002
return AH_TRUE;
1003
case HAL_CAP_TPC_ACK:
1004
case HAL_CAP_TPC_CTS:
1005
setting += ahp->ah_txPowerIndexOffset;
1006
if (setting > 63)
1007
setting = 63;
1008
if (type == HAL_CAP_TPC_ACK) {
1009
ahp->ah_macTPC &= AR_TPC_ACK;
1010
ahp->ah_macTPC |= MS(setting, AR_TPC_ACK);
1011
} else {
1012
ahp->ah_macTPC &= AR_TPC_CTS;
1013
ahp->ah_macTPC |= MS(setting, AR_TPC_CTS);
1014
}
1015
OS_REG_WRITE(ah, AR_TPC, ahp->ah_macTPC);
1016
return AH_TRUE;
1017
case HAL_CAP_INTMIT: { /* interference mitigation */
1018
/* This maps the public ANI commands to the internal ANI commands */
1019
/* Private: HAL_ANI_CMD; Public: HAL_CAP_INTMIT_CMD */
1020
static const HAL_ANI_CMD cmds[] = {
1021
HAL_ANI_PRESENT,
1022
HAL_ANI_MODE,
1023
HAL_ANI_NOISE_IMMUNITY_LEVEL,
1024
HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
1025
HAL_ANI_CCK_WEAK_SIGNAL_THR,
1026
HAL_ANI_FIRSTEP_LEVEL,
1027
HAL_ANI_SPUR_IMMUNITY_LEVEL,
1028
};
1029
return capability < N(cmds) ?
1030
AH5212(ah)->ah_aniControl(ah, cmds[capability], setting) :
1031
AH_FALSE;
1032
}
1033
case HAL_CAP_TSF_ADJUST: /* hardware has beacon tsf adjust */
1034
if (pCap->halTsfAddSupport) {
1035
if (setting)
1036
ahp->ah_miscMode |= AR_MISC_MODE_TX_ADD_TSF;
1037
else
1038
ahp->ah_miscMode &= ~AR_MISC_MODE_TX_ADD_TSF;
1039
return AH_TRUE;
1040
}
1041
/* fall thru... */
1042
default:
1043
return ath_hal_setcapability(ah, type, capability,
1044
setting, status);
1045
}
1046
#undef N
1047
}
1048
1049
HAL_BOOL
1050
ar5212GetDiagState(struct ath_hal *ah, int request,
1051
const void *args, uint32_t argsize,
1052
void **result, uint32_t *resultsize)
1053
{
1054
struct ath_hal_5212 *ahp = AH5212(ah);
1055
HAL_ANI_STATS *astats;
1056
1057
(void) ahp;
1058
if (ath_hal_getdiagstate(ah, request, args, argsize, result, resultsize))
1059
return AH_TRUE;
1060
switch (request) {
1061
case HAL_DIAG_EEPROM:
1062
case HAL_DIAG_EEPROM_EXP_11A:
1063
case HAL_DIAG_EEPROM_EXP_11B:
1064
case HAL_DIAG_EEPROM_EXP_11G:
1065
case HAL_DIAG_RFGAIN:
1066
return ath_hal_eepromDiag(ah, request,
1067
args, argsize, result, resultsize);
1068
case HAL_DIAG_RFGAIN_CURSTEP:
1069
*result = __DECONST(void *, ahp->ah_gainValues.currStep);
1070
*resultsize = (*result == AH_NULL) ?
1071
0 : sizeof(GAIN_OPTIMIZATION_STEP);
1072
return AH_TRUE;
1073
case HAL_DIAG_PCDAC:
1074
*result = ahp->ah_pcdacTable;
1075
*resultsize = ahp->ah_pcdacTableSize;
1076
return AH_TRUE;
1077
case HAL_DIAG_TXRATES:
1078
*result = &ahp->ah_ratesArray[0];
1079
*resultsize = sizeof(ahp->ah_ratesArray);
1080
return AH_TRUE;
1081
case HAL_DIAG_ANI_CURRENT:
1082
*result = ar5212AniGetCurrentState(ah);
1083
*resultsize = (*result == AH_NULL) ?
1084
0 : sizeof(struct ar5212AniState);
1085
return AH_TRUE;
1086
case HAL_DIAG_ANI_STATS:
1087
OS_MEMZERO(&ahp->ext_ani_stats, sizeof(ahp->ext_ani_stats));
1088
astats = ar5212AniGetCurrentStats(ah);
1089
if (astats == NULL) {
1090
*result = NULL;
1091
*resultsize = 0;
1092
} else {
1093
OS_MEMCPY(&ahp->ext_ani_stats, astats, sizeof(HAL_ANI_STATS));
1094
*result = &ahp->ext_ani_stats;
1095
*resultsize = sizeof(ahp->ext_ani_stats);
1096
}
1097
return AH_TRUE;
1098
case HAL_DIAG_ANI_CMD:
1099
if (argsize != 2*sizeof(uint32_t))
1100
return AH_FALSE;
1101
AH5212(ah)->ah_aniControl(ah, ((const uint32_t *)args)[0],
1102
((const uint32_t *)args)[1]);
1103
return AH_TRUE;
1104
case HAL_DIAG_ANI_PARAMS:
1105
/*
1106
* NB: We assume struct ar5212AniParams is identical
1107
* to HAL_ANI_PARAMS; if they diverge then we'll need
1108
* to handle it here
1109
*/
1110
if (argsize == 0 && args == AH_NULL) {
1111
struct ar5212AniState *aniState =
1112
ar5212AniGetCurrentState(ah);
1113
if (aniState == AH_NULL)
1114
return AH_FALSE;
1115
*result = __DECONST(void *, aniState->params);
1116
*resultsize = sizeof(struct ar5212AniParams);
1117
return AH_TRUE;
1118
} else {
1119
if (argsize != sizeof(struct ar5212AniParams))
1120
return AH_FALSE;
1121
return ar5212AniSetParams(ah, args, args);
1122
}
1123
break;
1124
}
1125
return AH_FALSE;
1126
}
1127
1128
/*
1129
* Check whether there's an in-progress NF completion.
1130
*
1131
* Returns AH_TRUE if there's a in-progress NF calibration, AH_FALSE
1132
* otherwise.
1133
*/
1134
HAL_BOOL
1135
ar5212IsNFCalInProgress(struct ath_hal *ah)
1136
{
1137
if (OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF)
1138
return AH_TRUE;
1139
return AH_FALSE;
1140
}
1141
1142
/*
1143
* Wait for an in-progress NF calibration to complete.
1144
*
1145
* The completion function waits "i" times 10uS.
1146
* It returns AH_TRUE if the NF calibration completed (or was never
1147
* in progress); AH_FALSE if it was still in progress after "i" checks.
1148
*/
1149
HAL_BOOL
1150
ar5212WaitNFCalComplete(struct ath_hal *ah, int i)
1151
{
1152
int j;
1153
if (i <= 0)
1154
i = 1; /* it should run at least once */
1155
for (j = 0; j < i; j++) {
1156
if (! ar5212IsNFCalInProgress(ah))
1157
return AH_TRUE;
1158
OS_DELAY(10);
1159
}
1160
return AH_FALSE;
1161
}
1162
1163
void
1164
ar5212EnableDfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe)
1165
{
1166
uint32_t val;
1167
val = OS_REG_READ(ah, AR_PHY_RADAR_0);
1168
1169
if (pe->pe_firpwr != HAL_PHYERR_PARAM_NOVAL) {
1170
val &= ~AR_PHY_RADAR_0_FIRPWR;
1171
val |= SM(pe->pe_firpwr, AR_PHY_RADAR_0_FIRPWR);
1172
}
1173
if (pe->pe_rrssi != HAL_PHYERR_PARAM_NOVAL) {
1174
val &= ~AR_PHY_RADAR_0_RRSSI;
1175
val |= SM(pe->pe_rrssi, AR_PHY_RADAR_0_RRSSI);
1176
}
1177
if (pe->pe_height != HAL_PHYERR_PARAM_NOVAL) {
1178
val &= ~AR_PHY_RADAR_0_HEIGHT;
1179
val |= SM(pe->pe_height, AR_PHY_RADAR_0_HEIGHT);
1180
}
1181
if (pe->pe_prssi != HAL_PHYERR_PARAM_NOVAL) {
1182
val &= ~AR_PHY_RADAR_0_PRSSI;
1183
val |= SM(pe->pe_prssi, AR_PHY_RADAR_0_PRSSI);
1184
}
1185
if (pe->pe_inband != HAL_PHYERR_PARAM_NOVAL) {
1186
val &= ~AR_PHY_RADAR_0_INBAND;
1187
val |= SM(pe->pe_inband, AR_PHY_RADAR_0_INBAND);
1188
}
1189
if (pe->pe_enabled)
1190
val |= AR_PHY_RADAR_0_ENA;
1191
else
1192
val &= ~ AR_PHY_RADAR_0_ENA;
1193
1194
if (IS_5413(ah)) {
1195
if (pe->pe_blockradar == 1)
1196
OS_REG_SET_BIT(ah, AR_PHY_RADAR_2,
1197
AR_PHY_RADAR_2_BLOCKOFDMWEAK);
1198
else
1199
OS_REG_CLR_BIT(ah, AR_PHY_RADAR_2,
1200
AR_PHY_RADAR_2_BLOCKOFDMWEAK);
1201
1202
if (pe->pe_en_relstep_check == 1)
1203
OS_REG_SET_BIT(ah, AR_PHY_RADAR_2,
1204
AR_PHY_RADAR_2_ENRELSTEPCHK);
1205
else
1206
OS_REG_CLR_BIT(ah, AR_PHY_RADAR_2,
1207
AR_PHY_RADAR_2_ENRELSTEPCHK);
1208
1209
if (pe->pe_usefir128 == 1)
1210
OS_REG_SET_BIT(ah, AR_PHY_RADAR_2,
1211
AR_PHY_RADAR_2_USEFIR128);
1212
else
1213
OS_REG_CLR_BIT(ah, AR_PHY_RADAR_2,
1214
AR_PHY_RADAR_2_USEFIR128);
1215
1216
if (pe->pe_enmaxrssi == 1)
1217
OS_REG_SET_BIT(ah, AR_PHY_RADAR_2,
1218
AR_PHY_RADAR_2_ENMAXRSSI);
1219
else
1220
OS_REG_CLR_BIT(ah, AR_PHY_RADAR_2,
1221
AR_PHY_RADAR_2_ENMAXRSSI);
1222
1223
if (pe->pe_enrelpwr == 1)
1224
OS_REG_SET_BIT(ah, AR_PHY_RADAR_2,
1225
AR_PHY_RADAR_2_ENRELPWRCHK);
1226
else
1227
OS_REG_CLR_BIT(ah, AR_PHY_RADAR_2,
1228
AR_PHY_RADAR_2_ENRELPWRCHK);
1229
1230
if (pe->pe_relpwr != HAL_PHYERR_PARAM_NOVAL)
1231
OS_REG_RMW_FIELD(ah, AR_PHY_RADAR_2,
1232
AR_PHY_RADAR_2_RELPWR, pe->pe_relpwr);
1233
1234
if (pe->pe_relstep != HAL_PHYERR_PARAM_NOVAL)
1235
OS_REG_RMW_FIELD(ah, AR_PHY_RADAR_2,
1236
AR_PHY_RADAR_2_RELSTEP, pe->pe_relstep);
1237
1238
if (pe->pe_maxlen != HAL_PHYERR_PARAM_NOVAL)
1239
OS_REG_RMW_FIELD(ah, AR_PHY_RADAR_2,
1240
AR_PHY_RADAR_2_MAXLEN, pe->pe_maxlen);
1241
}
1242
1243
OS_REG_WRITE(ah, AR_PHY_RADAR_0, val);
1244
}
1245
1246
/*
1247
* Parameters for the AR5212 PHY.
1248
*/
1249
#define AR5212_DFS_FIRPWR -35
1250
#define AR5212_DFS_RRSSI 20
1251
#define AR5212_DFS_HEIGHT 14
1252
#define AR5212_DFS_PRSSI 6
1253
#define AR5212_DFS_INBAND 4
1254
1255
/*
1256
* Default parameters for the AR5413 PHY.
1257
*/
1258
#define AR5413_DFS_FIRPWR -34
1259
#define AR5413_DFS_RRSSI 20
1260
#define AR5413_DFS_HEIGHT 10
1261
#define AR5413_DFS_PRSSI 15
1262
#define AR5413_DFS_INBAND 6
1263
#define AR5413_DFS_RELPWR 8
1264
#define AR5413_DFS_RELSTEP 31
1265
#define AR5413_DFS_MAXLEN 255
1266
1267
HAL_BOOL
1268
ar5212GetDfsDefaultThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe)
1269
{
1270
1271
if (IS_5413(ah)) {
1272
pe->pe_firpwr = AR5413_DFS_FIRPWR;
1273
pe->pe_rrssi = AR5413_DFS_RRSSI;
1274
pe->pe_height = AR5413_DFS_HEIGHT;
1275
pe->pe_prssi = AR5413_DFS_PRSSI;
1276
pe->pe_inband = AR5413_DFS_INBAND;
1277
pe->pe_relpwr = AR5413_DFS_RELPWR;
1278
pe->pe_relstep = AR5413_DFS_RELSTEP;
1279
pe->pe_maxlen = AR5413_DFS_MAXLEN;
1280
pe->pe_usefir128 = 0;
1281
pe->pe_blockradar = 1;
1282
pe->pe_enmaxrssi = 1;
1283
pe->pe_enrelpwr = 1;
1284
pe->pe_en_relstep_check = 0;
1285
} else {
1286
pe->pe_firpwr = AR5212_DFS_FIRPWR;
1287
pe->pe_rrssi = AR5212_DFS_RRSSI;
1288
pe->pe_height = AR5212_DFS_HEIGHT;
1289
pe->pe_prssi = AR5212_DFS_PRSSI;
1290
pe->pe_inband = AR5212_DFS_INBAND;
1291
pe->pe_relpwr = 0;
1292
pe->pe_relstep = 0;
1293
pe->pe_maxlen = 0;
1294
pe->pe_usefir128 = 0;
1295
pe->pe_blockradar = 0;
1296
pe->pe_enmaxrssi = 0;
1297
pe->pe_enrelpwr = 0;
1298
pe->pe_en_relstep_check = 0;
1299
}
1300
1301
return (AH_TRUE);
1302
}
1303
1304
void
1305
ar5212GetDfsThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe)
1306
{
1307
uint32_t val,temp;
1308
1309
val = OS_REG_READ(ah, AR_PHY_RADAR_0);
1310
1311
temp = MS(val,AR_PHY_RADAR_0_FIRPWR);
1312
temp |= 0xFFFFFF80;
1313
pe->pe_firpwr = temp;
1314
pe->pe_rrssi = MS(val, AR_PHY_RADAR_0_RRSSI);
1315
pe->pe_height = MS(val, AR_PHY_RADAR_0_HEIGHT);
1316
pe->pe_prssi = MS(val, AR_PHY_RADAR_0_PRSSI);
1317
pe->pe_inband = MS(val, AR_PHY_RADAR_0_INBAND);
1318
pe->pe_enabled = !! (val & AR_PHY_RADAR_0_ENA);
1319
1320
pe->pe_relpwr = 0;
1321
pe->pe_relstep = 0;
1322
pe->pe_maxlen = 0;
1323
pe->pe_usefir128 = 0;
1324
pe->pe_blockradar = 0;
1325
pe->pe_enmaxrssi = 0;
1326
pe->pe_enrelpwr = 0;
1327
pe->pe_en_relstep_check = 0;
1328
pe->pe_extchannel = AH_FALSE;
1329
1330
if (IS_5413(ah)) {
1331
val = OS_REG_READ(ah, AR_PHY_RADAR_2);
1332
pe->pe_relpwr = !! MS(val, AR_PHY_RADAR_2_RELPWR);
1333
pe->pe_relstep = !! MS(val, AR_PHY_RADAR_2_RELSTEP);
1334
pe->pe_maxlen = !! MS(val, AR_PHY_RADAR_2_MAXLEN);
1335
1336
pe->pe_usefir128 = !! (val & AR_PHY_RADAR_2_USEFIR128);
1337
pe->pe_blockradar = !! (val & AR_PHY_RADAR_2_BLOCKOFDMWEAK);
1338
pe->pe_enmaxrssi = !! (val & AR_PHY_RADAR_2_ENMAXRSSI);
1339
pe->pe_enrelpwr = !! (val & AR_PHY_RADAR_2_ENRELPWRCHK);
1340
pe->pe_en_relstep_check =
1341
!! (val & AR_PHY_RADAR_2_ENRELSTEPCHK);
1342
}
1343
}
1344
1345
/*
1346
* Process the radar phy error and extract the pulse duration.
1347
*/
1348
HAL_BOOL
1349
ar5212ProcessRadarEvent(struct ath_hal *ah, struct ath_rx_status *rxs,
1350
uint64_t fulltsf, const char *buf, HAL_DFS_EVENT *event)
1351
{
1352
uint8_t dur;
1353
uint8_t rssi;
1354
1355
/* Check whether the given phy error is a radar event */
1356
if ((rxs->rs_phyerr != HAL_PHYERR_RADAR) &&
1357
(rxs->rs_phyerr != HAL_PHYERR_FALSE_RADAR_EXT))
1358
return AH_FALSE;
1359
1360
/*
1361
* The first byte is the pulse width - if there's
1362
* no data, simply set the duration to 0
1363
*/
1364
if (rxs->rs_datalen >= 1)
1365
/* The pulse width is byte 0 of the data */
1366
dur = ((uint8_t) buf[0]) & 0xff;
1367
else
1368
dur = 0;
1369
1370
/* Pulse RSSI is the normal reported RSSI */
1371
rssi = (uint8_t) rxs->rs_rssi;
1372
1373
/* 0 duration/rssi is not a valid radar event */
1374
if (dur == 0 && rssi == 0)
1375
return AH_FALSE;
1376
1377
HALDEBUG(ah, HAL_DEBUG_DFS, "%s: rssi=%d, dur=%d\n",
1378
__func__, rssi, dur);
1379
1380
/* Record the event */
1381
event->re_full_ts = fulltsf;
1382
event->re_ts = rxs->rs_tstamp;
1383
event->re_rssi = rssi;
1384
event->re_dur = dur;
1385
event->re_flags = HAL_DFS_EVENT_PRICH;
1386
1387
return AH_TRUE;
1388
}
1389
1390
/*
1391
* Return whether 5GHz fast-clock (44MHz) is enabled.
1392
* It's always disabled for AR5212 series NICs.
1393
*/
1394
HAL_BOOL
1395
ar5212IsFastClockEnabled(struct ath_hal *ah)
1396
{
1397
return AH_FALSE;
1398
}
1399
1400
/*
1401
* Return what percentage of the extension channel is busy.
1402
* This is always disabled for AR5212 series NICs.
1403
*/
1404
uint32_t
1405
ar5212Get11nExtBusy(struct ath_hal *ah)
1406
{
1407
return 0;
1408
}
1409
1410
/*
1411
* Channel survey support.
1412
*/
1413
HAL_BOOL
1414
ar5212GetMibCycleCounts(struct ath_hal *ah, HAL_SURVEY_SAMPLE *hsample)
1415
{
1416
struct ath_hal_5212 *ahp = AH5212(ah);
1417
u_int32_t good = AH_TRUE;
1418
1419
/* XXX freeze/unfreeze mib counters */
1420
uint32_t rc = OS_REG_READ(ah, AR_RCCNT);
1421
uint32_t rf = OS_REG_READ(ah, AR_RFCNT);
1422
uint32_t tf = OS_REG_READ(ah, AR_TFCNT);
1423
uint32_t cc = OS_REG_READ(ah, AR_CCCNT); /* read cycles last */
1424
1425
if (ahp->ah_cycleCount == 0 || ahp->ah_cycleCount > cc) {
1426
/*
1427
* Cycle counter wrap (or initial call); it's not possible
1428
* to accurately calculate a value because the registers
1429
* right shift rather than wrap--so punt and return 0.
1430
*/
1431
HALDEBUG(ah, HAL_DEBUG_ANY,
1432
"%s: cycle counter wrap. ExtBusy = 0\n", __func__);
1433
good = AH_FALSE;
1434
} else {
1435
hsample->cycle_count = cc - ahp->ah_cycleCount;
1436
hsample->chan_busy = rc - ahp->ah_ctlBusy;
1437
hsample->ext_chan_busy = 0;
1438
hsample->rx_busy = rf - ahp->ah_rxBusy;
1439
hsample->tx_busy = tf - ahp->ah_txBusy;
1440
}
1441
1442
/*
1443
* Keep a copy of the MIB results so the next sample has something
1444
* to work from.
1445
*/
1446
ahp->ah_cycleCount = cc;
1447
ahp->ah_rxBusy = rf;
1448
ahp->ah_ctlBusy = rc;
1449
ahp->ah_txBusy = tf;
1450
1451
return (good);
1452
}
1453
1454
void
1455
ar5212SetChainMasks(struct ath_hal *ah, uint32_t tx_chainmask,
1456
uint32_t rx_chainmask)
1457
{
1458
}
1459
1460
/*
1461
* Get the current NAV value from the hardware.
1462
*
1463
* 0xdeadbeef indicates the hardware is currently powered off.
1464
*/
1465
u_int
1466
ar5212GetNav(struct ath_hal *ah)
1467
{
1468
uint32_t reg;
1469
1470
reg = OS_REG_READ(ah, AR_NAV);
1471
1472
if (reg == 0xdeadbeef)
1473
return (0);
1474
return (reg);
1475
}
1476
1477
/*
1478
* Set the current NAV value to the hardware.
1479
*/
1480
void
1481
ar5212SetNav(struct ath_hal *ah, u_int val)
1482
{
1483
1484
OS_REG_WRITE(ah, AR_NAV, val);
1485
}
1486
1487