1 1.1 alc /* 2 1.1 alc * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting 3 1.1 alc * Copyright (c) 2002-2004 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: ar5210_recv.c,v 1.1.1.1 2008/12/11 04:46:28 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 "ar5210/ar5210.h" 26 1.1 alc #include "ar5210/ar5210reg.h" 27 1.1 alc #include "ar5210/ar5210desc.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 ar5210GetRxDP(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 ar5210SetRxDP(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 } 46 1.1 alc 47 1.1 alc 48 1.1 alc /* 49 1.1 alc * Set Receive Enable bits. 50 1.1 alc */ 51 1.1 alc void 52 1.1 alc ar5210EnableReceive(struct ath_hal *ah) 53 1.1 alc { 54 1.1 alc OS_REG_WRITE(ah, AR_CR, AR_CR_RXE); 55 1.1 alc } 56 1.1 alc 57 1.1 alc /* 58 1.1 alc * Stop Receive at the DMA engine 59 1.1 alc */ 60 1.1 alc HAL_BOOL 61 1.1 alc ar5210StopDmaReceive(struct ath_hal *ah) 62 1.1 alc { 63 1.1 alc int i; 64 1.1 alc 65 1.1 alc OS_REG_WRITE(ah, AR_CR, AR_CR_RXD); /* Set receive disable bit */ 66 1.1 alc for (i = 0; i < 1000; i++) { 67 1.1 alc if ((OS_REG_READ(ah, AR_CR) & AR_CR_RXE) == 0) 68 1.1 alc return AH_TRUE; 69 1.1 alc OS_DELAY(10); 70 1.1 alc } 71 1.1 alc #ifdef AH_DEBUG 72 1.1 alc ath_hal_printf(ah, "ar5210: dma receive failed to stop in 10ms\n"); 73 1.1 alc ath_hal_printf(ah, "AR_CR=0x%x\n", OS_REG_READ(ah, AR_CR)); 74 1.1 alc ath_hal_printf(ah, "AR_DIAG_SW=0x%x\n", OS_REG_READ(ah, AR_DIAG_SW)); 75 1.1 alc #endif 76 1.1 alc return AH_FALSE; 77 1.1 alc } 78 1.1 alc 79 1.1 alc /* 80 1.1 alc * Start Transmit at the PCU engine (unpause receive) 81 1.1 alc */ 82 1.1 alc void 83 1.1 alc ar5210StartPcuReceive(struct ath_hal *ah) 84 1.1 alc { 85 1.1 alc OS_REG_WRITE(ah, AR_DIAG_SW, 86 1.1 alc OS_REG_READ(ah, AR_DIAG_SW) & ~(AR_DIAG_SW_DIS_RX)); 87 1.1 alc } 88 1.1 alc 89 1.1 alc /* 90 1.1 alc * Stop Transmit at the PCU engine (pause receive) 91 1.1 alc */ 92 1.1 alc void 93 1.1 alc ar5210StopPcuReceive(struct ath_hal *ah) 94 1.1 alc { 95 1.1 alc OS_REG_WRITE(ah, AR_DIAG_SW, 96 1.1 alc OS_REG_READ(ah, AR_DIAG_SW) | AR_DIAG_SW_DIS_RX); 97 1.1 alc } 98 1.1 alc 99 1.1 alc /* 100 1.1 alc * Set multicast filter 0 (lower 32-bits) 101 1.1 alc * filter 1 (upper 32-bits) 102 1.1 alc */ 103 1.1 alc void 104 1.1 alc ar5210SetMulticastFilter(struct ath_hal *ah, uint32_t filter0, uint32_t filter1) 105 1.1 alc { 106 1.1 alc OS_REG_WRITE(ah, AR_MCAST_FIL0, filter0); 107 1.1 alc OS_REG_WRITE(ah, AR_MCAST_FIL1, filter1); 108 1.1 alc } 109 1.1 alc 110 1.1 alc /* 111 1.1 alc * Clear multicast filter by index 112 1.1 alc */ 113 1.1 alc HAL_BOOL 114 1.1 alc ar5210ClrMulticastFilterIndex(struct ath_hal *ah, uint32_t ix) 115 1.1 alc { 116 1.1 alc uint32_t val; 117 1.1 alc 118 1.1 alc if (ix >= 64) 119 1.1 alc return AH_FALSE; 120 1.1 alc if (ix >= 32) { 121 1.1 alc val = OS_REG_READ(ah, AR_MCAST_FIL1); 122 1.1 alc OS_REG_WRITE(ah, AR_MCAST_FIL1, (val &~ (1<<(ix-32)))); 123 1.1 alc } else { 124 1.1 alc val = OS_REG_READ(ah, AR_MCAST_FIL0); 125 1.1 alc OS_REG_WRITE(ah, AR_MCAST_FIL0, (val &~ (1<<ix))); 126 1.1 alc } 127 1.1 alc return AH_TRUE; 128 1.1 alc } 129 1.1 alc 130 1.1 alc /* 131 1.1 alc * Set multicast filter by index 132 1.1 alc */ 133 1.1 alc HAL_BOOL 134 1.1 alc ar5210SetMulticastFilterIndex(struct ath_hal *ah, uint32_t ix) 135 1.1 alc { 136 1.1 alc uint32_t val; 137 1.1 alc 138 1.1 alc if (ix >= 64) 139 1.1 alc return AH_FALSE; 140 1.1 alc if (ix >= 32) { 141 1.1 alc val = OS_REG_READ(ah, AR_MCAST_FIL1); 142 1.1 alc OS_REG_WRITE(ah, AR_MCAST_FIL1, (val | (1<<(ix-32)))); 143 1.1 alc } else { 144 1.1 alc val = OS_REG_READ(ah, AR_MCAST_FIL0); 145 1.1 alc OS_REG_WRITE(ah, AR_MCAST_FIL0, (val | (1<<ix))); 146 1.1 alc } 147 1.1 alc return AH_TRUE; 148 1.1 alc } 149 1.1 alc 150 1.1 alc /* 151 1.1 alc * Return the receive packet filter. 152 1.1 alc */ 153 1.1 alc uint32_t 154 1.1 alc ar5210GetRxFilter(struct ath_hal *ah) 155 1.1 alc { 156 1.1 alc /* XXX can't be sure if promiscuous mode is set because of PHYRADAR */ 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 * Turn off/on bits in the receive packet filter. 162 1.1 alc */ 163 1.1 alc void 164 1.1 alc ar5210SetRxFilter(struct ath_hal *ah, uint32_t bits) 165 1.1 alc { 166 1.1 alc if (bits & HAL_RX_FILTER_PHYRADAR) { 167 1.1 alc /* must enable promiscuous mode to get radar */ 168 1.1 alc bits = (bits &~ HAL_RX_FILTER_PHYRADAR) | AR_RX_FILTER_PROMISCUOUS; 169 1.1 alc } 170 1.1 alc OS_REG_WRITE(ah, AR_RX_FILTER, bits); 171 1.1 alc } 172 1.1 alc 173 1.1 alc /* 174 1.1 alc * Initialize RX descriptor, by clearing the status and clearing 175 1.1 alc * the size. This is not strictly HW dependent, but we want the 176 1.1 alc * control and status words to be opaque above the hal. 177 1.1 alc */ 178 1.1 alc HAL_BOOL 179 1.1 alc ar5210SetupRxDesc(struct ath_hal *ah, struct ath_desc *ds, 180 1.1 alc uint32_t size, u_int flags) 181 1.1 alc { 182 1.1 alc struct ar5210_desc *ads = AR5210DESC(ds); 183 1.1 alc 184 1.1 alc (void) flags; 185 1.1 alc 186 1.1 alc ads->ds_ctl0 = 0; 187 1.1 alc ads->ds_ctl1 = size & AR_BufLen; 188 1.1 alc if (ads->ds_ctl1 != size) { 189 1.1 alc HALDEBUG(ah, HAL_DEBUG_ANY, "%s: buffer size %u too large\n", 190 1.1 alc __func__, size); 191 1.1 alc return AH_FALSE; 192 1.1 alc } 193 1.1 alc if (flags & HAL_RXDESC_INTREQ) 194 1.1 alc ads->ds_ctl1 |= AR_RxInterReq; 195 1.1 alc ads->ds_status0 = ads->ds_status1 = 0; 196 1.1 alc 197 1.1 alc return AH_TRUE; 198 1.1 alc } 199 1.1 alc 200 1.1 alc /* 201 1.1 alc * Process an RX descriptor, and return the status to the caller. 202 1.1 alc * Copy some hardware specific items into the software portion 203 1.1 alc * of the descriptor. 204 1.1 alc * 205 1.1 alc * NB: the caller is responsible for validating the memory contents 206 1.1 alc * of the descriptor (e.g. flushing any cached copy). 207 1.1 alc */ 208 1.1 alc HAL_STATUS 209 1.1 alc ar5210ProcRxDesc(struct ath_hal *ah, struct ath_desc *ds, 210 1.1 alc uint32_t pa, struct ath_desc *nds, uint64_t tsf, 211 1.1 alc struct ath_rx_status *rs) 212 1.1 alc { 213 1.1 alc struct ar5210_desc *ads = AR5210DESC(ds); 214 1.1 alc struct ar5210_desc *ands = AR5210DESC(nds); 215 1.1 alc uint32_t now, rstamp; 216 1.1 alc 217 1.1 alc if ((ads->ds_status1 & AR_Done) == 0) 218 1.1 alc return HAL_EINPROGRESS; 219 1.1 alc /* 220 1.1 alc * Given the use of a self-linked tail be very sure that the hw is 221 1.1 alc * done with this descriptor; the hw may have done this descriptor 222 1.1 alc * once and picked it up again...make sure the hw has moved on. 223 1.1 alc */ 224 1.1 alc if ((ands->ds_status1 & AR_Done) == 0 && OS_REG_READ(ah, AR_RXDP) == pa) 225 1.1 alc return HAL_EINPROGRESS; 226 1.1 alc 227 1.1 alc rs->rs_datalen = ads->ds_status0 & AR_DataLen; 228 1.1 alc rstamp = MS(ads->ds_status1, AR_RcvTimestamp); 229 1.1 alc /* 230 1.1 alc * Convert timestamp. The value in the 231 1.1 alc * descriptor is bits [10..22] of the TSF. 232 1.1 alc */ 233 1.1 alc now = (OS_REG_READ(ah, AR_TSF_L32) >> 10) & 0xffff; 234 1.1 alc if ((now & 0x1fff) < rstamp) 235 1.1 alc rstamp |= (now - 0x2000) & 0xffff; 236 1.1 alc else 237 1.1 alc rstamp |= now; 238 1.1 alc /* NB: keep only 15 bits for consistency w/ other chips */ 239 1.1 alc rs->rs_tstamp = rstamp & 0x7fff; 240 1.1 alc rs->rs_status = 0; 241 1.1 alc if ((ads->ds_status1 & AR_FrmRcvOK) == 0) { 242 1.1 alc if (ads->ds_status1 & AR_CRCErr) 243 1.1 alc rs->rs_status |= HAL_RXERR_CRC; 244 1.1 alc else if (ads->ds_status1 & AR_DecryptCRCErr) 245 1.1 alc rs->rs_status |= HAL_RXERR_DECRYPT; 246 1.1 alc else if (ads->ds_status1 & AR_FIFOOverrun) 247 1.1 alc rs->rs_status |= HAL_RXERR_FIFO; 248 1.1 alc else { 249 1.1 alc rs->rs_status |= HAL_RXERR_PHY; 250 1.1 alc rs->rs_phyerr = 251 1.1 alc (ads->ds_status1 & AR_PHYErr) >> AR_PHYErr_S; 252 1.1 alc } 253 1.1 alc } 254 1.1 alc /* XXX what about KeyCacheMiss? */ 255 1.1 alc rs->rs_rssi = MS(ads->ds_status0, AR_RcvSigStrength); 256 1.1 alc if (ads->ds_status1 & AR_KeyIdxValid) 257 1.1 alc rs->rs_keyix = MS(ads->ds_status1, AR_KeyIdx); 258 1.1 alc else 259 1.1 alc rs->rs_keyix = HAL_RXKEYIX_INVALID; 260 1.1 alc /* NB: caller expected to do rate table mapping */ 261 1.1 alc rs->rs_rate = MS(ads->ds_status0, AR_RcvRate); 262 1.1 alc rs->rs_antenna = (ads->ds_status0 & AR_RcvAntenna) ? 1 : 0; 263 1.1 alc rs->rs_more = (ads->ds_status0 & AR_More) ? 1 : 0; 264 1.1 alc 265 1.1 alc return HAL_OK; 266 1.1 alc } 267