1 1.1 alc /* 2 1.1 alc * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting 3 1.1 alc * Copyright (c) 2002-2006 Atheros Communications, Inc. 4 1.1 alc * 5 1.1 alc * Permission to use, copy, modify, and/or distribute this software for any 6 1.1 alc * purpose with or without fee is hereby granted, provided that the above 7 1.1 alc * copyright notice and this permission notice appear in all copies. 8 1.1 alc * 9 1.1 alc * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 1.1 alc * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 1.1 alc * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 1.1 alc * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 1.1 alc * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 1.1 alc * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 1.1 alc * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 1.1 alc * 17 1.1 alc * $Id: ar5211_recv.c,v 1.1.1.1 2008/12/11 04:46:33 alc Exp $ 18 1.1 alc */ 19 1.1 alc #include "opt_ah.h" 20 1.1 alc 21 1.1 alc #include "ah.h" 22 1.1 alc #include "ah_internal.h" 23 1.1 alc #include "ah_desc.h" 24 1.1 alc 25 1.1 alc #include "ar5211/ar5211.h" 26 1.1 alc #include "ar5211/ar5211reg.h" 27 1.1 alc #include "ar5211/ar5211desc.h" 28 1.1 alc 29 1.1 alc /* 30 1.1 alc * Get the RXDP. 31 1.1 alc */ 32 1.1 alc uint32_t 33 1.1 alc ar5211GetRxDP(struct ath_hal *ah) 34 1.1 alc { 35 1.1 alc return OS_REG_READ(ah, AR_RXDP); 36 1.1 alc } 37 1.1 alc 38 1.1 alc /* 39 1.1 alc * Set the RxDP. 40 1.1 alc */ 41 1.1 alc void 42 1.1 alc ar5211SetRxDP(struct ath_hal *ah, uint32_t rxdp) 43 1.1 alc { 44 1.1 alc OS_REG_WRITE(ah, AR_RXDP, rxdp); 45 1.1 alc HALASSERT(OS_REG_READ(ah, AR_RXDP) == rxdp); 46 1.1 alc } 47 1.1 alc 48 1.1 alc 49 1.1 alc /* 50 1.1 alc * Set Receive Enable bits. 51 1.1 alc */ 52 1.1 alc void 53 1.1 alc ar5211EnableReceive(struct ath_hal *ah) 54 1.1 alc { 55 1.1 alc OS_REG_WRITE(ah, AR_CR, AR_CR_RXE); 56 1.1 alc } 57 1.1 alc 58 1.1 alc /* 59 1.1 alc * Stop Receive at the DMA engine 60 1.1 alc */ 61 1.1 alc HAL_BOOL 62 1.1 alc ar5211StopDmaReceive(struct ath_hal *ah) 63 1.1 alc { 64 1.1 alc OS_REG_WRITE(ah, AR_CR, AR_CR_RXD); /* Set receive disable bit */ 65 1.1 alc if (!ath_hal_wait(ah, AR_CR, AR_CR_RXE, 0)) { 66 1.1 alc #ifdef AH_DEBUG 67 1.1 alc ath_hal_printf(ah, "%s failed to stop in 10ms\n" 68 1.1 alc "AR_CR=0x%08X\nAR_DIAG_SW=0x%08X\n" 69 1.1 alc , __func__ 70 1.1 alc , OS_REG_READ(ah, AR_CR) 71 1.1 alc , OS_REG_READ(ah, AR_DIAG_SW) 72 1.1 alc ); 73 1.1 alc #endif 74 1.1 alc return AH_FALSE; 75 1.1 alc } else { 76 1.1 alc return AH_TRUE; 77 1.1 alc } 78 1.1 alc } 79 1.1 alc 80 1.1 alc /* 81 1.1 alc * Start Transmit at the PCU engine (unpause receive) 82 1.1 alc */ 83 1.1 alc void 84 1.1 alc ar5211StartPcuReceive(struct ath_hal *ah) 85 1.1 alc { 86 1.1 alc OS_REG_WRITE(ah, AR_DIAG_SW, 87 1.1 alc OS_REG_READ(ah, AR_DIAG_SW) & ~(AR_DIAG_SW_DIS_RX)); 88 1.1 alc } 89 1.1 alc 90 1.1 alc /* 91 1.1 alc * Stop Transmit at the PCU engine (pause receive) 92 1.1 alc */ 93 1.1 alc void 94 1.1 alc ar5211StopPcuReceive(struct ath_hal *ah) 95 1.1 alc { 96 1.1 alc OS_REG_WRITE(ah, AR_DIAG_SW, 97 1.1 alc OS_REG_READ(ah, AR_DIAG_SW) | AR_DIAG_SW_DIS_RX); 98 1.1 alc } 99 1.1 alc 100 1.1 alc /* 101 1.1 alc * Set multicast filter 0 (lower 32-bits) 102 1.1 alc * filter 1 (upper 32-bits) 103 1.1 alc */ 104 1.1 alc void 105 1.1 alc ar5211SetMulticastFilter(struct ath_hal *ah, uint32_t filter0, uint32_t filter1) 106 1.1 alc { 107 1.1 alc OS_REG_WRITE(ah, AR_MCAST_FIL0, filter0); 108 1.1 alc OS_REG_WRITE(ah, AR_MCAST_FIL1, filter1); 109 1.1 alc } 110 1.1 alc 111 1.1 alc /* 112 1.1 alc * Clear multicast filter by index 113 1.1 alc */ 114 1.1 alc HAL_BOOL 115 1.1 alc ar5211ClrMulticastFilterIndex(struct ath_hal *ah, uint32_t ix) 116 1.1 alc { 117 1.1 alc uint32_t val; 118 1.1 alc 119 1.1 alc if (ix >= 64) 120 1.1 alc return AH_FALSE; 121 1.1 alc if (ix >= 32) { 122 1.1 alc val = OS_REG_READ(ah, AR_MCAST_FIL1); 123 1.1 alc OS_REG_WRITE(ah, AR_MCAST_FIL1, (val &~ (1<<(ix-32)))); 124 1.1 alc } else { 125 1.1 alc val = OS_REG_READ(ah, AR_MCAST_FIL0); 126 1.1 alc OS_REG_WRITE(ah, AR_MCAST_FIL0, (val &~ (1<<ix))); 127 1.1 alc } 128 1.1 alc return AH_TRUE; 129 1.1 alc } 130 1.1 alc 131 1.1 alc /* 132 1.1 alc * Set multicast filter by index 133 1.1 alc */ 134 1.1 alc HAL_BOOL 135 1.1 alc ar5211SetMulticastFilterIndex(struct ath_hal *ah, uint32_t ix) 136 1.1 alc { 137 1.1 alc uint32_t val; 138 1.1 alc 139 1.1 alc if (ix >= 64) 140 1.1 alc return AH_FALSE; 141 1.1 alc if (ix >= 32) { 142 1.1 alc val = OS_REG_READ(ah, AR_MCAST_FIL1); 143 1.1 alc OS_REG_WRITE(ah, AR_MCAST_FIL1, (val | (1<<(ix-32)))); 144 1.1 alc } else { 145 1.1 alc val = OS_REG_READ(ah, AR_MCAST_FIL0); 146 1.1 alc OS_REG_WRITE(ah, AR_MCAST_FIL0, (val | (1<<ix))); 147 1.1 alc } 148 1.1 alc return AH_TRUE; 149 1.1 alc } 150 1.1 alc 151 1.1 alc /* 152 1.1 alc * Get receive filter. 153 1.1 alc */ 154 1.1 alc uint32_t 155 1.1 alc ar5211GetRxFilter(struct ath_hal *ah) 156 1.1 alc { 157 1.1 alc return OS_REG_READ(ah, AR_RX_FILTER); 158 1.1 alc } 159 1.1 alc 160 1.1 alc /* 161 1.1 alc * Set receive filter. 162 1.1 alc */ 163 1.1 alc void 164 1.1 alc ar5211SetRxFilter(struct ath_hal *ah, uint32_t bits) 165 1.1 alc { 166 1.1 alc OS_REG_WRITE(ah, AR_RX_FILTER, bits); 167 1.1 alc } 168 1.1 alc 169 1.1 alc /* 170 1.1 alc * Initialize RX descriptor, by clearing the status and clearing 171 1.1 alc * the size. This is not strictly HW dependent, but we want the 172 1.1 alc * control and status words to be opaque above the hal. 173 1.1 alc */ 174 1.1 alc HAL_BOOL 175 1.1 alc ar5211SetupRxDesc(struct ath_hal *ah, struct ath_desc *ds, 176 1.1 alc uint32_t size, u_int flags) 177 1.1 alc { 178 1.1 alc struct ar5211_desc *ads = AR5211DESC(ds); 179 1.1 alc 180 1.1 alc ads->ds_ctl0 = 0; 181 1.1 alc ads->ds_ctl1 = size & AR_BufLen; 182 1.1 alc if (ads->ds_ctl1 != size) { 183 1.1 alc HALDEBUG(ah, HAL_DEBUG_ANY, "%s: buffer size %u too large\n", 184 1.1 alc __func__, size); 185 1.1 alc return AH_FALSE; 186 1.1 alc } 187 1.1 alc if (flags & HAL_RXDESC_INTREQ) 188 1.1 alc ads->ds_ctl1 |= AR_RxInterReq; 189 1.1 alc ads->ds_status0 = ads->ds_status1 = 0; 190 1.1 alc 191 1.1 alc return AH_TRUE; 192 1.1 alc } 193 1.1 alc 194 1.1 alc /* 195 1.1 alc * Process an RX descriptor, and return the status to the caller. 196 1.1 alc * Copy some hardware specific items into the software portion 197 1.1 alc * of the descriptor. 198 1.1 alc * 199 1.1 alc * NB: the caller is responsible for validating the memory contents 200 1.1 alc * of the descriptor (e.g. flushing any cached copy). 201 1.1 alc */ 202 1.1 alc HAL_STATUS 203 1.1 alc ar5211ProcRxDesc(struct ath_hal *ah, struct ath_desc *ds, 204 1.1 alc uint32_t pa, struct ath_desc *nds, uint64_t tsf, 205 1.1 alc struct ath_rx_status *rs) 206 1.1 alc { 207 1.1 alc struct ar5211_desc *ads = AR5211DESC(ds); 208 1.1 alc struct ar5211_desc *ands = AR5211DESC(nds); 209 1.1 alc 210 1.1 alc if ((ads->ds_status1 & AR_Done) == 0) 211 1.1 alc return HAL_EINPROGRESS; 212 1.1 alc /* 213 1.1 alc * Given the use of a self-linked tail be very sure that the hw is 214 1.1 alc * done with this descriptor; the hw may have done this descriptor 215 1.1 alc * once and picked it up again...make sure the hw has moved on. 216 1.1 alc */ 217 1.1 alc if ((ands->ds_status1 & AR_Done) == 0 && OS_REG_READ(ah, AR_RXDP) == pa) 218 1.1 alc return HAL_EINPROGRESS; 219 1.1 alc 220 1.1 alc rs->rs_datalen = ads->ds_status0 & AR_DataLen; 221 1.1 alc rs->rs_tstamp = MS(ads->ds_status1, AR_RcvTimestamp); 222 1.1 alc rs->rs_status = 0; 223 1.1 alc if ((ads->ds_status1 & AR_FrmRcvOK) == 0) { 224 1.1 alc if (ads->ds_status1 & AR_CRCErr) 225 1.1 alc rs->rs_status |= HAL_RXERR_CRC; 226 1.1 alc else if (ads->ds_status1 & AR_DecryptCRCErr) 227 1.1 alc rs->rs_status |= HAL_RXERR_DECRYPT; 228 1.1 alc else { 229 1.1 alc rs->rs_status |= HAL_RXERR_PHY; 230 1.1 alc rs->rs_phyerr = MS(ads->ds_status1, AR_PHYErr); 231 1.1 alc } 232 1.1 alc } 233 1.1 alc /* XXX what about KeyCacheMiss? */ 234 1.1 alc rs->rs_rssi = MS(ads->ds_status0, AR_RcvSigStrength); 235 1.1 alc if (ads->ds_status1 & AR_KeyIdxValid) 236 1.1 alc rs->rs_keyix = MS(ads->ds_status1, AR_KeyIdx); 237 1.1 alc else 238 1.1 alc rs->rs_keyix = HAL_RXKEYIX_INVALID; 239 1.1 alc /* NB: caller expected to do rate table mapping */ 240 1.1 alc rs->rs_rate = MS(ads->ds_status0, AR_RcvRate); 241 1.1 alc rs->rs_antenna = MS(ads->ds_status0, AR_RcvAntenna); 242 1.1 alc rs->rs_more = (ads->ds_status0 & AR_More) ? 1 : 0; 243 1.1 alc 244 1.1 alc return HAL_OK; 245 1.1 alc } 246