1 | /* |
2 | * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting |
3 | * Copyright (c) 2002-2008 Atheros Communications, Inc. |
4 | * |
5 | * Permission to use, copy, modify, and/or distribute this software for any |
6 | * purpose with or without fee is hereby granted, provided that the above |
7 | * copyright notice and this permission notice appear in all copies. |
8 | * |
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
16 | * |
17 | * $Id: ar5416_recv.c,v 1.1.1.1 2008/12/11 04:46:48 alc Exp $ |
18 | */ |
19 | #include "opt_ah.h" |
20 | |
21 | #include "ah.h" |
22 | #include "ah_desc.h" |
23 | #include "ah_internal.h" |
24 | |
25 | #include "ar5416/ar5416.h" |
26 | #include "ar5416/ar5416reg.h" |
27 | #include "ar5416/ar5416desc.h" |
28 | |
29 | /* |
30 | * Start receive at the PCU engine |
31 | */ |
32 | void |
33 | ar5416StartPcuReceive(struct ath_hal *ah) |
34 | { |
35 | struct ath_hal_private *ahp = AH_PRIVATE(ah); |
36 | |
37 | HALDEBUG(ah, HAL_DEBUG_RX, "%s: Start PCU Receive \n" , __func__); |
38 | ar5212EnableMibCounters(ah); |
39 | /* NB: restore current settings */ |
40 | ar5416AniReset(ah, ahp->ah_curchan, ahp->ah_opmode, AH_TRUE); |
41 | /* |
42 | * NB: must do after enabling phy errors to avoid rx |
43 | * frames w/ corrupted descriptor status. |
44 | */ |
45 | OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT); |
46 | } |
47 | |
48 | /* |
49 | * Stop receive at the PCU engine |
50 | * and abort current frame in PCU |
51 | */ |
52 | void |
53 | ar5416StopPcuReceive(struct ath_hal *ah) |
54 | { |
55 | OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT); |
56 | |
57 | HALDEBUG(ah, HAL_DEBUG_RX, "%s: Stop PCU Receive \n" , __func__); |
58 | ar5212DisableMibCounters(ah); |
59 | } |
60 | |
61 | /* |
62 | * Initialize RX descriptor, by clearing the status and setting |
63 | * the size (and any other flags). |
64 | */ |
65 | HAL_BOOL |
66 | ar5416SetupRxDesc(struct ath_hal *ah, struct ath_desc *ds, |
67 | uint32_t size, u_int flags) |
68 | { |
69 | struct ar5416_desc *ads = AR5416DESC(ds); |
70 | |
71 | HALASSERT((size &~ AR_BufLen) == 0); |
72 | |
73 | ads->ds_ctl1 = size & AR_BufLen; |
74 | if (flags & HAL_RXDESC_INTREQ) |
75 | ads->ds_ctl1 |= AR_RxIntrReq; |
76 | |
77 | /* this should be enough */ |
78 | ads->ds_rxstatus8 &= ~AR_RxDone; |
79 | |
80 | return AH_TRUE; |
81 | } |
82 | |
83 | /* |
84 | * Process an RX descriptor, and return the status to the caller. |
85 | * Copy some hardware specific items into the software portion |
86 | * of the descriptor. |
87 | * |
88 | * NB: the caller is responsible for validating the memory contents |
89 | * of the descriptor (e.g. flushing any cached copy). |
90 | */ |
91 | HAL_STATUS |
92 | ar5416ProcRxDesc(struct ath_hal *ah, struct ath_desc *ds, |
93 | uint32_t pa, struct ath_desc *nds, uint64_t tsf, |
94 | struct ath_rx_status *rs) |
95 | { |
96 | struct ar5416_desc *ads = AR5416DESC(ds); |
97 | struct ar5416_desc *ands = AR5416DESC(nds); |
98 | |
99 | if ((ads->ds_rxstatus8 & AR_RxDone) == 0) |
100 | return HAL_EINPROGRESS; |
101 | /* |
102 | * Given the use of a self-linked tail be very sure that the hw is |
103 | * done with this descriptor; the hw may have done this descriptor |
104 | * once and picked it up again...make sure the hw has moved on. |
105 | */ |
106 | if ((ands->ds_rxstatus8 & AR_RxDone) == 0 |
107 | && OS_REG_READ(ah, AR_RXDP) == pa) |
108 | return HAL_EINPROGRESS; |
109 | |
110 | rs->rs_status = 0; |
111 | rs->rs_flags = 0; |
112 | |
113 | rs->rs_datalen = ads->ds_rxstatus1 & AR_DataLen; |
114 | rs->rs_tstamp = ads->AR_RcvTimestamp; |
115 | |
116 | /* XXX what about KeyCacheMiss? */ |
117 | |
118 | rs->rs_rssi = MS(ads->ds_rxstatus4, AR_RxRSSICombined); |
119 | rs->rs_rssi_ctl[0] = MS(ads->ds_rxstatus0, AR_RxRSSIAnt00); |
120 | rs->rs_rssi_ctl[1] = MS(ads->ds_rxstatus0, AR_RxRSSIAnt01); |
121 | rs->rs_rssi_ctl[2] = MS(ads->ds_rxstatus0, AR_RxRSSIAnt02); |
122 | rs->rs_rssi_ext[0] = MS(ads->ds_rxstatus4, AR_RxRSSIAnt10); |
123 | rs->rs_rssi_ext[1] = MS(ads->ds_rxstatus4, AR_RxRSSIAnt11); |
124 | rs->rs_rssi_ext[2] = MS(ads->ds_rxstatus4, AR_RxRSSIAnt12); |
125 | |
126 | if (ads->ds_rxstatus8 & AR_RxKeyIdxValid) |
127 | rs->rs_keyix = MS(ads->ds_rxstatus8, AR_KeyIdx); |
128 | else |
129 | rs->rs_keyix = HAL_RXKEYIX_INVALID; |
130 | |
131 | /* NB: caller expected to do rate table mapping */ |
132 | rs->rs_rate = RXSTATUS_RATE(ah, ads); |
133 | rs->rs_more = (ads->ds_rxstatus1 & AR_RxMore) ? 1 : 0; |
134 | |
135 | rs->rs_isaggr = (ads->ds_rxstatus8 & AR_RxAggr) ? 1 : 0; |
136 | rs->rs_moreaggr = (ads->ds_rxstatus8 & AR_RxMoreAggr) ? 1 : 0; |
137 | rs->rs_antenna = MS(ads->ds_rxstatus3, AR_RxAntenna); |
138 | |
139 | if (ads->ds_rxstatus3 & AR_GI) |
140 | rs->rs_flags |= HAL_RX_GI; |
141 | if (ads->ds_rxstatus3 & AR_2040) |
142 | rs->rs_flags |= HAL_RX_2040; |
143 | |
144 | if (ads->ds_rxstatus8 & AR_PreDelimCRCErr) |
145 | rs->rs_flags |= HAL_RX_DELIM_CRC_PRE; |
146 | if (ads->ds_rxstatus8 & AR_PostDelimCRCErr) |
147 | rs->rs_flags |= HAL_RX_DELIM_CRC_POST; |
148 | if (ads->ds_rxstatus8 & AR_DecryptBusyErr) |
149 | rs->rs_flags |= HAL_RX_DECRYPT_BUSY; |
150 | if (ads->ds_rxstatus8 & AR_HiRxChain) |
151 | rs->rs_flags |= HAL_RX_HI_RX_CHAIN; |
152 | |
153 | if ((ads->ds_rxstatus8 & AR_RxFrameOK) == 0) { |
154 | /* |
155 | * These four bits should not be set together. The |
156 | * 5416 spec states a Michael error can only occur if |
157 | * DecryptCRCErr not set (and TKIP is used). Experience |
158 | * indicates however that you can also get Michael errors |
159 | * when a CRC error is detected, but these are specious. |
160 | * Consequently we filter them out here so we don't |
161 | * confuse and/or complicate drivers. |
162 | */ |
163 | if (ads->ds_rxstatus8 & AR_CRCErr) |
164 | rs->rs_status |= HAL_RXERR_CRC; |
165 | else if (ads->ds_rxstatus8 & AR_PHYErr) { |
166 | u_int phyerr; |
167 | |
168 | rs->rs_status |= HAL_RXERR_PHY; |
169 | phyerr = MS(ads->ds_rxstatus8, AR_PHYErrCode); |
170 | rs->rs_phyerr = phyerr; |
171 | } else if (ads->ds_rxstatus8 & AR_DecryptCRCErr) |
172 | rs->rs_status |= HAL_RXERR_DECRYPT; |
173 | else if (ads->ds_rxstatus8 & AR_MichaelErr) |
174 | rs->rs_status |= HAL_RXERR_MIC; |
175 | } |
176 | |
177 | return HAL_OK; |
178 | } |
179 | |