📄 ethernet.c
字号:
endEtherPacketAddrGet /* Get packet addresses. */
};
/*******************************************************************************
*
* sndsEndLoad - initialize the driver and device
*
* This routine initializes the driver and the device to the operational state.
* All of the device specific parameters are passed in the initString.
*
* The string contains the target specific parameters like this:
*
* "<unit>:<Speed>:<duplex>:<autoneg>"
*
* RETURNS: An END object pointer or NULL on error.
*/
END_OBJ* sndsEndLoad
(
char* initString /* String to be parsed by the driver. */
)
{
END_DEVICE *pDrvCtrl;
#if 0
ENDLOGMSG (("Loading sndsEndEnd...\n", 1, 2, 3, 4, 5, 6));
#endif
if (initString[0] == NULL)
{
strcpy (initString, "secEnd");
return (END_OBJ *)0;
}
/* allocate the device structure */
pDrvCtrl = (END_DEVICE *)calloc (sizeof (END_DEVICE), 1);
if (pDrvCtrl == NULL)
goto errorExit;
/* parse the init string, filling in the device structure */
if (sndsEndParse (pDrvCtrl, initString) == ERROR)
goto errorExit;
pDrvCtrl->ivecBdmaTx = INT_LVL_BDMATx;
pDrvCtrl->ivecBdmaRx = INT_LVL_BDMARx;
pDrvCtrl->ivecMacTx = INT_LVL_MACTx;
pDrvCtrl->ivecMacRx = INT_LVL_MACRx;
/* Ask the BSP to provide the ethernet address. */
SYS_ENET_ADDR_GET(pDrvCtrl);
strcpy (pDrvCtrl->end.devObject.name, "secEnd");
strcpy (pDrvCtrl->end.devObject.description, "Samsung SNDS100 END Driver");
/* initialize the END and MIB2 parts of the structure */
/*
* The M2 element must come from m2Lib.h
* This sndsEnd is set up for a DIX type ethernet device.
*/
if (END_OBJ_INIT (&pDrvCtrl->end, (DEV_OBJ *)pDrvCtrl, "secEnd",
pDrvCtrl->unit, &endFuncTable,
"Samsung SNDS100 END Driver") == ERROR
|| END_MIB_INIT (&pDrvCtrl->end, M2_ifType_ethernet_csmacd,
&pDrvCtrl->enetAddr[0], 6, ETHERMTU,
END_SPEED)
== ERROR)
goto errorExit;
/* Perform memory allocation/distribution */
if (sndsEndMemInit (pDrvCtrl) == ERROR)
goto errorExit;
/* reset and reconfigure the device */
sndsEndConfig (pDrvCtrl);
/* set the flags to indicate readiness */
END_OBJ_READY (&pDrvCtrl->end, IFF_NOTRAILERS | IFF_BROADCAST | IFF_MULTICAST);
return (&pDrvCtrl->end);
errorExit:
if (pDrvCtrl != NULL)
free ((char *)pDrvCtrl);
return NULL;
}
/*******************************************************************************
*
* sndsEndParse - parse the init string
*
* Parse the input string. Fill in values in the driver control structure.
*
* The initialization string format is:
* "<unit>:<Speed>:<duplex>:<autoneg>"
*
* .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 */
)
{
#if 1
BDMARXCON bdmaRxCon;
#endif
unsigned long i;
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;
/* 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.
*/
static int GoodCnt = 0;
LOCAL void sndsEndHandleRcvInt
(
END_DEVICE *pDrvCtrl, /* interrupting device */
UINT32 stat /* receive status */
)
{
BDMASTAT bdmaStat;
BDMARXCON bdmaRxCon;
RECEIVE_FRAME_DESC *pReceiveFrameDesc;
UINT16 * pFrameData;
UINT32 frameLength;
bdmaStat.stat_resetval = stat;
*(UINT32 *)(&pReceiveFrameDesc) = *(UINT32 *)(SNDS_BDMARXPTR);
*(UINT32 *)(&bdmaRxCon)=*(UINT32 *) (SNDS_BDMARXCON);
if ((*(UINT32 *) (&gpReceiveFrameDescStart->rxStatusLength)) == 0)
return;
*(UINT32 *)SNDS_IOPDATA = 0xff ;
/*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -