Path: blob/main/sys/dev/ath/ath_hal/ar5211/ar5211_recv.c
39566 views
/*-1* SPDX-License-Identifier: ISC2*3* Copyright (c) 2002-2008 Sam Leffler, Errno Consulting4* Copyright (c) 2002-2006 Atheros Communications, Inc.5*6* Permission to use, copy, modify, and/or distribute this software for any7* purpose with or without fee is hereby granted, provided that the above8* copyright notice and this permission notice appear in all copies.9*10* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES11* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF12* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR13* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES14* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN15* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF16* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.17*/18#include "opt_ah.h"1920#include "ah.h"21#include "ah_internal.h"22#include "ah_desc.h"2324#include "ar5211/ar5211.h"25#include "ar5211/ar5211reg.h"26#include "ar5211/ar5211desc.h"2728/*29* Get the RXDP.30*/31uint32_t32ar5211GetRxDP(struct ath_hal *ah, HAL_RX_QUEUE qtype)33{3435HALASSERT(qtype == HAL_RX_QUEUE_HP);36return OS_REG_READ(ah, AR_RXDP);37}3839/*40* Set the RxDP.41*/42void43ar5211SetRxDP(struct ath_hal *ah, uint32_t rxdp, HAL_RX_QUEUE qtype)44{4546HALASSERT(qtype == HAL_RX_QUEUE_HP);47OS_REG_WRITE(ah, AR_RXDP, rxdp);48HALASSERT(OS_REG_READ(ah, AR_RXDP) == rxdp);49}5051/*52* Set Receive Enable bits.53*/54void55ar5211EnableReceive(struct ath_hal *ah)56{57OS_REG_WRITE(ah, AR_CR, AR_CR_RXE);58}5960/*61* Stop Receive at the DMA engine62*/63HAL_BOOL64ar5211StopDmaReceive(struct ath_hal *ah)65{66OS_REG_WRITE(ah, AR_CR, AR_CR_RXD); /* Set receive disable bit */67if (!ath_hal_wait(ah, AR_CR, AR_CR_RXE, 0)) {68#ifdef AH_DEBUG69ath_hal_printf(ah, "%s failed to stop in 10ms\n"70"AR_CR=0x%08X\nAR_DIAG_SW=0x%08X\n"71, __func__72, OS_REG_READ(ah, AR_CR)73, OS_REG_READ(ah, AR_DIAG_SW)74);75#endif76return AH_FALSE;77} else {78return AH_TRUE;79}80}8182/*83* Start Transmit at the PCU engine (unpause receive)84*/85void86ar5211StartPcuReceive(struct ath_hal *ah, HAL_BOOL is_scanning)87{88OS_REG_WRITE(ah, AR_DIAG_SW,89OS_REG_READ(ah, AR_DIAG_SW) & ~(AR_DIAG_SW_DIS_RX));90}9192/*93* Stop Transmit at the PCU engine (pause receive)94*/95void96ar5211StopPcuReceive(struct ath_hal *ah)97{98OS_REG_WRITE(ah, AR_DIAG_SW,99OS_REG_READ(ah, AR_DIAG_SW) | AR_DIAG_SW_DIS_RX);100}101102/*103* Set multicast filter 0 (lower 32-bits)104* filter 1 (upper 32-bits)105*/106void107ar5211SetMulticastFilter(struct ath_hal *ah, uint32_t filter0, uint32_t filter1)108{109OS_REG_WRITE(ah, AR_MCAST_FIL0, filter0);110OS_REG_WRITE(ah, AR_MCAST_FIL1, filter1);111}112113/*114* Clear multicast filter by index115*/116HAL_BOOL117ar5211ClrMulticastFilterIndex(struct ath_hal *ah, uint32_t ix)118{119uint32_t val;120121if (ix >= 64)122return AH_FALSE;123if (ix >= 32) {124val = OS_REG_READ(ah, AR_MCAST_FIL1);125OS_REG_WRITE(ah, AR_MCAST_FIL1, (val &~ (1<<(ix-32))));126} else {127val = OS_REG_READ(ah, AR_MCAST_FIL0);128OS_REG_WRITE(ah, AR_MCAST_FIL0, (val &~ (1<<ix)));129}130return AH_TRUE;131}132133/*134* Set multicast filter by index135*/136HAL_BOOL137ar5211SetMulticastFilterIndex(struct ath_hal *ah, uint32_t ix)138{139uint32_t val;140141if (ix >= 64)142return AH_FALSE;143if (ix >= 32) {144val = OS_REG_READ(ah, AR_MCAST_FIL1);145OS_REG_WRITE(ah, AR_MCAST_FIL1, (val | (1<<(ix-32))));146} else {147val = OS_REG_READ(ah, AR_MCAST_FIL0);148OS_REG_WRITE(ah, AR_MCAST_FIL0, (val | (1<<ix)));149}150return AH_TRUE;151}152153/*154* Get receive filter.155*/156uint32_t157ar5211GetRxFilter(struct ath_hal *ah)158{159return OS_REG_READ(ah, AR_RX_FILTER);160}161162/*163* Set receive filter.164*/165void166ar5211SetRxFilter(struct ath_hal *ah, uint32_t bits)167{168OS_REG_WRITE(ah, AR_RX_FILTER, bits);169}170171/*172* Initialize RX descriptor, by clearing the status and clearing173* the size. This is not strictly HW dependent, but we want the174* control and status words to be opaque above the hal.175*/176HAL_BOOL177ar5211SetupRxDesc(struct ath_hal *ah, struct ath_desc *ds,178uint32_t size, u_int flags)179{180struct ar5211_desc *ads = AR5211DESC(ds);181182ads->ds_ctl0 = 0;183ads->ds_ctl1 = size & AR_BufLen;184if (ads->ds_ctl1 != size) {185HALDEBUG(ah, HAL_DEBUG_ANY, "%s: buffer size %u too large\n",186__func__, size);187return AH_FALSE;188}189if (flags & HAL_RXDESC_INTREQ)190ads->ds_ctl1 |= AR_RxInterReq;191ads->ds_status0 = ads->ds_status1 = 0;192193return AH_TRUE;194}195196/*197* Process an RX descriptor, and return the status to the caller.198* Copy some hardware specific items into the software portion199* of the descriptor.200*201* NB: the caller is responsible for validating the memory contents202* of the descriptor (e.g. flushing any cached copy).203*/204HAL_STATUS205ar5211ProcRxDesc(struct ath_hal *ah, struct ath_desc *ds,206uint32_t pa, struct ath_desc *nds, uint64_t tsf,207struct ath_rx_status *rs)208{209struct ar5211_desc *ads = AR5211DESC(ds);210struct ar5211_desc *ands = AR5211DESC(nds);211212if ((ads->ds_status1 & AR_Done) == 0)213return HAL_EINPROGRESS;214/*215* Given the use of a self-linked tail be very sure that the hw is216* done with this descriptor; the hw may have done this descriptor217* once and picked it up again...make sure the hw has moved on.218*/219if ((ands->ds_status1 & AR_Done) == 0 && OS_REG_READ(ah, AR_RXDP) == pa)220return HAL_EINPROGRESS;221222rs->rs_datalen = ads->ds_status0 & AR_DataLen;223rs->rs_tstamp = MS(ads->ds_status1, AR_RcvTimestamp);224rs->rs_status = 0;225if ((ads->ds_status1 & AR_FrmRcvOK) == 0) {226if (ads->ds_status1 & AR_CRCErr)227rs->rs_status |= HAL_RXERR_CRC;228else if (ads->ds_status1 & AR_DecryptCRCErr)229rs->rs_status |= HAL_RXERR_DECRYPT;230else {231rs->rs_status |= HAL_RXERR_PHY;232rs->rs_phyerr = MS(ads->ds_status1, AR_PHYErr);233}234}235/* XXX what about KeyCacheMiss? */236rs->rs_rssi = MS(ads->ds_status0, AR_RcvSigStrength);237if (ads->ds_status1 & AR_KeyIdxValid)238rs->rs_keyix = MS(ads->ds_status1, AR_KeyIdx);239else240rs->rs_keyix = HAL_RXKEYIX_INVALID;241/* NB: caller expected to do rate table mapping */242rs->rs_rate = MS(ads->ds_status0, AR_RcvRate);243rs->rs_antenna = MS(ads->ds_status0, AR_RcvAntenna);244rs->rs_more = (ads->ds_status0 & AR_More) ? 1 : 0;245246return HAL_OK;247}248249250