📄 ethernet.c
字号:
*
* sndsEndUnload - unload a driver from the system
*
* This function first brings down the device, and then frees any
* stuff that was allocated by the driver in the load function.
*
* RETURNS: OK or ERROR.
*/
LOCAL STATUS sndsEndUnload
(
END_DEVICE* pDrvCtrl /* device to be unloaded */
)
{
END_OBJECT_UNLOAD (&pDrvCtrl->end); /*this call will indicate */
/* protocol that the device will be unloaded */
/* TODO - Free any shared DMA memory */
sndsEndStop(pDrvCtrl); /*before unloading the device will stop functioning*/
sndsEndReset(pDrvCtrl); /*then it will reset the registers in order to clear any pending interrupts */
if (pDrvCtrl->fdInitialized)
sndsEndFdFree(pDrvCtrl);
if (pDrvCtrl->end.pNetPool)
{
netPoolDelete (pDrvCtrl->end.pNetPool);
free (pDrvCtrl->end.pNetPool);
pDrvCtrl->end.pNetPool = (NET_POOL_ID)0;
}
if (endClDescTbl[0].memArea)
{
free (endClDescTbl[0].memArea);
endClDescTbl[0].memArea = (char *)0;
}
if (endMclConfig.memArea)
{
free (endMclConfig.memArea);
endMclConfig.memArea = (char *)0;
}
if (pDrvCtrl)
{
free (pDrvCtrl);
(END_DEVICE *)pDrvCtrl = 0;
}
return (OK);
}
/******************************************************************************
* sndsEndReset - Reset the device
* This function resets the driver after initializing from sndsEndLoad
*/
LOCAL void sndsEndReset
(
END_DEVICE* pDrvCtrl /* device to be reset */
)
{
BDMARXCON bdmaRxCon;
BDMATXCON bdmaTxCon;
BDMARXLSZ bdmaRxLsz;
MACCON macCon;
if(pDrvCtrl->unit != 0)
return;
*(UINT32 *) (&bdmaRxCon) = 0;
*(UINT32 *) (&bdmaTxCon) = 0;
*(UINT32 *) (&bdmaRxLsz) = 0;
*(UINT32 *) (&macCon) = 0;
if (pDrvCtrl->autoNeg == 1) /* auto negotiation enabled? */
sndsEndPhyWrite (PHY_CONTROL_REG, PHY_ADDR, _AUTO_NEGOTIATE);
else if (pDrvCtrl->netSpeed == 10)
sndsEndPhyWrite (PHY_CONTROL_REG, PHY_ADDR, _10_MB_HDX);
else if (pDrvCtrl->netSpeed == 100)
{
if (pDrvCtrl->duplexMode == 1) /* FDX */
sndsEndPhyWrite (PHY_CONTROL_REG, PHY_ADDR, _100_MB_FDX);
else
sndsEndPhyWrite (PHY_CONTROL_REG, PHY_ADDR, _100_MB_HDX);
}
bdmaRxCon.rxCon_reg.reset = 1;
*(UINT32 *)SNDS_BDMARXCON = bdmaRxCon.rxCon_resetval;
bdmaTxCon.txCon_reg.reset = 1;
*(UINT32 *)SNDS_BDMATXCON = bdmaTxCon.txCon_resetval;
bdmaRxLsz.rxLsz_reg.bdmaRxMaxSize = END_BUFSIZ;
*(UINT32 *)SNDS_BDMARXLSZ = bdmaRxLsz.rxLsz_resetval;
macCon.macCon_reg.swReset = 1;
*(UINT32 *)SNDS_MACCON = macCon.macCon_resetval;
return;
}
/******************************************************************************
* sndsEndPhyRead - Read PHY device
* This function is used to read a byte from the PHY device
*/
LOCAL UINT32 sndsEndPhyRead
(
UINT32 phyRegAddr, /* Address of PHY register to be read */
UINT32 phyAddr /* Address of the PHY chip (usually 0 for single PHY) */
)
{
UINT32 phyData;
STACON staCon;
*(UINT32 *) (&staCon) = 0;
staCon.staCon_reg.phyRegisterAddr = phyRegAddr;
staCon.staCon_reg.phyAddr = phyAddr;
staCon.staCon_reg.busy = 1;
*(UINT32 *)SNDS_STACON = staCon.staCon_resetval;
while (*(UINT32 *)SNDS_STACON & 0x800) /***** Busy bit ***/
; /* Wait till busy bit is clear */
phyData = *(UINT32 *)(SNDS_STADATA);
return (phyData);
}
/******************************************************************************
* sndsEndPhyWrite - Wrire into PHY device
* This function is used to write a byte to the PHY device
*/
LOCAL void sndsEndPhyWrite
(
UINT32 phyRegAddr, /* Address of PHY register to be written */
UINT32 phyAddr, /* Address of the PHY chip (usually 0 for single PHY) */
UINT32 phyData /* Data to be written */
)
{
STACON staCon;
UINT32 count = 1000;
*(UINT32 *)(SNDS_STADATA) = phyData;
*(UINT32 *) (&staCon) = 0;
staCon.staCon_reg.phyRegisterAddr = phyRegAddr;
staCon.staCon_reg.phyAddr = phyAddr;
staCon.staCon_reg.busy = 1;
staCon.staCon_reg.write = 1;
*(UINT32 *)SNDS_STACON = staCon.staCon_resetval;
while (*(UINT32 *)SNDS_STACON & 0x800) /***** Busy bit ******/
; /* Wait till busy bit is clear */
while (count--)
; /* Dummy delay after PHY write */
}
/******************************************************************************
* sndsEndMacIntialize - Initialize MAC/BDMA registers
* Initialize the MAC and BDMA registers to make the Ethernet interface functional
*/
LOCAL void sndsEndMacInitialize
(
END_DEVICE *pDevice /* Device that has to be initialized */
)
{
BDMARXCON bdmaRxCon;
BDMATXCON bdmaTxCon;
MACCON macCon;
CAMCON camCon;
MACTXCON macTxCon;
MACRXCON macRxCon;
CAMEN camEn;
UINT32 count;
UCHAR *pAddr;
*(UINT32 *)SNDS_IOPMOD = 0xffff ;
/* init MACCON register */
*(UINT32 *)(&macCon) = 0;
if ((pDevice->autoNeg == 0) && (pDevice->duplexMode == 1))
macCon.macCon_reg.fullDup = 1;
*(UINT32 *)SNDS_MACCON = macCon.macCon_resetval;
/* init BDMA TXRX PTR registers */
*(UINT32 *)(SNDS_BDMARXPTR) = *(UINT32 *) (&gpReceiveFrameDescStart);
*(UINT32 *)(SNDS_BDMATXPTR) = *(UINT32 *) (&gpTransmitFrameDescStart); /* Initialize the register */
/* Copy our MAC address to the first location in address array */
pAddr = (UCHAR *)(&(pDevice->addrList[0]));
*(UINT32 *)pAddr = htonl (*(UINT32 *)pDevice->enetAddr);
pAddr += 6;
*(UINT16 *)pAddr = htons (*(UINT16 *)(pDevice->enetAddr+4));
/* Copy the address array into CAM registers */
for (count = 0; count < 32; count++)
*(((UINT32 *)SNDS_CAM_BASE) + count) = pDevice->addrList[count];
/* init CAMCON register */
*(UINT32 *) (&camCon) = 0;
if (END_FLAGS_GET(&pDevice->end) & IFF_PROMISC)
camCon.camCon_reg.stationAccept = 1;
camCon.camCon_reg.broadcastAccept = 1;
camCon.camCon_reg.cmpEnable = 1;
*(UINT32 *)SNDS_CAMCON = camCon.camCon_resetval;
/* init CAMEN register. Set bits for our MAC address and all
* multicast addresses
*/
*(UINT32 *)(&camEn) = 0;
for (count = 0; count <= pDevice->mcastAddrCount; count++)
camEn.camen_reg.camEnable |= (0x1<<count);
*(UINT32 *)SNDS_CAMEN = camEn.camen_resetval;
/* init BDMARXCON register */
*(UINT32 *) (&bdmaRxCon) = 0;
bdmaRxCon.rxCon_reg.burstSize = 31;
bdmaRxCon.rxCon_reg.stop_skipFrame = 1;
bdmaRxCon.rxCon_reg.memAddrsInc_Dec = 1;
bdmaRxCon.rxCon_reg.big_LittleEndian = 1;
bdmaRxCon.rxCon_reg.wordAlign = 2;
bdmaRxCon.rxCon_reg.reset = 0;
*(UINT32 *)SNDS_BDMARXCON = bdmaRxCon.rxCon_resetval;
/* init MACRXCON register */
*(UINT32 *)(&macRxCon) = 0;
macRxCon.macRxCon_reg.stripCRCVal = 1;
/*cjw*/
macRxCon.macRxCon_reg.passCtrlPacket = 1;
/*cjw*/
*(UINT32 *)SNDS_MACRXCON = macRxCon.macRxCon_resetval;
/* init BDMATXCON register */
*(UINT32 *)(&bdmaTxCon) = 0;
bdmaTxCon.txCon_reg.burstSize = 15;
bdmaTxCon.txCon_reg.stop_skipFrame = 1;
bdmaTxCon.txCon_reg.macTxStartLevel = 6; /* 110 */
*(UINT32 *)SNDS_BDMATXCON = bdmaTxCon.txCon_resetval;
/* init MACTXCON register */
*(UINT32 *)(&macTxCon) = 0;
if ((pDevice->flags & LS_POLLING) == 0) /* Not polling mode */
macTxCon.macTxCon_reg.enableCompletion = 1;
*(UINT32 *)SNDS_MACTXCON = macTxCon.macTxCon_resetval;
return;
}
/**********************************************************************************
* sndsEndFdInitialize - Initialize TX and RX FD lists
* Make a circular list of Rx and TX frame descriptors and buffers.
* Two global variables gpReceiveFrameDescStart and gpTransmitFrameDescStart
* stores the pointer to the start of the list. BDMA TX/RX PTR registers are
* also initialized with the start of the appropriate list.
*/
LOCAL STATUS sndsEndFdInitialize
(
END_DEVICE* pDrvCtrl /* device to be initialized */
)
{
int count;
RECEIVE_FRAME_DESC* pReceiveFrameDesc;
TRANSMIT_FRAME_DESC* pTransmitFrameDesc;
RECEIVE_FRAME_DESC* pPrevReceiveFrameDesc = 0;
TRANSMIT_FRAME_DESC* pPrevTransmitFrameDesc = 0;
char *pNewCluster;
for(count = 0; count < RX_FD_NUM; count++)
{
if ((pReceiveFrameDesc = (RECEIVE_FRAME_DESC *)calloc(sizeof(RECEIVE_FRAME_DESC), 1)) == NULL)
return ERROR;
(UINT32)pReceiveFrameDesc += NON_CACHE_REGION;
pNewCluster = netClusterGet (pDrvCtrl->end.pNetPool, pDrvCtrl->end.pNetPool->clTbl[0]);
if (pNewCluster == NULL)
{
return ERROR;
}
(UINT32)pNewCluster |= NON_CACHE_REGION;
(pReceiveFrameDesc->rxFrameData).frameDataPtr = (UINT32)pNewCluster;
(pReceiveFrameDesc->rxFrameData).o_bit = 1;
*(UINT32 *) (&pReceiveFrameDesc->rxStatusLength) = 0;
pReceiveFrameDesc->nextRxFrameDesc = NULL;
if (count == 0)
{
gpReceiveFrameDescStart = pReceiveFrameDesc;
*(UINT32 *)(SNDS_BDMARXPTR) = *(UINT32 *) (&pReceiveFrameDesc); /* Initialize the register */
}
else
{
pPrevReceiveFrameDesc->nextRxFrameDesc = pReceiveFrameDesc;
}
if (count == (RX_FD_NUM - 1))
{
pReceiveFrameDesc->nextRxFrameDesc = gpReceiveFrameDescStart;
}
pPrevReceiveFrameDesc = pReceiveFrameDesc;
}/* end of for loop*/
for(count = 0; count < TX_FD_NUM; count++)
{
if ((pTransmitFrameDesc = (TRANSMIT_FRAME_DESC *)calloc(sizeof(TRANSMIT_FRAME_DESC), 1)) == NULL)
return ERROR;
(UINT32)pTransmitFrameDesc += NON_CACHE_REGION;
(pTransmitFrameDesc->txFrameData).frameDataPtr = (UINT32)calloc (END_BUFSIZ, 1);
(pTransmitFrameDesc->txFrameData).frameDataPtr |= NON_CACHE_REGION;
(pTransmitFrameDesc->txFrameData).o_bit = 0;
*(UINT32 *) (&pTransmitFrameDesc->txControl) = 0;
pTransmitFrameDesc->nextTxFrameDesc = NULL;
if (count == 0)
{
gpTransmitFrameDescStart = pTransmitFrameDesc;
*(UINT32 *)(SNDS_BDMATXPTR) = *(UINT32 *) (&pTransmitFrameDesc); /* Initialize the register */
}
else
{
pPrevTransmitFrameDesc->nextTxFrameDesc = pTransmitFrameDesc;
}
if (count == (TX_FD_NUM - 1))
{
pTransmitFrameDesc->nextTxFrameDesc = gpTransmitFrameDescStart;
}
pPrevTransmitFrameDesc = pTransmitFrameDesc;
}/* end of for loop */
pDrvCtrl->fdInitialized = TRUE;
return OK;
}
/******************************************************************************
* sndsEndFdFree - Free the allocated TX and RX FD lists and buffers
* This function frees all the allocated TX and RX FDs and the associated
* buffers
*/
LOCAL void sndsEndFdFree
(
END_DEVICE* pDrvCtrl /* device to be freed */
)
{
RECEIVE_FRAME_DESC *pReceiveFrameDesc;
TRANSMIT_FRAME_DESC *pTransmitFrameDesc;
UINT32 count;
if (pDrvCtrl->fdInitialized == FALSE)
return;
for (count = 0; (count < TX_FD_NUM) && gpTransmitFrameDescStart; count++)
{
pTransmitFrameDesc = gpTransmitFrameDescStart;
if (gpTransmitFrameDescStart->txFrameData.frameDataPtr)
{
gpTransmitFrameDescStart->txFrameData.frameDataPtr &= ~NON_CACHE_REGION;
free ((void *)gpTransmitFrameDescStart->txFrameData.frameDataPtr);
}
gpTransmitFrameDescStart = gpTransmitFrameDescStart->nextTxFrameDesc;
(UINT32)pTransmitFrameDesc -= NON_CACHE_REGION;
free (pTransmitFrameDesc);
}
for (count = 0; (count < RX_FD_NUM) && gpReceiveFrameDescStart; count++)
{
pReceiveFrameDesc = gpReceiveFrameDescStart;
if (gpReceiveFrameDescStart->rxFrameData.frameDataPtr)
{
gpReceiveFrameDescStart->rxFrameData.frameDataPtr &= ~NON_CACHE_REGION;
netClFree (pDrvCtrl->end.pNetPool, (char *)gpReceiveFrameDescStart->rxFrameData.frameDataPtr);
}
gpReceiveFrameDescStart = gpReceiveFrameDescStart->nextRxFrameDesc;
(UINT32)pReceiveFrameDesc -= NON_CACHE_REGION;
free (pReceiveFrameDesc);
}
*(UINT32 *)(&gpReceiveFrameDescStart) = *(UINT32 *)(&gpTransmitFrameDescStart) = 0;
pDrvCtrl->fdInitialized = FALSE;
}
/******************************************************************************
* sndsEndBugFix - Bug Fix code for KS32C50100 Ethernet MAC
* This function checks for the receive bug in Ethernet MAC and corrects the pointer
* to frame data by skipping the received garbage data. Refer to KS32C50100 Application
* notes
*/
LOCAL void sndsEndBugFix (UINT16 *pFrameData)
{
UINT16 data1, data2;
UINT32 frameData;
UINT32 swapData;
gBugFixDone = FALSE;
pFrameData++; /* Point to start of data (MAC is configured with WordAlign = 2) */
/*
* Received data starts at a 2-byte boundary. So read as 2 16-bit short words
* to avoid data abort.
*/
data1 = *pFrameData++;
data2 = *pFrameData;
frameData = ((UINT32)data2 << 16) | data1;
swapData = ((frameData << 24) & 0xFF000000) | ((frameData << 8) & 0x00FF0000) |
((frameData >> 24) & 0x000000FF) | ((frameData >> 8) & 0x0000FF00);
if (swapData == gStatusLengthPrevious)
gBugFixDone = TRUE; /* To bump the offset while sending the frame up */
return;
}
#endif /* INCLUDE_SNDS_END */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -