?? s3c2510eth.c
字號:
*
* s3c2510EthPollStop - stop polling mode
*
* RETURNS: OK, or ERROR.
*/
STATUS s3c2510EthPollStop(
ETH_DRV_CTRL *pDrvCtrl /* pointer to driver structure */
)
{
int unit = pDrvCtrl->unit;
#ifdef DEBUG_TRACE
printf("s3c2510Eth%d PollStop\n", unit);
#endif /* DEBUG_TRACE */
/* Clear status. */
/* should be clear value one, jwchoi
*S3C2510_BMRXSTAT(unit) = 0;
*S3C2510_BMTXSTAT(unit) = 0;
*/
*S3C2510_BMRXINTEN(unit) |= S3C2510_BMRXINTEN_BDONEIE; /* BDMA Rx Done Interrupt Enable */
*S3C2510_BMTXINTEN(unit) |= S3C2510_BMTXINTEN_MCOMPIE; /* MAC Tx Completion Interrupt Enable */
pDrvCtrl->bPolling = FALSE;
/* Enable interrupt. */
intEnable(pDrvCtrl->intLvlRx);
intEnable(pDrvCtrl->intLvlTx);
return OK;
}
/*******************************************************************************
*
* s3c2510EthRbdGet - allocate RBD
*
* RETURNS: pointer to the RBD.
*/
PETHRBD s3c2510EthRbdGet(
ETH_DRV_CTRL *pDrvCtrl /* pointer to driver structure */
)
{
PETHRBD pRbd;
#ifdef DEBUG_TRACE
printf("s3c2510Eth%d RbdGet\n", pDrvCtrl->unit);
#endif /* DEBUG_TRACE */
/* Get the first available RBD. */
pRbd = (PETHRBD)(pDrvCtrl->rbdBase + pDrvCtrl->rbdIndex * SIZE_BD);
/* If no RBD is available, retry it later. */
if (pRbd->status & S3C2510_ETH_RBD_O)
{
return NULL;
}
return (pRbd);
}
/*******************************************************************************
*
* s3c2510EthRbdFree - free RBD
*
* RETURNS: N/A.
*/
void s3c2510EthRbdFree(
ETH_DRV_CTRL *pDrvCtrl, /* pointer to driver structure */
PETHRBD pRbd /* pointer to the RBD to be freed */
)
{
#ifdef DEBUG_TRACE
printf("s3c2510Eth%d RbdFree\n", pDrvCtrl->unit);
#endif /* DEBUG_TRACE */
/* Free the used RBD. */
pRbd->status = S3C2510_ETH_RBD_O;
/* Advance to next RBD. */
pDrvCtrl->rbdIndex++;
if (pDrvCtrl->rbdIndex == NUM_RBD_ETH)
{
pDrvCtrl->rbdIndex = 0;
}
}
/*******************************************************************************
*
* s3c2510EthRbdCheck - check RBD
*
* RETURNS: length of frame received.
*/
ULONG s3c2510EthRbdCheck(
ETH_DRV_CTRL *pDrvCtrl, /* pointer to driver structure */
PETHRBD pRbd /* pointer to the RBD to be checked */
)
{
#ifdef DEBUG_TRACE
printf("s3c2510Eth%d RbdCheck\n", pDrvCtrl->unit);
#endif /* DEBUG_TRACE */
/* printf("s3c2510Eth%d pRbdStatus 0x%08x Length %d\n", pDrvCtrl->unit, pRbd->status, pRbd->length); test by jwchoi */
if (pRbd->status & (S3C2510_ETH_RBD_BMSO | /* BDMA Rx Maximum Size Over */
S3C2510_ETH_RBD_MHALTED | /* MAC Rx Halted */
S3C2510_ETH_RBD_MPARERR | /* MAC Rx Parity Error */
S3C2510_ETH_RBD_MLONGERR | /* MAC Rx Long Error */
S3C2510_ETH_RBD_MOVERFLOW | /* MAC Rx Overflow */
S3C2510_ETH_RBD_MCRCERR | /* MAC Rx CRC Error */
S3C2510_ETH_RBD_MALIGNERR)) /* MAC Rx Alignment Error */
{
if (pRbd->status & S3C2510_ETH_RBD_BMSO)
{
#ifdef DEBUG_TRACE
printf(" S3C2510_ETH_RBD_BMSO\n");
#endif /* DEBUG_TRACE */
/* Up-date statistics. */
pDrvCtrl->bRxMso++;
}
if (pRbd->status & S3C2510_ETH_RBD_MHALTED)
{
#ifdef DEBUG_TRACE
printf(" S3C2510_ETH_RBD_MHALTED\n");
#endif /* DEBUG_TRACE */
/* Up-date statistics. */
pDrvCtrl->mRxHalted++;
}
if (pRbd->status & S3C2510_ETH_RBD_MPARERR)
{
#ifdef DEBUG_TRACE
printf(" S3C2510_ETH_RBD_MPARERR\n");
#endif /* DEBUG_TRACE */
/* Up-date statistics. */
pDrvCtrl->mRxParErr++;
}
if (pRbd->status & S3C2510_ETH_RBD_MLONGERR)
{
#ifdef DEBUG_TRACE
printf(" S3C2510_ETH_RBD_MLONGERR\n");
#endif /* DEBUG_TRACE */
/* Up-date statistics. */
pDrvCtrl->mRxLongErr++;
}
if (pRbd->status & S3C2510_ETH_RBD_MOVERFLOW)
{
#ifdef DEBUG_TRACE
printf(" S3C2510_ETH_RBD_MOVERFLOW\n");
#endif /* DEBUG_TRACE */
/* Up-date statistics. */
pDrvCtrl->mRxOverflow++;
}
if (pRbd->status & S3C2510_ETH_RBD_MCRCERR)
{
#ifdef DEBUG_TRACE
printf(" S3C2510_ETH_RBD_MCRCERR\n");
#endif /* DEBUG_TRACE */
/* Up-date statistics. */
pDrvCtrl->mRxCrcErr++;
}
if (pRbd->status & S3C2510_ETH_RBD_MALIGNERR)
{
#ifdef DEBUG_TRACE
printf(" S3C2510_ETH_RBD_MALIGNERR\n");
#endif /* DEBUG_TRACE */
/* Up-date statistics. */
pDrvCtrl->mRxAlignErr++;
}
return 0;
}
if (pRbd->status & S3C2510_ETH_RBD_BDONE) /* BDMA Rx Done */
{
ULONG length = (ULONG)(pRbd->length - SIZE_ETH_CRC);
/* Check frame length. */
if ((length < SIZE_ETH_MINFLR) || (length > SIZE_ETH_MFLR))
{
printf("s3c2510Eth%d Error: Invalid RBD(0x%08X) length, %u\n", pDrvCtrl->unit, (UINT32)pRbd, (UINT)length);
return 0;
}
#ifdef DEBUG_TRACE
printf("pRbd(0x%08X), pBuf(0x%08X), status(0x%04X), length(%u)\n", (UINT32)pRbd, pRbd->pBuf, pRbd->status, pRbd->length);
#endif /* DEBUG_TRACE */
return (length);
}
printf("s3c2510Eth%d Error: Unknown RBD(0x%08X) status(0x%04X)\n", pDrvCtrl->unit, (UINT32)pRbd, pRbd->status);
return 0;
}
/*******************************************************************************
*
* s3c2510EthTbdGet - allocate TBD
*
* RETURNS: pointer to the TBD.
*/
PETHTBD s3c2510EthTbdGet(
ETH_DRV_CTRL *pDrvCtrl /* pointer to driver structure */
)
{
PETHTBD pTbd;
#ifdef DEBUG_TRACE
printf("s3c2510Eth%d TbdGet\n", pDrvCtrl->unit);
#endif /* DEBUG_TRACE */
/* Get the first available TBD. */
pTbd = (PETHTBD)(pDrvCtrl->tbdBase + pDrvCtrl->tbdFree * SIZE_BD);
if (pDrvCtrl->pClPool)
{
char *pBuf;
/* If it has associate cluster buffer, completion routine will clear all of the bits. */
if ((pTbd->status & S3C2510_ETH_TBD_O) || (pTbd->length != 0))
{
return NULL;
}
/* Allocate cluster buffer. */
pBuf = netClusterGet(pDrvCtrl->endObj.pNetPool, pDrvCtrl->pClPool);
if (!pBuf)
{
#ifdef DEBUG_TRACE
printf("s3c2510Eth%d Error: Failed to allocate cluster buffer\n", pDrvCtrl->unit);
#endif /* DEBUG_TRACE */
return NULL;
}
pTbd->pBuf = (UINT32)(pBuf + (SIZE_ETH_FB_HDR - 4));
}
else
{
/* If it has no associate cluster buffer, check only owner bit. */
if (pTbd->status & S3C2510_ETH_TBD_O)
{
return NULL;
}
}
/* Advance to next TBD. */
pDrvCtrl->tbdFree++;
if (pDrvCtrl->tbdFree == NUM_TBD_ETH)
{
pDrvCtrl->tbdFree = 0;
}
return (pTbd);
}
/*******************************************************************************
*
* s3c2510EthTbdFree - free TBD
*
* RETURNS: N/A.
*/
void s3c2510EthTbdFree(
ETH_DRV_CTRL *pDrvCtrl, /* pointer to driver structure */
PETHTBD pTbd /* pointer to the TBD to be freed */
)
{
#ifdef DEBUG_TRACE
printf("s3c2510Eth%d TbdFree\n", pDrvCtrl->unit);
#endif /* DEBUG_TRACE */
/* Free cluster buffer if necessary. */
if (pDrvCtrl->pClPool)
{
netClFree(pDrvCtrl->endObj.pNetPool, (UCHAR *)(pTbd->pBuf - (SIZE_ETH_FB_HDR - 4)));
}
/* Free the used TBD. */
pTbd->length = 0;
/* Advance to next RBD. */
pDrvCtrl->tbdIndex++;
if (pDrvCtrl->tbdIndex == NUM_TBD_ETH)
{
pDrvCtrl->tbdIndex = 0;
}
}
/*******************************************************************************
*
* s3c2510EthTbdStart - start transmit
*
* RETURNS: N/A.
*/
void s3c2510EthTbdStart(
ETH_DRV_CTRL *pDrvCtrl, /* pointer to driver structure */
PETHTBD pTbd, /* pointer to the TBD to be freed */
ULONG length /* length of data */
)
{
int unit = pDrvCtrl->unit;
#ifdef DEBUG_TRACE
printf("s3c2510Eth%d TbdStart\n", unit);
#endif /* DEBUG_TRACE */
pTbd->length = (UINT16)length;
pTbd->status = S3C2510_ETH_TBD_O | (SIZE_ETH_WA << S3C2510_ETH_TBD_WA_SHIFT);
/* Enable MAC Tx. */
*S3C2510_MTXCON(unit) |= S3C2510_MTXCON_EN; /* Transmission Enable */
/* Enable BDMA Tx. */
*S3C2510_BTXCON(unit) |= S3C2510_BTXCON_EN; /* BDMA Tx Block Enable */
}
/*******************************************************************************
*
* s3c2510EthTbdCheck - check TBD
*
* RETURNS: OK, or ERROR.
*/
STATUS s3c2510EthTbdCheck(
ETH_DRV_CTRL *pDrvCtrl, /* pointer to driver structure */
PETHTBD pTbd /* pointer to the TBD to be checked */
)
{
int unit = pDrvCtrl->unit;
int timeout = TX_WAIT_MAX;
int retry = 3;
#ifdef DEBUG_TRACE
printf("s3c2510Eth%d TbdCheck\n", pDrvCtrl->unit);
#endif /* DEBUG_TRACE */
/* Check if completed. */
while (pTbd->status & S3C2510_ETH_TBD_O)
{
if (--timeout == 0)
{
if (--retry == 0)
{
printf("s3c2510Eth%d Error: Tx timeout\n", pDrvCtrl->unit);
return ERROR;
}
timeout = TX_WAIT_MAX;
if (!(*S3C2510_BTXCON(unit) & S3C2510_BTXCON_EN))
{
/* Enable BDMA Tx. */
*S3C2510_BTXCON(unit) |= S3C2510_BTXCON_EN; /* BDMA Tx Block Enable */
}
}
}
if (pTbd->status & (S3C2510_ETH_TBD_MPAUSED | /* MAC Tx Paused */
S3C2510_ETH_TBD_MHALTED | /* MAC Tx Halted */
S3C2510_ETH_TBD_MSQEERR | /* MAC Tx Signal Quality Error */
S3C2510_ETH_TBD_MPARERR | /* MAC Tx Parity Error */
S3C2510_ETH_TBD_MLATECOLL | /* MAC Tx Late Collision */
S3C2510_ETH_TBD_MNOCARR | /* MAC Tx No Carrier */
S3C2510_ETH_TBD_MDEFERERR | /* MAC Tx Deferred Error */
S3C2510_ETH_TBD_MUNDERFLOW | /* MAC Tx FIFO Underflow */
S3C2510_ETH_TBD_MEXCOLL)) /* MAC Tx Excessive Collion is Occured */
{
if (pTbd->status & S3C2510_ETH_TBD_MPAUSED)
{
#ifdef DEBUG_TRACE
printf(" S3C2510_ETH_TBD_MPAUSED\n");
#endif /* DEBUG_TRACE */
/* Up-date statistics. */
pDrvCtrl->mTxPaused++;
}
if (pTbd->status & S3C2510_ETH_TBD_MHALTED)
{
#ifdef DEBUG_TRACE
printf(" S3C2510_ETH_TBD_MHALTED\n");
#endif /* DEBUG_TRACE */
/* Up-date statistics. */
pDrvCtrl->mTxHalted++;
}
if (pTbd->status & S3C2510_ETH_TBD_MSQEERR)
{
#ifdef DEBUG_TRACE
printf(" S3C2510_ETH_TBD_MSQEERR\n");
#endif /* DEBUG_TRACE */
/* Up-date statistics. */
pDrvCtrl->mTxSqeErr++;
}
if (pTbd->status & S3C2510_ETH_TBD_MPARERR)
{
#ifdef DEBUG_TRACE
printf(" S3C2510_ETH_TBD_MPARERR\n");
#endif /* DEBUG_TRACE */
/* Up-date statistics. */
pDrvCtrl->mTxParErr++;
}
if (pTbd->status & S3C2510_ETH_TBD_MLATECOLL)
{
#ifdef DEBUG_TRACE
printf(" S3C2510_ETH_TBD_MLATECOLL\n");
#endif /* DEBUG_TRACE */
/* Up-date statistics. */
pDrvCtrl->mTxLateColl++;
}
if (pTbd->status & S3C2510_ETH_TBD_MNOCARR)
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -