The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/dev/ath/ath_hal/ar9300/ar9300_recv.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 2013 Qualcomm Atheros, Inc.
    3  *
    4  * Permission to use, copy, modify, and/or distribute this software for any
    5  * purpose with or without fee is hereby granted, provided that the above
    6  * copyright notice and this permission notice appear in all copies.
    7  *
    8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
    9  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
   10  * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
   11  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
   12  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
   13  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
   14  * PERFORMANCE OF THIS SOFTWARE.
   15  */
   16 
   17 #include "opt_ah.h"
   18 
   19 #include "ah.h"
   20 #include "ah_desc.h"
   21 #include "ah_internal.h"
   22 
   23 #include "ar9300/ar9300.h"
   24 #include "ar9300/ar9300reg.h"
   25 #include "ar9300/ar9300desc.h"
   26 
   27 /*
   28  * Get the RXDP.
   29  */
   30 u_int32_t
   31 ar9300_get_rx_dp(struct ath_hal *ath, HAL_RX_QUEUE qtype)
   32 {
   33     if (qtype == HAL_RX_QUEUE_HP) {
   34         return OS_REG_READ(ath, AR_HP_RXDP);
   35     } else {
   36         return OS_REG_READ(ath, AR_LP_RXDP);
   37     }
   38 }
   39 
   40 /*
   41  * Set the rx_dp.
   42  */
   43 void
   44 ar9300_set_rx_dp(struct ath_hal *ah, u_int32_t rxdp, HAL_RX_QUEUE qtype)
   45 {
   46     HALASSERT((qtype == HAL_RX_QUEUE_HP) || (qtype == HAL_RX_QUEUE_LP));
   47 
   48     if (qtype == HAL_RX_QUEUE_HP) {
   49         OS_REG_WRITE(ah, AR_HP_RXDP, rxdp);
   50     } else {
   51         OS_REG_WRITE(ah, AR_LP_RXDP, rxdp);
   52     }
   53 }
   54 
   55 /*
   56  * Set Receive Enable bits.
   57  */
   58 void
   59 ar9300_enable_receive(struct ath_hal *ah)
   60 {
   61     OS_REG_WRITE(ah, AR_CR, 0);
   62 }
   63 
   64 /*
   65  * Set the RX abort bit.
   66  */
   67 HAL_BOOL
   68 ar9300_set_rx_abort(struct ath_hal *ah, HAL_BOOL set)
   69 { 
   70     if (set) {
   71         /* Set the force_rx_abort bit */
   72         OS_REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
   73 
   74         if ( AH9300(ah)->ah_reset_reason == HAL_RESET_BBPANIC ){
   75             /* depending upon the BB panic status, rx state may not return to 0,
   76              * so skipping the wait for BB panic reset */
   77             OS_REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
   78             return AH_FALSE;
   79         } else {
   80             HAL_BOOL okay;
   81             okay = ath_hal_wait(
   82                 ah, AR_OBS_BUS_1, AR_OBS_BUS_1_RX_STATE, 0);
   83             /* Wait for Rx state to return to 0 */
   84             if (!okay) {
   85                 /* abort: chip rx failed to go idle in 10 ms */
   86                 OS_REG_CLR_BIT(ah, AR_DIAG_SW,
   87                     (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
   88 
   89                 HALDEBUG(ah, HAL_DEBUG_RX,
   90                     "%s: rx failed to go idle in 10 ms RXSM=0x%x\n",
   91                     __func__, OS_REG_READ(ah, AR_OBS_BUS_1));
   92 
   93                 return AH_FALSE; /* failure */
   94             }
   95         }
   96     } else {
   97         OS_REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
   98     }
   99 
  100     return AH_TRUE; /* success */
  101 }
  102 
  103 /*
  104  * Stop Receive at the DMA engine
  105  */
  106 HAL_BOOL
  107 ar9300_stop_dma_receive(struct ath_hal *ah, u_int timeout)
  108 {
  109     int wait;
  110     HAL_BOOL status, okay;
  111     u_int32_t org_value;
  112 
  113 #define AH_RX_STOP_DMA_TIMEOUT 10000   /* usec */
  114 #define AH_TIME_QUANTUM        100     /* usec */
  115 
  116     OS_MARK(ah, AH_MARK_RX_CTL, AH_MARK_RX_CTL_DMA_STOP);
  117 
  118     if (timeout == 0) {
  119         timeout = AH_RX_STOP_DMA_TIMEOUT;
  120     }
  121 
  122     org_value = OS_REG_READ(ah, AR_MACMISC);
  123 
  124     OS_REG_WRITE(ah, AR_MACMISC, 
  125         ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) | 
  126          (AR_MACMISC_MISC_OBS_BUS_1 << AR_MACMISC_MISC_OBS_BUS_MSB_S)));
  127 
  128         okay = ath_hal_wait(
  129             ah, AR_DMADBG_7, AR_DMADBG_RX_STATE, 0);
  130     /* wait for Rx DMA state machine to become idle */
  131         if (!okay) {
  132             HALDEBUG(ah, HAL_DEBUG_RX,
  133                 "reg AR_DMADBG_7 is not 0, instead 0x%08x\n",
  134                 OS_REG_READ(ah, AR_DMADBG_7));
  135         }
  136 
  137     /* Set receive disable bit */
  138     OS_REG_WRITE(ah, AR_CR, AR_CR_RXD);
  139 
  140     /* Wait for rx enable bit to go low */
  141     for (wait = timeout / AH_TIME_QUANTUM; wait != 0; wait--) {
  142         if ((OS_REG_READ(ah, AR_CR) & AR_CR_RXE) == 0) {
  143             break;
  144         }
  145         OS_DELAY(AH_TIME_QUANTUM);
  146     }
  147 
  148     if (wait == 0) {
  149         HALDEBUG(ah, HAL_DEBUG_RX, "%s: dma failed to stop in %d ms\n"
  150                 "AR_CR=0x%08x\nAR_DIAG_SW=0x%08x\n",
  151                 __func__,
  152                 timeout / 1000,
  153                 OS_REG_READ(ah, AR_CR),
  154                 OS_REG_READ(ah, AR_DIAG_SW));
  155         status = AH_FALSE;
  156     } else {
  157         status = AH_TRUE;
  158     }
  159 
  160     OS_REG_WRITE(ah, AR_MACMISC, org_value);
  161 
  162     OS_MARK(ah, AH_MARK_RX_CTL,
  163         status ? AH_MARK_RX_CTL_DMA_STOP_OK : AH_MARK_RX_CTL_DMA_STOP_ERR);
  164 
  165     return status;
  166 #undef AH_RX_STOP_DMA_TIMEOUT
  167 #undef AH_TIME_QUANTUM
  168 }
  169 
  170 /*
  171  * Start Transmit at the PCU engine (unpause receive)
  172  */
  173 void
  174 ar9300_start_pcu_receive(struct ath_hal *ah, HAL_BOOL is_scanning)
  175 {
  176     ar9300_enable_mib_counters(ah);
  177     ar9300_ani_reset(ah, is_scanning);
  178     /* Clear RX_DIS and RX_ABORT after enabling phy errors in ani_reset */
  179     OS_REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
  180 }
  181 
  182 /*
  183  * Stop Transmit at the PCU engine (pause receive)
  184  */
  185 void
  186 ar9300_stop_pcu_receive(struct ath_hal *ah)
  187 {
  188     OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS);
  189     ar9300_disable_mib_counters(ah);
  190 }
  191 
  192 /*
  193  * Set multicast filter 0 (lower 32-bits)
  194  *               filter 1 (upper 32-bits)
  195  */
  196 void
  197 ar9300_set_multicast_filter(
  198     struct ath_hal *ah,
  199     u_int32_t filter0,
  200     u_int32_t filter1)
  201 {
  202     OS_REG_WRITE(ah, AR_MCAST_FIL0, filter0);
  203     OS_REG_WRITE(ah, AR_MCAST_FIL1, filter1);
  204 }
  205 
  206 /*
  207  * Get the receive filter.
  208  */
  209 u_int32_t
  210 ar9300_get_rx_filter(struct ath_hal *ah)
  211 {
  212     u_int32_t bits = OS_REG_READ(ah, AR_RX_FILTER);
  213     u_int32_t phybits = OS_REG_READ(ah, AR_PHY_ERR);
  214     if (phybits & AR_PHY_ERR_RADAR) {
  215         bits |= HAL_RX_FILTER_PHYRADAR;
  216     }
  217     if (phybits & (AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING)) {
  218         bits |= HAL_RX_FILTER_PHYERR;
  219     }
  220     return bits;
  221 }
  222 
  223 /*
  224  * Set the receive filter.
  225  */
  226 void
  227 ar9300_set_rx_filter(struct ath_hal *ah, u_int32_t bits)
  228 {
  229     u_int32_t phybits;
  230 
  231     if (AR_SREV_SCORPION(ah) || AR_SREV_HONEYBEE(ah)) {
  232         /* Enable Rx for 4 address frames */
  233         bits |= AR_RX_4ADDRESS;
  234     }
  235     if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) {
  236         /* HW fix for rx hang and corruption. */
  237         bits |= AR_RX_CONTROL_WRAPPER;
  238     }
  239     OS_REG_WRITE(ah, AR_RX_FILTER,
  240         bits | AR_RX_UNCOM_BA_BAR | AR_RX_COMPR_BAR);
  241     phybits = 0;
  242     if (bits & HAL_RX_FILTER_PHYRADAR) {
  243         phybits |= AR_PHY_ERR_RADAR;
  244     }
  245     if (bits & HAL_RX_FILTER_PHYERR) {
  246         phybits |= AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING;
  247     }
  248     OS_REG_WRITE(ah, AR_PHY_ERR, phybits);
  249     if (phybits) {
  250         OS_REG_WRITE(ah, AR_RXCFG,
  251             OS_REG_READ(ah, AR_RXCFG) | AR_RXCFG_ZLFDMA);
  252     } else {
  253         OS_REG_WRITE(ah, AR_RXCFG,
  254             OS_REG_READ(ah, AR_RXCFG) &~ AR_RXCFG_ZLFDMA);
  255     }
  256 }
  257 
  258 /*
  259  * Select to pass PLCP headr or EVM data.
  260  */
  261 HAL_BOOL
  262 ar9300_set_rx_sel_evm(struct ath_hal *ah, HAL_BOOL sel_evm, HAL_BOOL just_query)
  263 {
  264     struct ath_hal_9300 *ahp = AH9300(ah);
  265     HAL_BOOL old_value = ahp->ah_get_plcp_hdr == 0;
  266 
  267     if (just_query) {
  268         return old_value;
  269     }
  270     if (sel_evm) {
  271         OS_REG_SET_BIT(ah, AR_PCU_MISC, AR_PCU_SEL_EVM);
  272     } else {
  273         OS_REG_CLR_BIT(ah, AR_PCU_MISC, AR_PCU_SEL_EVM);
  274     }
  275 
  276     ahp->ah_get_plcp_hdr = !sel_evm;
  277 
  278     return old_value;
  279 }
  280 
  281 void ar9300_promisc_mode(struct ath_hal *ah, HAL_BOOL enable)
  282 {
  283     u_int32_t reg_val = 0;
  284     reg_val =  OS_REG_READ(ah, AR_RX_FILTER);
  285     if (enable){
  286         reg_val |= AR_RX_PROM;
  287     } else{ /*Disable promisc mode */
  288         reg_val &= ~AR_RX_PROM;
  289     }    
  290     OS_REG_WRITE(ah, AR_RX_FILTER, reg_val);
  291 }
  292 
  293 void 
  294 ar9300_read_pktlog_reg(
  295     struct ath_hal *ah,
  296     u_int32_t *rxfilter_val,
  297     u_int32_t *rxcfg_val,
  298     u_int32_t *phy_err_mask_val,
  299     u_int32_t *mac_pcu_phy_err_regval)
  300 {
  301     *rxfilter_val = OS_REG_READ(ah, AR_RX_FILTER);
  302     *rxcfg_val    = OS_REG_READ(ah, AR_RXCFG);
  303     *phy_err_mask_val = OS_REG_READ(ah, AR_PHY_ERR);
  304     *mac_pcu_phy_err_regval = OS_REG_READ(ah, 0x8338);
  305     HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,
  306         "%s[%d] rxfilter_val 0x%08x , rxcfg_val 0x%08x, "
  307         "phy_err_mask_val 0x%08x mac_pcu_phy_err_regval 0x%08x\n",
  308         __func__, __LINE__,
  309         *rxfilter_val, *rxcfg_val, *phy_err_mask_val, *mac_pcu_phy_err_regval);
  310 }
  311 
  312 void
  313 ar9300_write_pktlog_reg(
  314     struct ath_hal *ah,
  315     HAL_BOOL enable,
  316     u_int32_t rxfilter_val,
  317     u_int32_t rxcfg_val,
  318     u_int32_t phy_err_mask_val,
  319     u_int32_t mac_pcu_phy_err_reg_val)
  320 {
  321     if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) {
  322         /* HW fix for rx hang and corruption. */
  323         rxfilter_val |= AR_RX_CONTROL_WRAPPER;
  324     }
  325     if (enable) { /* Enable pktlog phyerr setting */
  326         OS_REG_WRITE(ah, AR_RX_FILTER, 0xffff | AR_RX_COMPR_BAR | rxfilter_val);
  327         OS_REG_WRITE(ah, AR_PHY_ERR, 0xFFFFFFFF);
  328         OS_REG_WRITE(ah, AR_RXCFG, rxcfg_val | AR_RXCFG_ZLFDMA);
  329         OS_REG_WRITE(ah, AR_PHY_ERR_MASK_REG, mac_pcu_phy_err_reg_val | 0xFF);
  330     } else { /* Disable phyerr and Restore regs */
  331         OS_REG_WRITE(ah, AR_RX_FILTER, rxfilter_val);
  332         OS_REG_WRITE(ah, AR_PHY_ERR, phy_err_mask_val);
  333         OS_REG_WRITE(ah, AR_RXCFG, rxcfg_val);
  334         OS_REG_WRITE(ah, AR_PHY_ERR_MASK_REG, mac_pcu_phy_err_reg_val);
  335     }
  336     HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,
  337         "%s[%d] ena %d rxfilter_val 0x%08x , rxcfg_val 0x%08x, "
  338         "phy_err_mask_val 0x%08x mac_pcu_phy_err_regval 0x%08x\n",
  339         __func__, __LINE__,
  340         enable, rxfilter_val, rxcfg_val,
  341         phy_err_mask_val, mac_pcu_phy_err_reg_val);
  342 }

Cache object: 31b6a986be11f7c3570843cc50fd512a


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.