📄 sndsend.c
字号:
* .bS
* unit Device unit number, a small integer.
* Speed 10 (10Mbps) or 100 (100 Mbps)
* duplex 0 (HDX) or 1 (FDX)
* autoneg Autonegotiation disabled (0) or enabled (1)
* .bE
*
* RETURNS: OK or ERROR for invalid arguments.
*/
STATUS sndsEndParse
(
END_DEVICE * pDrvCtrl, /* device pointer */
char * initString /* information string */
)
{
char* tok;
char* pHolder = NULL;
/* Parse the initString */
/* Unit number. */
tok = strtok_r (initString, ":", &pHolder);
if (tok == NULL)
return ERROR;
pDrvCtrl->unit = atoi (tok);
/* netSpeed */
tok = strtok_r (NULL, ":", &pHolder);
if (tok == NULL)
return ERROR;
pDrvCtrl->netSpeed = atoi (tok);
/* DuplexMode */
tok = strtok_r (NULL, ":", &pHolder);
if (tok == NULL)
return ERROR;
pDrvCtrl->duplexMode = atoi (tok);
/* auto Negotiation */
tok = strtok_r (NULL, ":", &pHolder);
if (tok == NULL)
return ERROR;
pDrvCtrl->autoNeg = atoi (tok);
return OK;
}
/*******************************************************************************
*
* sndsEndMemInit - initialize memory for the chip
*
* This routine is highly specific to the device.
*
* RETURNS: OK or ERROR.
*/
STATUS sndsEndMemInit
(
END_DEVICE * pDrvCtrl /* device to be initialized */
)
{
/*
* This is how we would set up and END netPool using netBufLib(1).
* This code is pretty generic.
*/
if ((pDrvCtrl->end.pNetPool = (NET_POOL_ID) malloc (sizeof(NET_POOL))) == NULL)
return (ERROR);
endMclConfig.mBlkNum = END_MBLK_NUM;
endClDescTbl[0].clNum = END_CL_NUM;
endMclConfig.clBlkNum = endClDescTbl[0].clNum;
/* Calculate the total memory for all the M-Blks and CL-Blks. */
endMclConfig.memSize = (endMclConfig.mBlkNum * (MSIZE + sizeof (long))) +
(endMclConfig.clBlkNum * (CL_BLK_SZ + sizeof(long)));
if ((endMclConfig.memArea = (char *) memalign (sizeof(long),
endMclConfig.memSize))
== NULL)
return (ERROR);
/* Calculate the memory size of all the clusters. */
endClDescTbl[0].memSize = (endClDescTbl[0].clNum * (endClDescTbl[0].clSize + 8))
+ sizeof(int); /* +8 is for proper alignment */
/* Allocate the memory for the clusters */
endClDescTbl[0].memArea =
(char *) malloc (endClDescTbl[0].memSize);
if ((int)endClDescTbl[0].memArea == NULL)
{
return (ERROR);
}
/* Initialize the memory pool. */
if (netPoolInit(pDrvCtrl->end.pNetPool, &endMclConfig,
&endClDescTbl[0], endClDescTblNumEnt, NULL) == ERROR)
{
return (ERROR);
}
return OK;
}
/*******************************************************************************
*
* sndsEndStart - start the device
*
* This function calls BSP functions to connect interrupts and start the
* device running in interrupt mode.
*
* RETURNS: OK or ERROR
*
*/
LOCAL STATUS sndsEndStart
(
END_DEVICE *pDrvCtrl /* device to be started */
)
{
BDMARXCON bdmaRxCon;
MACRXCON macRxCon;
/* init BDMARXCON register */
*(UINT32 *) (&bdmaRxCon) = *(UINT32 *)SNDS_BDMARXCON;
bdmaRxCon.rxCon_reg.recvFrameIntrEnb = 1;
bdmaRxCon.rxCon_reg.nullListIntrEnb = 1;
bdmaRxCon.rxCon_reg.notOwnerIntrEnb = 1;
bdmaRxCon.rxCon_reg.enable = 1 ;
*(UINT32 *)SNDS_BDMARXCON = bdmaRxCon.rxCon_resetval;
printf("\rBDMARXCON %x\r", *(UINT32 *)SNDS_BDMARXCON) ;
/* init MACRXCON register */
*(UINT32 *)(&macRxCon) = *(UINT32 *)SNDS_MACRXCON;
macRxCon.macRxCon_reg.receiveEnable = 1;
*(UINT32 *)SNDS_MACRXCON = macRxCon.macRxCon_resetval;
/* Connect BDMA and MAC TX and RX interrupts */ /*modified by knp/nts 27/9/99 */
intConnect ((VOIDFUNCPTR *)INUM_TO_IVEC (pDrvCtrl->ivecBdmaTx), sndsEndBdmaTxInt, NULL);
intConnect ((VOIDFUNCPTR *)INUM_TO_IVEC (pDrvCtrl->ivecBdmaRx), sndsEndBdmaRxInt, (UINT32) pDrvCtrl);
intConnect ((VOIDFUNCPTR *)INUM_TO_IVEC (pDrvCtrl->ivecMacTx), sndsEndMacTxInt, (UINT32) pDrvCtrl);
intConnect ((VOIDFUNCPTR *)INUM_TO_IVEC (pDrvCtrl->ivecMacRx), sndsEndMacRxInt, NULL);
/* Enable all the four interrupts */ /*modified by knp/nts 27/9/9/99 */
intEnable (pDrvCtrl->ivecBdmaTx);
intEnable (pDrvCtrl->ivecBdmaRx);
intEnable (pDrvCtrl->ivecMacTx);
intEnable (pDrvCtrl->ivecMacRx);
/* Set the flags to indicate that the device is up */
END_FLAGS_SET (&pDrvCtrl->end, IFF_UP | IFF_RUNNING);
return (OK);
}
/******************************************************************************
* sndsEndBdmaTxInt - handle controller interrupt
*
* This routine is called at interrupt level in response to an interrupt from
* the BdmaTx controller.
*
* RETURNS: N/A.
*/
LOCAL void sndsEndBdmaTxInt
(
END_DEVICE *pDrvCtrl /* interrupting device */
)
{
/**Nothing to be done here**/
}
/*******************************************************************************
* sndsEndBdmaRxInt - handle controller interrupt
*
* This routine is called at interrupt level in response to an interrupt from
* the BdmaTx controller.
*
* RETURNS: N/A.
*/
LOCAL void sndsEndBdmaRxInt
(
END_DEVICE *pDrvCtrl /* interrupting device */
)
{
BDMASTAT bdmaStat;
bdmaStat.stat_resetval = *(UINT32 *)SNDS_BDMASTAT;
*(UINT32 *)SNDS_BDMASTAT |= bdmaStat.stat_resetval; /* Clear status bits */
netJobAdd ((FUNCPTR)sndsEndHandleRcvInt, (int)pDrvCtrl, bdmaStat.stat_resetval,0,0,0);
}
/*******************************************************************************
* sndsEndMacTxInt - handle controller interrupt
*
* This routine is called at interrupt level in response to an interrupt from
* the MacRx controller.
*
* RETURNS: N/A.
*/
LOCAL void sndsEndMacTxInt
(
END_DEVICE *pDrvCtrl /* interrupting device */
)
{
TRANSMIT_FRAME_DESC *pTxDesc;
*(UINT32 *)(&pTxDesc) = *(UINT32 *)(SNDS_BDMATXPTR);
while (pTxDesc != gpTransmitFrameDescStart)
{
if (pTxDesc->txFrameData.o_bit)
break; /* Ownership is still with BDMA */
if (pTxDesc->txStatusLength.comp)
{
pDrvCtrl->statistics.txGood++;
}
else /* Update error statistics */
{
if (pTxDesc->txStatusLength.underRun)
pDrvCtrl->statistics.txUnderErr++;
if (pTxDesc->txStatusLength.exColl)
pDrvCtrl->statistics.txExCollErr++;
if (pTxDesc->txStatusLength.txDefer)
pDrvCtrl->statistics.txDeferredErr++;
if (pTxDesc->txStatusLength.paused)
pDrvCtrl->statistics.txPaused++;
if (pTxDesc->txStatusLength.deferAl)
pDrvCtrl->statistics.txDeferErr++;
if (pTxDesc->txStatusLength.ncArr)
pDrvCtrl->statistics.txNCarrErr++;
if (pTxDesc->txStatusLength.sqeErr)
pDrvCtrl->statistics.txSQE++;
if (pTxDesc->txStatusLength.lateColl)
pDrvCtrl->statistics.txLateCollErr++;
if (pTxDesc->txStatusLength.txPar)
pDrvCtrl->statistics.txParErr++;
if (pTxDesc->txStatusLength.txHalted)
pDrvCtrl->statistics.txHalted++;
}
*(UINT32 *)(&pTxDesc->txStatusLength) = 0; /* Clear status field */
pTxDesc = pTxDesc->nextTxFrameDesc;
}
}
/*******************************************************************************
* sndsEndMacRxInt - handle controller interrupt
*
* This routine is called at interrupt level in response to an interrupt from
* the MacRx controller.
*
* RETURNS: N/A.
*/
LOCAL void sndsEndMacRxInt
(
END_DEVICE *pDrvCtrl /* interrupting device */
)
{
/***Nothing to be done here***/
}
/*******************************************************************************
*
* sndsEndHandleRcvInt - task level interrupt service for input packets
*
* This routine is called at task level indirectly by the interrupt
* service routine to do any message received processing.
*
* RETURNS: N/A.
*/
LOCAL void sndsEndHandleRcvInt
(
END_DEVICE *pDrvCtrl, /* interrupting device */
UINT32 stat /* receive status */
)
{
BDMASTAT bdmaStat;
/* inserted by jwchoi */
BDMARXCON bdmaRxCon;
MACRXCON macRxCon;
/* */
RECEIVE_FRAME_DESC *pReceiveFrameDesc;
UINT16 * pFrameData;
UINT32 frameLength;
bdmaStat.stat_resetval = stat;
*(UINT32 *)(&pReceiveFrameDesc) = *(UINT32 *)(SNDS_BDMARXPTR);
/*
if ((*(UINT32 *) (&gpReceiveFrameDescStart->rxStatusLength)) == 0)
return;
*/
do
{
/*
* Check if Null list interrupt has occurred. If yes, reset
* and restart the Ethernet MAC (as given in Samsung sample code.
*/
/*
* Received a good frame
*/
frameLength = gpReceiveFrameDescStart->rxStatusLength.frameLength;
if ((*(UINT32 *) (&gpReceiveFrameDescStart->rxStatusLength)) & 0xbfff0000 )
{
pDrvCtrl->statistics.rxBad++;
*(UINT32 *)SNDS_IOPDATA = 0xf3 ;
if (gpReceiveFrameDescStart->rxStatusLength.ovMax)
pDrvCtrl->statistics.rxOvMaxSize++;
if (gpReceiveFrameDescStart->rxStatusLength.ctlRcv)
pDrvCtrl->statistics.rxCtlRecd++;
if (gpReceiveFrameDescStart->rxStatusLength.rx10Stat)
pDrvCtrl->statistics.rx10Stat++;
if (gpReceiveFrameDescStart->rxStatusLength.alignErr)
pDrvCtrl->statistics.rxAlignErr++;
if (gpReceiveFrameDescStart->rxStatusLength.crcErr)
pDrvCtrl->statistics.rxCRCErr++;
if (gpReceiveFrameDescStart->rxStatusLength.overFlow)
pDrvCtrl->statistics.rxOverflowErr++;
if (gpReceiveFrameDescStart->rxStatusLength.longErr)
pDrvCtrl->statistics.rxLongErr++;
if (gpReceiveFrameDescStart->rxStatusLength.rxPar)
pDrvCtrl->statistics.rxParErr++;
if (gpReceiveFrameDescStart->rxStatusLength.rxHalted)
pDrvCtrl->statistics.rxHalted++;
}
else if((gpReceiveFrameDescStart->rxStatusLength.good))
{
pDrvCtrl->statistics.rxGood++;
pFrameData = (UINT16 *)(gpReceiveFrameDescStart->rxFrameData.frameDataPtr);
sndsEndBugFix (pFrameData);
sndsEndRecv (pDrvCtrl, (char *)pFrameData, frameLength);
*(UINT32 *)SNDS_IOPDATA = 0x3f ;
}
else ;
gpReceiveFrameDescStart->rxFrameData.o_bit = 1; /* Ownership back to BDMA */
gStatusLengthPrevious = *(UINT32 *)(&gpReceiveFrameDescStart->rxStatusLength); /* For MAC bug fix */
*(UINT32 *)(&gpReceiveFrameDescStart->rxStatusLength) = 0; /* Rx status length field */
gpReceiveFrameDescStart = gpReceiveFrameDescStart->nextRxFrameDesc;
} while (gpReceiveFrameDescStart != pReceiveFrameDesc);
if (bdmaStat.stat_reg.bdmaRxNotOwner) {
*(UINT32 *)SNDS_BDMASTAT = BRxNO ;
}
if(!(gpReceiveFrameDescStart->rxFrameData.o_bit)) ;
else if(! (*(UINT32 *)SNDS_BDMARXCON & BRxEn) ){
*(UINT32 *) (&bdmaRxCon) = *(UINT32 *)SNDS_BDMARXCON;
bdmaRxCon.rxCon_reg.enable = 1 ;
*(UINT32 *)SNDS_BDMARXCON = bdmaRxCon.rxCon_resetval;
}
/* *(UINT32 *)SNDS_IOPDATA = 0x00 ; */
/* printf("\r ## BRXCON %08x\n BPTR %08x",
*(UINT32 *)SNDS_BDMARXCON, *(UINT32 *)SNDS_BDMARXPTR) ; */
}
/*******************************************************************************
*
* sndsEndRecv - process the next incoming packet
*
* Handle one incoming packet. The packet is checked for errors.
*
* RETURNS: N/A.
*/
LOCAL STATUS sndsEndRecv
(
END_DEVICE *pDrvCtrl, /* device structure */
char* pData, /* packet to process */
UINT32 len
)
{
M_BLK_ID pMblk;
char* pNewCluster;
CL_BLK_ID pClBlk;
/* Add one to our unicast data. */
END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1);
/*
* We implicitly are loaning here, if copying is necessary this
* step may be skipped, but the data must be copied before being
* passed up to the protocols.
*/
pNewCluster = netClusterGet (pDrvCtrl->end.pNetPool, pDrvCtrl->end.pNetPool->clTbl[0]);
if (pNewCluster == NULL)
{
END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
goto cleanRXD;
}
/* Grab a cluster block to marry to the cluster we received. */
if ((pClBlk = netClBlkGet (pDrvCtrl->end.pNetPool, M_DONTWAIT)) == NULL)
{
netClFree (pDrvCtrl->end.pNetPool, pNewCluster);
END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
goto cleanRXD;
}
/*
* OK we've got a spare, let's get an M_BLK_ID and marry it to the
* one in the ring.
*/
if ((pMblk = mBlkGet (pDrvCtrl->end.pNetPool, M_DONTWAIT, MT_DATA)) == NULL)
{
netClBlkFree (pDrvCtrl->end.pNetPool, pClBlk);
netClFree (pDrvCtrl->end.pNetPool, pNewCluster);
END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
goto cleanRXD;
}
END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1);
(UINT32)pData &= ~NON_CACHE_REGION;
/* Join the cluster to the MBlock */
netClBlkJoin (pClBlk, pData, SNDS_CL_SIZE, NULL, 0, 0, 0);
netMblkClJoin (pMblk, pClBlk);
pMblk->mBlkHdr.mData += SNDS_DATA_OFFSET;
if (gBugFixDone == TRUE)
pMblk->mBlkHdr.mData += 4;
pMblk->mBlkHdr.mLen = len;
pMblk->mBlkHdr.mFlags |= M_PKTHDR;
pMblk->mBlkPktHdr.len = len;
/* Call the upper layer's receive routine. */
END_RCV_RTN_CALL(&pDrvCtrl->end, pMblk);
gpReceiveFrameDescStart->rxFrameData.frameDataPtr = (UINT32)pNewCluster;
cleanRXD:
gpReceiveFrameDescStart->rxFrameData.frameDataPtr |= NON_CACHE_REGION;
return (OK);
}
/*******************************************************************************
*
* sndsEndSend - the driver send routine
*
* This routine takes a M_BLK_ID sends off the data in the M_BLK_ID.
* The buffer must already have the addressing information properly installed
* in it. This is done by a higher layer. The last arguments are a free
* routine to be called when the device is done with the buffer and a pointer
* to the argument to pass to the free routine.
*
* RETURNS: OK or ERROR.
*/
LOCAL STATUS sndsEndSend
(
END_DEVICE *pDrvCtrl, /* device ptr */
M_BLK_ID pNBuff /* data to send */
)
{
int len;
int oldLevel;
BOOL freeNow = TRUE;
TRANSMIT_FRAME_DESC *pTxFd;
BDMATXCON bdmaTxCon;
MACTXCON macTxCon;
*(UINT32 *)(&bdmaTxCon) = 0;
*(UINT32 *)(&macTxCon) = 0;
if (gpTransmitFrameDescStart->txFrameData.o_bit) /* Ownership with BDMA? */
return ERROR;
pTxFd = gpTransmitFrameDescStart;
len = pNBuff->mBlkPktHdr.len;
/*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -