📄 motcpmend.c
字号:
*
* If it detects a transmission error, the restart command is issued.
*
* These routine should not call any kernel functions.
*
* RETURNS: OK or EAGAIN
*/
/*LOCAL STATUS motCpmEndPollSend*/
LOCAL STATUS motCpmEndSend/*wut 2004.7.22modify*/
(
END_CTRL *pDrvCtrl, /* pointer to END_CTRL structure */
M_BLK_ID pMblk /* data to send */
)
{
int length;
int oldLevel;
SCC_BUF * pTxBd;
u_char * pad;
char * pBuf;
if(send1==1)
MOTCPMLOGMSG(("motCpmEndSend_START \n", 0, 0, 0, 0, 0, 0));
END_TX_SEM_TAKE (&pDrvCtrl->endObject, WAIT_FOREVER);
/* get a free transmit frame descriptor */
pTxBd = & pDrvCtrl->ether.txBdBase[pDrvCtrl->ether.txBdNext];
/* check if a transmit buffer descriptor is available */
if ((pTxBd->statusMode & SCC_ETHER_TX_BD_R) ||
(((pDrvCtrl->ether.txBdNext + 1) % pDrvCtrl->ether.txBdNum)
== pDrvCtrl->txBdIndexC))
{
END_TX_SEM_GIVE (&pDrvCtrl->endObject);
if(send3==1)
MOTCPMLOGMSG(("pTxBd->statusMode & SCC_ETHER_TX_BD_R \n", 0, 0, 0, 0, 0, 0));
motCpmCleanTxBdQueue (pDrvCtrl);
return (EAGAIN);
}
/* fill the transmit frame descriptor */
pBuf = netClusterGet (pDrvCtrl->endObject.pNetPool, pDrvCtrl->pClPoolId);
if (pBuf == NULL)
{
END_TX_SEM_GIVE (&pDrvCtrl->endObject);
if(send4==1)
MOTCPMLOGMSG(("tran_pBuf == NULL \n", 0, 0, 0, 0, 0, 0));
netMblkClChainFree(pMblk); /*wutao*/
return (ERROR);
}
length = netMblkToBufCopy (pMblk, (char *)pBuf, NULL);
pTxBd->dataPointer = (u_char *) pBuf;
/* padding mechanism in Rev A is buggy - do in software */
if (length < FRAME_MIN)
{
pad = pTxBd->dataPointer + length;
for (; length != FRAME_MIN; length++, pad++)
*pad = 0x88;
}
pTxBd->dataLength = length;
oldLevel = intLock (); /* disable ints during update */
if (pTxBd->statusMode & SCC_ETHER_TX_BD_W)
pTxBd->statusMode = SCC_ETHER_TX_BD_I | SCC_ETHER_TX_BD_PAD |
SCC_ETHER_TX_BD_L | SCC_ETHER_TX_BD_TC |
SCC_ETHER_TX_BD_W | SCC_ETHER_TX_BD_R;
else
pTxBd->statusMode = SCC_ETHER_TX_BD_I | SCC_ETHER_TX_BD_PAD |
SCC_ETHER_TX_BD_L | SCC_ETHER_TX_BD_TC |
SCC_ETHER_TX_BD_R;
/* incr BD count */
pDrvCtrl->ether.txBdNext = (pDrvCtrl->ether.txBdNext + 1) %
pDrvCtrl->ether.txBdNum;
intUnlock (oldLevel);
/* Bump the statistic counter. */
END_ERR_ADD (&pDrvCtrl->endObject, MIB2_OUT_UCAST, +1);
/*
* Spin until we've sent it.
*/
if(send5==1)
MOTCPMLOGMSG(("while no over \n", 0, 0, 0, 0, 0, 0));
while (pTxBd->statusMode & SCC_ETHER_TX_BD_R)
;
if (pTxBd->statusMode & (SCC_ETHER_TX_BD_RL | SCC_ETHER_TX_BD_UN |
SCC_ETHER_TX_BD_CSL | SCC_ETHER_TX_BD_LC))
{
/* An error has occured, restart the transmitter */
if(send6==1)
MOTCPMLOGMSG(("pDrvCtrl->txStop = TRUE \n", 0, 0, 0, 0, 0, 0));
motCpmTxRestart (pDrvCtrl);
motCpmCleanTxBdQueue (pDrvCtrl);
}
netClFree (pDrvCtrl->endObject.pNetPool, pBuf);
netMblkClChainFree(pMblk);
pDrvCtrl->txBdIndexC = pDrvCtrl->ether.txBdNext;
if(send7==1)
MOTCPMLOGMSG(("tran_over \n", 0, 0, 0, 0, 0, 0));
END_TX_SEM_GIVE (&pDrvCtrl->endObject);
return (OK);
}
/******************************************************************************
*
* motCpmEndPollSend - transmit a packet in polled mode
*
* This routine is called by a user to try and send a packet on the
* device. It sends a packet directly on the network from the caller without
* going through the normal processes of queuing a pacet on an output queue
* and the waiting for the device to decide to transmit it.
*
* If it detects a transmission error, the restart command is issued.
*
* These routine should not call any kernel functions.
*
* RETURNS: OK or EAGAIN
*/
LOCAL STATUS motCpmEndPollSend
(
END_CTRL *pDrvCtrl, /* pointer to END_CTRL structure */
M_BLK_ID pMblk /* data to send */
)
{
int length;
SCC_BUF * pTxBd;
u_char * pad;
char * pBuf;
MOTCPMLOGMSG(("motCpmEndPollSend \n", 0, 0, 0, 0, 0, 0));
if (pDrvCtrl->txStop)
return (ERROR);
/* get a free transmit frame descriptor */
pTxBd = & pDrvCtrl->ether.txBdBase[pDrvCtrl->ether.txBdNext];
/* check if a transmit buffer descriptor is available */
if ((pTxBd->statusMode & SCC_ETHER_TX_BD_R) ||
(((pDrvCtrl->ether.txBdNext + 1) % pDrvCtrl->ether.txBdNum)
== pDrvCtrl->txBdIndexC))
{
motCpmCleanTxBdQueue (pDrvCtrl);
return (EAGAIN);
}
/* fill the transmit frame descriptor */
pBuf = netClusterGet (pDrvCtrl->endObject.pNetPool, pDrvCtrl->pClPoolId);
if (pBuf == NULL)
{
return (ERROR);
}
length = netMblkToBufCopy (pMblk, (char *)pBuf, NULL);
pTxBd->dataPointer = (u_char *) pBuf;
/* padding mechanism in Rev A is buggy - do in software */
if (length < FRAME_MIN)
{
pad = pTxBd->dataPointer + length;
for (; length != FRAME_MIN; length++, pad++)
*pad = 0x88;
}
pTxBd->dataLength = length;
if (pTxBd->statusMode & SCC_ETHER_TX_BD_W)
pTxBd->statusMode = SCC_ETHER_TX_BD_I | SCC_ETHER_TX_BD_PAD |
SCC_ETHER_TX_BD_L | SCC_ETHER_TX_BD_TC |
SCC_ETHER_TX_BD_W | SCC_ETHER_TX_BD_R;
else
pTxBd->statusMode = SCC_ETHER_TX_BD_I | SCC_ETHER_TX_BD_PAD |
SCC_ETHER_TX_BD_L | SCC_ETHER_TX_BD_TC |
SCC_ETHER_TX_BD_R;
/* incr BD count */
pDrvCtrl->ether.txBdNext = (pDrvCtrl->ether.txBdNext + 1) %
pDrvCtrl->ether.txBdNum;
/* Bump the statistic counter. */
END_ERR_ADD (&pDrvCtrl->endObject, MIB2_OUT_UCAST, +1);
/*
* Spin until we've sent it.
*/
while (pTxBd->statusMode & SCC_ETHER_TX_BD_R)
;
if (pTxBd->statusMode & (SCC_ETHER_TX_BD_RL | SCC_ETHER_TX_BD_UN |
SCC_ETHER_TX_BD_CSL | SCC_ETHER_TX_BD_LC))
{
/* An error has occured, restart the transmitter */
pDrvCtrl->txStop = TRUE;
motCpmTxRestart (pDrvCtrl);
}
/*
* we are allow to do this because transmit queue is empty when we
* start polling mode.
*/
netClFree (pDrvCtrl->endObject.pNetPool, pBuf);
netMblkClChainFree(pMblk);
pDrvCtrl->txBdIndexC = pDrvCtrl->ether.txBdNext;
return (OK);
}
/*******************************************************************************
*
* motCpmEndPollReceive - receive a packet in polled mode
*
* This routine is called by a user to try and get a packet from the
* device. It returns EAGAIN if no packet is available. The caller must
* supply a M_BLK_ID with enough space to contain the receiving packet. If
* enough buffer is not available then EAGAIN is returned.
*
* These routine should not call any kernel functions.
*
* RETURNS: OK or EAGAIN
*/
LOCAL STATUS motCpmEndPollReceive
(
END_CTRL *pDrvCtrl, /* pointer to END_CTRL structure */
M_BLK_ID pMblk
)
{
SCC_BUF * pRxBd = & pDrvCtrl->ether.rxBdBase[pDrvCtrl->ether.rxBdNext];
int length;
int status = EAGAIN;
MOTCPMLOGMSG(("motCpmEndPollReceive \n", 0, 0, 0, 0, 0, 0));
/* if we have not received packets, leave immediatly */
if (pRxBd->statusMode & SCC_ETHER_RX_BD_E)
return (EAGAIN);
/* check packets for errors */
if (((pRxBd->statusMode & (SCC_ETHER_RX_BD_F | SCC_ETHER_RX_BD_L))
== (SCC_ETHER_RX_BD_F | SCC_ETHER_RX_BD_L))
&& !(pRxBd->statusMode & (SCC_ETHER_RX_BD_CL |
SCC_ETHER_RX_BD_OV | SCC_ETHER_RX_BD_CR |
SCC_ETHER_RX_BD_SH | SCC_ETHER_RX_BD_NO |
SCC_ETHER_RX_BD_LG)))
{
/* adjust length to data only */
length = pRxBd->dataLength;
if ((length - SIZEOF_ETHERHEADER) <= 0)
{
/* bump input error packet counter */
END_ERR_ADD (&pDrvCtrl->endObject, MIB2_IN_ERRS, +1);
goto cleanRxBd;
}
/*
* Upper layer provides the buffer.
* If buffer is not large enough, we return.
*/
/* copy data */
if ((pMblk->mBlkHdr.mLen < length) ||
(!(pMblk->mBlkHdr.mFlags & M_EXT)))
{
goto cleanRxBd;
}
bcopy ((char *) pRxBd->dataPointer, (char *)pMblk->mBlkHdr.mData,
length);
pMblk->mBlkHdr.mLen = length;
pMblk->mBlkPktHdr.len = length;
pMblk->mBlkHdr.mFlags |= M_PKTHDR;
/* bump input packet counter */
END_ERR_ADD (&pDrvCtrl->endObject, MIB2_IN_UCAST, +1);
status = OK;
}
else
{
/* bump input error packet counter */
END_ERR_ADD (&pDrvCtrl->endObject, MIB2_IN_ERRS, +1);
}
cleanRxBd:
motCpmCleanRxBd (pDrvCtrl, pRxBd); /* reset buffer descriptor as empty */
return (status);
}
/*******************************************************************************
*
* motCpmIntr - network interface interrupt handler
*
* This routine gets called at interrupt level. It handles work that
* requires minimal processing. Interrupt processing that is more
* extensive gets handled at task level. The network task, netTask(), is
* provided for this function. Routines get added to the netTask() work
* queue via the netJobAdd() command.
*
* RETURNS: N/A
*/
LOCAL void motCpmIntr/*wut*/
(
END_CTRL * pDrvCtrl /* pointer to END_CTRL structure */
)
{
BOOL rxHandle = FALSE;
BOOL txbHandle = FALSE;
/* check for spurious interrupt -> initialized ? */
if (!pDrvCtrl->endObject.attached)
{
pDrvCtrl->ether.pSccReg->scce = 0xffff;
*CPM_CISR(pDrvCtrl->regBase) = pDrvCtrl->ether.intMask;
return;
}
/* handle receive events */
if ((pDrvCtrl->ether.pSccReg->sccm & SCC_ETHER_SCCX_RXF) &&
(pDrvCtrl->ether.pSccReg->scce & SCC_ETHER_SCCX_RXF))
{
(void) netJobAdd ((FUNCPTR) motCpmHandleInt, (int) pDrvCtrl,
0, 0, 0, 0);
/* turn off receive interrupts for now - motCpmHandleIt turns back on */
pDrvCtrl->ether.pSccReg->sccm &= ~SCC_ETHER_SCCX_RXF;
rxHandle = TRUE;
}
/* check for output errors */
if (pDrvCtrl->ether.pSccReg->scce & SCC_ETHER_SCCX_TXE)
{
/* clean the transmit buffer descriptor queue */
/* NOTE: HBC error not supported -> always RESTART Tx here */
if(send11==1)
MOTCPMLOGMSG(("netJobAdd (FUNCPTR) motCpmTxRestart\n", 0, 0, 0, 0, 0, 0));
if ( !pDrvCtrl->txCleaning)
motCpmCleanTxBdQueue (pDrvCtrl);
pDrvCtrl->ether.pSccReg->scce = SCC_ETHER_SCCX_TXE;
(void) netJobAdd ((FUNCPTR) motCpmTxRestart, (int) pDrvCtrl,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -