📄 ar5210_xmit.c
字号:
/* * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting * Copyright (c) 2002-2005 Atheros Communications, Inc. * All rights reserved. * * $Id: ar5210_xmit.c,v 1.1.1.1 2006/09/12 03:45:22 steven Exp $ */#include "opt_ah.h"#ifdef AH_SUPPORT_AR5210#include "ah.h"#include "ah_internal.h"#include "ah_desc.h"#include "ar5210/ar5210.h"#include "ar5210/ar5210reg.h"#include "ar5210/ar5210phy.h"#include "ar5210/ar5210desc.h"/* * Set the properties of the tx queue with the parameters * from qInfo. The queue must previously have been setup * with a call to ar5210SetupTxQueue. */HAL_BOOLar5210SetTxQueueProps(struct ath_hal *ah, int q, const HAL_TXQ_INFO *qInfo){ struct ath_hal_5210 *ahp = AH5210(ah); if (q >= HAL_NUM_TX_QUEUES) { HALDEBUG(ah, "%s: invalid queue num %u\n", __func__, q); return AH_FALSE; } return ath_hal_setTxQProps(ah, &ahp->ah_txq[q], qInfo);}/* * Return the properties for the specified tx queue. */HAL_BOOLar5210GetTxQueueProps(struct ath_hal *ah, int q, HAL_TXQ_INFO *qInfo){ struct ath_hal_5210 *ahp = AH5210(ah); if (q >= HAL_NUM_TX_QUEUES) { HALDEBUG(ah, "%s: invalid queue num %u\n", __func__, q); return AH_FALSE; } return ath_hal_getTxQProps(ah, qInfo, &ahp->ah_txq[q]);}/* * Allocate and initialize a tx DCU/QCU combination. */intar5210SetupTxQueue(struct ath_hal *ah, HAL_TX_QUEUE type, const HAL_TXQ_INFO *qInfo){ struct ath_hal_5210 *ahp = AH5210(ah); HAL_TX_QUEUE_INFO *qi; int q; switch (type) { case HAL_TX_QUEUE_BEACON: q = 2; break; case HAL_TX_QUEUE_CAB: q = 1; break; case HAL_TX_QUEUE_DATA: q = 0; break; default: HALDEBUG(ah, "%s: bad tx queue type %u\n", __func__, type); return -1; } HALDEBUG(ah, "%s: queue %u\n", __func__, q); qi = &ahp->ah_txq[q]; if (qi->tqi_type != HAL_TX_QUEUE_INACTIVE) { HALDEBUG(ah, "%s: tx queue %u already active\n", __func__, q); return -1; } OS_MEMZERO(qi, sizeof(HAL_TX_QUEUE_INFO)); qi->tqi_type = type; if (qInfo == AH_NULL) { /* by default enable OK+ERR+DESC+URN interrupts */ qi->tqi_qflags = TXQ_FLAG_TXOKINT_ENABLE | TXQ_FLAG_TXERRINT_ENABLE | TXQ_FLAG_TXDESCINT_ENABLE | TXQ_FLAG_TXURNINT_ENABLE ; qi->tqi_aifs = INIT_AIFS; qi->tqi_cwmin = HAL_TXQ_USEDEFAULT; /* NB: do at reset */ qi->tqi_shretry = INIT_SH_RETRY; qi->tqi_lgretry = INIT_LG_RETRY; } else (void) ar5210SetTxQueueProps(ah, q, qInfo); /* NB: must be followed by ar5210ResetTxQueue */ return q;}/* * Free a tx DCU/QCU combination. */HAL_BOOLar5210ReleaseTxQueue(struct ath_hal *ah, u_int q){ struct ath_hal_5210 *ahp = AH5210(ah); HAL_TX_QUEUE_INFO *qi; if (q >= HAL_NUM_TX_QUEUES) { HALDEBUG(ah, "%s: invalid queue num %u\n", __func__, q); return AH_FALSE; } qi = &ahp->ah_txq[q]; if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) { HALDEBUG(ah, "%s: inactive queue %u\n", __func__, q); return AH_FALSE; } HALDEBUG(ah, "%s: release queue %u\n", __func__, q); qi->tqi_type = HAL_TX_QUEUE_INACTIVE; ahp->ah_txOkInterruptMask &= ~(1 << q); ahp->ah_txErrInterruptMask &= ~(1 << q); ahp->ah_txDescInterruptMask &= ~(1 << q); ahp->ah_txEolInterruptMask &= ~(1 << q); ahp->ah_txUrnInterruptMask &= ~(1 << q); return AH_TRUE;#undef N}HAL_BOOLar5210ResetTxQueue(struct ath_hal *ah, u_int q){ struct ath_hal_5210 *ahp = AH5210(ah); HAL_CHANNEL_INTERNAL *chan = AH_PRIVATE(ah)->ah_curchan; HAL_TX_QUEUE_INFO *qi; u_int32_t cwMin; if (q >= HAL_NUM_TX_QUEUES) { HALDEBUG(ah, "%s: invalid queue num %u\n", __func__, q); return AH_FALSE; } qi = &ahp->ah_txq[q]; if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) { HALDEBUG(ah, "%s: inactive queue %u\n", __func__, q); return AH_FALSE; } /* * Ignore any non-data queue(s). */ if (qi->tqi_type != HAL_TX_QUEUE_DATA) return AH_TRUE; /* Set turbo mode / base mode parameters on or off */ if (IS_CHAN_TURBO(chan)) { OS_REG_WRITE(ah, AR_SLOT_TIME, INIT_SLOT_TIME_TURBO); OS_REG_WRITE(ah, AR_TIME_OUT, INIT_ACK_CTS_TIMEOUT_TURBO); OS_REG_WRITE(ah, AR_USEC, INIT_TRANSMIT_LATENCY_TURBO); OS_REG_WRITE(ah, AR_IFS0, ((INIT_SIFS_TURBO + qi->tqi_aifs * INIT_SLOT_TIME_TURBO) << AR_IFS0_DIFS_S) | INIT_SIFS_TURBO); OS_REG_WRITE(ah, AR_IFS1, INIT_PROTO_TIME_CNTRL_TURBO); OS_REG_WRITE(ah, AR_PHY(17), (OS_REG_READ(ah, AR_PHY(17)) & ~0x7F) | 0x38); OS_REG_WRITE(ah, AR_PHY_FRCTL, AR_PHY_SERVICE_ERR | AR_PHY_TXURN_ERR | AR_PHY_ILLLEN_ERR | AR_PHY_ILLRATE_ERR | AR_PHY_PARITY_ERR | AR_PHY_TIMING_ERR | 0x2020 | AR_PHY_TURBO_MODE | AR_PHY_TURBO_SHORT); } else { OS_REG_WRITE(ah, AR_SLOT_TIME, INIT_SLOT_TIME); OS_REG_WRITE(ah, AR_TIME_OUT, INIT_ACK_CTS_TIMEOUT); OS_REG_WRITE(ah, AR_USEC, INIT_TRANSMIT_LATENCY); OS_REG_WRITE(ah, AR_IFS0, ((INIT_SIFS + qi->tqi_aifs * INIT_SLOT_TIME) << AR_IFS0_DIFS_S) | INIT_SIFS); OS_REG_WRITE(ah, AR_IFS1, INIT_PROTO_TIME_CNTRL); OS_REG_WRITE(ah, AR_PHY(17), (OS_REG_READ(ah, AR_PHY(17)) & ~0x7F) | 0x1C); OS_REG_WRITE(ah, AR_PHY_FRCTL, AR_PHY_SERVICE_ERR | AR_PHY_TXURN_ERR | AR_PHY_ILLLEN_ERR | AR_PHY_ILLRATE_ERR | AR_PHY_PARITY_ERR | AR_PHY_TIMING_ERR | 0x1020); } if (qi->tqi_cwmin == HAL_TXQ_USEDEFAULT) cwMin = INIT_CWMIN; else cwMin = qi->tqi_cwmin; /* Set cwmin and retry limit values */ OS_REG_WRITE(ah, AR_RETRY_LMT, (cwMin << AR_RETRY_LMT_CW_MIN_S) | SM(INIT_SLG_RETRY, AR_RETRY_LMT_SLG_RETRY) | SM(INIT_SSH_RETRY, AR_RETRY_LMT_SSH_RETRY) | SM(qi->tqi_lgretry, AR_RETRY_LMT_LG_RETRY) | SM(qi->tqi_shretry, AR_RETRY_LMT_SH_RETRY) ); if (qi->tqi_qflags & TXQ_FLAG_TXOKINT_ENABLE) ahp->ah_txOkInterruptMask |= 1 << q; else ahp->ah_txOkInterruptMask &= ~(1 << q); if (qi->tqi_qflags & TXQ_FLAG_TXERRINT_ENABLE) ahp->ah_txErrInterruptMask |= 1 << q; else ahp->ah_txErrInterruptMask &= ~(1 << q); if (qi->tqi_qflags & TXQ_FLAG_TXDESCINT_ENABLE) ahp->ah_txDescInterruptMask |= 1 << q; else ahp->ah_txDescInterruptMask &= ~(1 << q); if (qi->tqi_qflags & TXQ_FLAG_TXEOLINT_ENABLE) ahp->ah_txEolInterruptMask |= 1 << q; else ahp->ah_txEolInterruptMask &= ~(1 << q); if (qi->tqi_qflags & TXQ_FLAG_TXURNINT_ENABLE) ahp->ah_txUrnInterruptMask |= 1 << q; else ahp->ah_txUrnInterruptMask &= ~(1 << q); return AH_TRUE;}/* * Get the TXDP for the "main" data queue. Needs to be extended * for multiple Q functionality */u_int32_tar5210GetTxDP(struct ath_hal *ah, u_int q){ struct ath_hal_5210 *ahp = AH5210(ah); HAL_TX_QUEUE_INFO *qi; HALASSERT(q < HAL_NUM_TX_QUEUES); qi = &ahp->ah_txq[q]; switch (qi->tqi_type) { case HAL_TX_QUEUE_DATA: return OS_REG_READ(ah, AR_TXDP0); case HAL_TX_QUEUE_INACTIVE: HALDEBUG(ah, "%s: inactive queue %u\n", __func__, q); /* fall thru... */ default: break; } return 0xffffffff;}/* * Set the TxDP for the "main" data queue. */HAL_BOOLar5210SetTxDP(struct ath_hal *ah, u_int q, u_int32_t txdp){ struct ath_hal_5210 *ahp = AH5210(ah); HAL_TX_QUEUE_INFO *qi; HALASSERT(q < HAL_NUM_TX_QUEUES); HALDEBUGn(ah, 2, "%s: queue %u 0x%x\n", __func__, q, txdp); qi = &ahp->ah_txq[q]; switch (qi->tqi_type) { case HAL_TX_QUEUE_DATA:#ifdef AH_DEBUG /* * Make sure that TXE is deasserted before setting the * TXDP. If TXE is still asserted, setting TXDP will * have no effect. */ if (OS_REG_READ(ah, AR_CR) & AR_CR_TXE0) ath_hal_printf(ah, "%s: TXE asserted; AR_CR=0x%x\n", __func__, OS_REG_READ(ah, AR_CR));#endif OS_REG_WRITE(ah, AR_TXDP0, txdp); break; case HAL_TX_QUEUE_BEACON: case HAL_TX_QUEUE_CAB: OS_REG_WRITE(ah, AR_TXDP1, txdp); break; case HAL_TX_QUEUE_INACTIVE: HALDEBUG(ah, "%s: inactive queue %u\n", __func__, q); /* fall thru... */ default: return AH_FALSE; } return AH_TRUE;}/* * Update Tx FIFO trigger level. * * Set bIncTrigLevel to TRUE to increase the trigger level. * Set bIncTrigLevel to FALSE to decrease the trigger level. *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -