Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/dev/ath/ath_hal/ar5211/ar5211_recv.c
39566 views
1
/*-
2
* SPDX-License-Identifier: ISC
3
*
4
* Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
5
* Copyright (c) 2002-2006 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_desc.h"
24
25
#include "ar5211/ar5211.h"
26
#include "ar5211/ar5211reg.h"
27
#include "ar5211/ar5211desc.h"
28
29
/*
30
* Get the RXDP.
31
*/
32
uint32_t
33
ar5211GetRxDP(struct ath_hal *ah, HAL_RX_QUEUE qtype)
34
{
35
36
HALASSERT(qtype == HAL_RX_QUEUE_HP);
37
return OS_REG_READ(ah, AR_RXDP);
38
}
39
40
/*
41
* Set the RxDP.
42
*/
43
void
44
ar5211SetRxDP(struct ath_hal *ah, uint32_t rxdp, HAL_RX_QUEUE qtype)
45
{
46
47
HALASSERT(qtype == HAL_RX_QUEUE_HP);
48
OS_REG_WRITE(ah, AR_RXDP, rxdp);
49
HALASSERT(OS_REG_READ(ah, AR_RXDP) == rxdp);
50
}
51
52
/*
53
* Set Receive Enable bits.
54
*/
55
void
56
ar5211EnableReceive(struct ath_hal *ah)
57
{
58
OS_REG_WRITE(ah, AR_CR, AR_CR_RXE);
59
}
60
61
/*
62
* Stop Receive at the DMA engine
63
*/
64
HAL_BOOL
65
ar5211StopDmaReceive(struct ath_hal *ah)
66
{
67
OS_REG_WRITE(ah, AR_CR, AR_CR_RXD); /* Set receive disable bit */
68
if (!ath_hal_wait(ah, AR_CR, AR_CR_RXE, 0)) {
69
#ifdef AH_DEBUG
70
ath_hal_printf(ah, "%s failed to stop in 10ms\n"
71
"AR_CR=0x%08X\nAR_DIAG_SW=0x%08X\n"
72
, __func__
73
, OS_REG_READ(ah, AR_CR)
74
, OS_REG_READ(ah, AR_DIAG_SW)
75
);
76
#endif
77
return AH_FALSE;
78
} else {
79
return AH_TRUE;
80
}
81
}
82
83
/*
84
* Start Transmit at the PCU engine (unpause receive)
85
*/
86
void
87
ar5211StartPcuReceive(struct ath_hal *ah, HAL_BOOL is_scanning)
88
{
89
OS_REG_WRITE(ah, AR_DIAG_SW,
90
OS_REG_READ(ah, AR_DIAG_SW) & ~(AR_DIAG_SW_DIS_RX));
91
}
92
93
/*
94
* Stop Transmit at the PCU engine (pause receive)
95
*/
96
void
97
ar5211StopPcuReceive(struct ath_hal *ah)
98
{
99
OS_REG_WRITE(ah, AR_DIAG_SW,
100
OS_REG_READ(ah, AR_DIAG_SW) | AR_DIAG_SW_DIS_RX);
101
}
102
103
/*
104
* Set multicast filter 0 (lower 32-bits)
105
* filter 1 (upper 32-bits)
106
*/
107
void
108
ar5211SetMulticastFilter(struct ath_hal *ah, uint32_t filter0, uint32_t filter1)
109
{
110
OS_REG_WRITE(ah, AR_MCAST_FIL0, filter0);
111
OS_REG_WRITE(ah, AR_MCAST_FIL1, filter1);
112
}
113
114
/*
115
* Clear multicast filter by index
116
*/
117
HAL_BOOL
118
ar5211ClrMulticastFilterIndex(struct ath_hal *ah, uint32_t ix)
119
{
120
uint32_t val;
121
122
if (ix >= 64)
123
return AH_FALSE;
124
if (ix >= 32) {
125
val = OS_REG_READ(ah, AR_MCAST_FIL1);
126
OS_REG_WRITE(ah, AR_MCAST_FIL1, (val &~ (1<<(ix-32))));
127
} else {
128
val = OS_REG_READ(ah, AR_MCAST_FIL0);
129
OS_REG_WRITE(ah, AR_MCAST_FIL0, (val &~ (1<<ix)));
130
}
131
return AH_TRUE;
132
}
133
134
/*
135
* Set multicast filter by index
136
*/
137
HAL_BOOL
138
ar5211SetMulticastFilterIndex(struct ath_hal *ah, uint32_t ix)
139
{
140
uint32_t val;
141
142
if (ix >= 64)
143
return AH_FALSE;
144
if (ix >= 32) {
145
val = OS_REG_READ(ah, AR_MCAST_FIL1);
146
OS_REG_WRITE(ah, AR_MCAST_FIL1, (val | (1<<(ix-32))));
147
} else {
148
val = OS_REG_READ(ah, AR_MCAST_FIL0);
149
OS_REG_WRITE(ah, AR_MCAST_FIL0, (val | (1<<ix)));
150
}
151
return AH_TRUE;
152
}
153
154
/*
155
* Get receive filter.
156
*/
157
uint32_t
158
ar5211GetRxFilter(struct ath_hal *ah)
159
{
160
return OS_REG_READ(ah, AR_RX_FILTER);
161
}
162
163
/*
164
* Set receive filter.
165
*/
166
void
167
ar5211SetRxFilter(struct ath_hal *ah, uint32_t bits)
168
{
169
OS_REG_WRITE(ah, AR_RX_FILTER, bits);
170
}
171
172
/*
173
* Initialize RX descriptor, by clearing the status and clearing
174
* the size. This is not strictly HW dependent, but we want the
175
* control and status words to be opaque above the hal.
176
*/
177
HAL_BOOL
178
ar5211SetupRxDesc(struct ath_hal *ah, struct ath_desc *ds,
179
uint32_t size, u_int flags)
180
{
181
struct ar5211_desc *ads = AR5211DESC(ds);
182
183
ads->ds_ctl0 = 0;
184
ads->ds_ctl1 = size & AR_BufLen;
185
if (ads->ds_ctl1 != size) {
186
HALDEBUG(ah, HAL_DEBUG_ANY, "%s: buffer size %u too large\n",
187
__func__, size);
188
return AH_FALSE;
189
}
190
if (flags & HAL_RXDESC_INTREQ)
191
ads->ds_ctl1 |= AR_RxInterReq;
192
ads->ds_status0 = ads->ds_status1 = 0;
193
194
return AH_TRUE;
195
}
196
197
/*
198
* Process an RX descriptor, and return the status to the caller.
199
* Copy some hardware specific items into the software portion
200
* of the descriptor.
201
*
202
* NB: the caller is responsible for validating the memory contents
203
* of the descriptor (e.g. flushing any cached copy).
204
*/
205
HAL_STATUS
206
ar5211ProcRxDesc(struct ath_hal *ah, struct ath_desc *ds,
207
uint32_t pa, struct ath_desc *nds, uint64_t tsf,
208
struct ath_rx_status *rs)
209
{
210
struct ar5211_desc *ads = AR5211DESC(ds);
211
struct ar5211_desc *ands = AR5211DESC(nds);
212
213
if ((ads->ds_status1 & AR_Done) == 0)
214
return HAL_EINPROGRESS;
215
/*
216
* Given the use of a self-linked tail be very sure that the hw is
217
* done with this descriptor; the hw may have done this descriptor
218
* once and picked it up again...make sure the hw has moved on.
219
*/
220
if ((ands->ds_status1 & AR_Done) == 0 && OS_REG_READ(ah, AR_RXDP) == pa)
221
return HAL_EINPROGRESS;
222
223
rs->rs_datalen = ads->ds_status0 & AR_DataLen;
224
rs->rs_tstamp = MS(ads->ds_status1, AR_RcvTimestamp);
225
rs->rs_status = 0;
226
if ((ads->ds_status1 & AR_FrmRcvOK) == 0) {
227
if (ads->ds_status1 & AR_CRCErr)
228
rs->rs_status |= HAL_RXERR_CRC;
229
else if (ads->ds_status1 & AR_DecryptCRCErr)
230
rs->rs_status |= HAL_RXERR_DECRYPT;
231
else {
232
rs->rs_status |= HAL_RXERR_PHY;
233
rs->rs_phyerr = MS(ads->ds_status1, AR_PHYErr);
234
}
235
}
236
/* XXX what about KeyCacheMiss? */
237
rs->rs_rssi = MS(ads->ds_status0, AR_RcvSigStrength);
238
if (ads->ds_status1 & AR_KeyIdxValid)
239
rs->rs_keyix = MS(ads->ds_status1, AR_KeyIdx);
240
else
241
rs->rs_keyix = HAL_RXKEYIX_INVALID;
242
/* NB: caller expected to do rate table mapping */
243
rs->rs_rate = MS(ads->ds_status0, AR_RcvRate);
244
rs->rs_antenna = MS(ads->ds_status0, AR_RcvAntenna);
245
rs->rs_more = (ads->ds_status0 & AR_More) ? 1 : 0;
246
247
return HAL_OK;
248
}
249
250