📄 at91emacend.c
字号:
*
* This routine adds a multicast address to whatever the driver
* is already listening for. It then resets the address filter.
*
* RETURNS: OK or ERROR.
*/
LOCAL STATUS at91EndMCastAdd
(
at91end_device *pDrvCtrl, /* device pointer */
char* pAddress /* new address to add */
)
{
int error;
if ( (error = etherMultiAdd (&pDrvCtrl->end.multiList,
pAddress)) == ENETRESET )
at91EndConfig (pDrvCtrl);
return (OK);
}
/*****************************************************************************
*
* at91EndMCastDel - delete a multicast address for the device
*
* This routine removes a multicast address from whatever the driver
* is listening for. It then resets the address filter.
*
* RETURNS: OK or ERROR.
*/
LOCAL STATUS at91EndMCastDel
(
at91end_device* pDrvCtrl, /* device pointer */
char* pAddress /* address to be deleted */
)
{
int error;
if ((error = etherMultiDel (&pDrvCtrl->end.multiList,
(char *)pAddress)) == ENETRESET)
at91EndConfig (pDrvCtrl);
return (OK);
}
/*****************************************************************************
*
* at91EndMCastGet - get the multicast address list for the device
*
* This routine gets the multicast list of whatever the driver
* is already listening for.
*
* RETURNS: OK or ERROR.
*/
LOCAL STATUS at91EndMCastGet
(
at91end_device* pDrvCtrl, /* device pointer */
MULTI_TABLE* pTable /* address table to be filled in */
)
{
int error;
error = etherMultiGet (&pDrvCtrl->end.multiList, pTable);
return (error);
}
/*******************************************************************************
*
* at91EndStop - stop the device
*
* This function calls BSP functions to disconnect interrupts and stop
* the device from operating in interrupt mode.
*
* RETURNS: OK or ERROR.
*/
LOCAL STATUS at91EndStop
(
at91end_device *pDrvCtrl /* device to be stopped */
)
{
EMAC_S* pemac = (EMAC_S*)EMAC_BASE_ADDR;
ENDLOGMSG ((" Enter at91EndStop routine...\n", 1, 2, 3, 4, 5, 6));
/*
* disable rx and tx, and int
*/
pemac ->EMAC_CTL = EMAC_CTL_CSR;
pemac ->EMAC_IDR = 0xFFFFFFFF;
intDisable ( pDrvCtrl->level );
END_FLAGS_CLR (&pDrvCtrl->end, IFF_UP | IFF_RUNNING);
ENDLOGMSG ((" Leave at91EndStop routine...\n", 1, 2, 3, 4, 5, 6));
return (OK);
}
/******************************************************************************
*
* at91EndUnload - 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 void FreeEndMemory( at91end_device* pDrvCtrl )
{
if ( pDrvCtrl->end.pNetPool )
{
netPoolDelete (pDrvCtrl->end.pNetPool);
free (pDrvCtrl->end.pNetPool);
pDrvCtrl->end.pNetPool = (NET_POOL_ID)0;
}
if (at91endClDescTbl[0].memArea)
{
cacheDmaFree (at91endClDescTbl[0].memArea);
at91endClDescTbl[0].memArea = (char *)0;
}
if( pDrvCtrl ->TranFifoBuf )
{
cacheDmaFree( pDrvCtrl ->TranFifoBuf );
pDrvCtrl ->RecvBufDesc = NULL;
pDrvCtrl ->TranFifoBuf = NULL;
pDrvCtrl ->RecvFifoBuf = NULL;
bzero( (void*)&(pDrvCtrl->pTxBufStart[0]), sizeof( AT91_END_TRAN_FD )*TX_FD_NUM );
}
if (at91endMclConfig.memArea)
{
free (at91endMclConfig.memArea);
at91endMclConfig.memArea = (char *)0;
}
if (pDrvCtrl)
{
free (pDrvCtrl);
(at91end_device*)pDrvCtrl = 0;
}
}
LOCAL STATUS at91EndUnload
(
at91end_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 */
at91EndStop(pDrvCtrl); /*before unloading the device will stop functioning*/
at91EmacReset(pDrvCtrl); /*then it will reset the registers in order to clear any pending interrupts */
at91EndFdFree(pDrvCtrl);
FreeEndMemory( pDrvCtrl );
return (OK);
}
/******************************************************************************
* at91EmacReset - Reset the device
* This function resets the driver after initializing from at91EndLoad
*/
LOCAL void at91EmacReset
(
at91end_device* pDrvCtrl /* device to be reset */
)
{
UINT32 dummy, i;
UINT32 tmp = 0xFFFFFFFF;
EMAC_S *pemac = (EMAC_S*)EMAC_BASE_ADDR;
if(pDrvCtrl->unit != 0)
return;
/*
* disable interrupt first
*/
pemac ->EMAC_IDR = 0xFFFFFFFF;
/*
* disable recive and transmit
*/
pemac ->EMAC_CTL = EMAC_CTL_CSR;
/*
* config EMAC state, MAX HCLK = (60-100)/16 < 8M (for LXT971)
*/
pemac ->EMAC_CFG = EMAC_CFG_CLK_HCLK_16 | EMAC_CFG_RMII /*bao | EMAC_CFG_SPD/*| EMAC_CFG_MTI | EMAC_CFG_UNI*/;
/*
* clear transmit and receive status bit
*/
pemac ->EMAC_TSR = tmp;
pemac ->EMAC_RSR = tmp;
/*
* clear interrupt status REG
*/
dummy = pemac ->EMAC_ISR;
/*
* set all statistic regoster by read it
*/
for( i = 0; i< sizeof(ETH_STAT_S)/sizeof(AT91_REG); i++ )
{
dummy = ( (AT91_REG*)( &(pemac ->ESTAT ) ) )[i];
}
/*
* after reset, we need to set address for mac
*/
/*
*
*/
return;
}
/******************************************************************************
* at91EndPhyRead - Read PHY device
* This function is used to read a byte from the PHY device
*/
LOCAL UINT32 at91EndPhyRead
(
UINT32 phyRegAddr, /* Address of PHY register to be read */
UINT32 phyAddr /* Address of the PHY chip (usually 0 for single PHY) */
)
{
EMAC_S* regs = (EMAC_S*)EMAC_BASE_ADDR;
UINT32 dummy;
regs->EMAC_MAN = EMAC_PHY_HIGH | EMAC_PHY_CODE | EMAC_PHY_RW_R
| (phyRegAddr << 18);
/* Wait until IDLE bit in Network Status register is cleared */
/* TODO: Enforce some maximum loop-count?*/
dummy = 0;
while ( !(regs->EMAC_SR & EMAC_SR_IDLE)&& (dummy++ < 10000) ) ;
return ( regs->EMAC_MAN & 0x0000ffff );
}
/******************************************************************************
* at91EndPhyWrite - Wrire into PHY device
* This function is used to write a byte to the PHY device
*/
LOCAL void at91EndPhyWrite
(
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 */
)
{
EMAC_S* regs = (EMAC_S*)EMAC_BASE_ADDR;
UINT32 dummy;
regs->EMAC_MAN = (EMAC_PHY_HIGH | EMAC_PHY_CODE | EMAC_PHY_RW_R
| (phyRegAddr << 18)) + (phyData & 0xffff);
/* Wait until IDLE bit in Network Status register is cleared */
/* TODO: Enforce some maximum loop-count?*/
dummy = 0;
while (!(regs->EMAC_SR & EMAC_SR_IDLE)&(dummy++ < 10000) ) ;
}
/******************************************************************************
* at91EndMacIntialize - Initialize MAC/BDMA registers
* Initialize the MAC and BDMA registers to make the Ethernet interface functional
*/
LOCAL void at91EndMacInitialize
(
at91end_device *pDevice /* Device that has to be initialized */
)
{
EMAC_S* pemac = (EMAC_S*)EMAC_BASE_ADDR;
/*
* set the first address as the IF mac address
*/
FormatETHSpecialAddrWord( &(pDevice ->addrListHigh[0]),
&(pDevice ->addrListLow[0]), (BYTE*)pDevice->enetAddr );
/*
* write the special address to chip
*/
pemac ->EMAC_SA1L = pDevice ->addrListLow[0];
pemac ->EMAC_SA1H = pDevice ->addrListHigh[0];
if( pDevice ->mcastAddrCount > 0 )
{
pemac ->EMAC_SA2L = pDevice ->addrListLow[1];
pemac ->EMAC_SA2H = pDevice ->addrListHigh[1];
}
else
{
pemac ->EMAC_SA2L = 0;
pemac ->EMAC_SA2H = 0;
}
if( pDevice ->mcastAddrCount > 1 )
{
pemac ->EMAC_SA3L = pDevice ->addrListLow[2];
pemac ->EMAC_SA3H = pDevice ->addrListHigh[2];
}
else
{
pemac ->EMAC_SA3L = 0;
pemac ->EMAC_SA3H = 0;
}
if( pDevice ->mcastAddrCount > 2 )
{
pemac ->EMAC_SA4L = pDevice ->addrListLow[3];
pemac ->EMAC_SA4H = pDevice ->addrListHigh[3];
}
else
{
pemac ->EMAC_SA4L = 0;
pemac ->EMAC_SA4H = 0;
}
/*
* what use for hash reg?, write all one first
*/
pemac ->EMAC_HSH = 0xFFFFFFFF;
pemac ->EMAC_HSL = 0xFFFFFFFF;
/*
* setup receive buffer address
*/
pemac ->EMAC_RBQP = (AT91_REG)(pDevice ->RecvBufDesc);
/*
* write configuration register again, do not allow mulitcast and unicast
*/
pemac ->EMAC_CFG = EMAC_CFG_CLK_HCLK_16 | EMAC_CFG_RMII /*bao | EMAC_CFG_SPD/*| EMAC_CFG_MTI | EMAC_CFG_UNI*/;
return;
}
/**********************************************************************************
* at91EndFdInitialize - 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 at91EndFdInitialize
(
at91end_device* pDrvCtrl /* device to be initialized */
)
{
int count;
char *pNewCluster;
if( pDrvCtrl ->RecvFifoBuf == NULL )
{
ENDLOGMSG( ( "END: at91EndFdInitialize find RX fifo have no buffer, something gong wrong ! ", 1,2,3,4,5,6 ));
at91EndFdFree( pDrvCtrl );
return (ERROR);
}
for( count = 0; count < RX_FD_NUM; count++ )
{
pNewCluster = pDrvCtrl ->RecvFifoBuf + count*(pDrvCtrl ->TranPkgSize);
/* netClusterGet ( pDrvCtrl->end.pNetPool, pDrvCtrl->pClPoolId );*/
/*
if ( pNewCluster == NULL )
{
ENDLOGMSG(( "END:Get clust failure in routine at91EndFdInitialize\n", 1,2,3,4,5, 6 ));
at91EndFdFree( pDrvCtrl );
return ERROR;
}
*/
pDrvCtrl ->clPointBuf[ count ] = pNewCluster;
if( ((UINT32)pNewCluster)&0x3 != 0 )
{
ENDLOGMSG(( "END:receive buffer address not at wordalign in routine at91EndFdInitialize. point: %x\n", (UINT32)pNewCluster ,2,3,4,5, 6 ))
}
/*
* just make the point align to word
*/
(pDrvCtrl ->RecvBufDesc)[count].bufaddr = ( ( ((UINT32)pNewCluster)+3 )&(0xFFFFFFFC) );
(pDrvCtrl ->RecvBufDesc)[count].recvstatus = 0;
}/* end of for loop*/
(pDrvCtrl ->RecvBufDesc)[RX_FD_NUM - 1].bufaddr |= EMAC_RECV_DESC_WRAP;
pDrvCtrl ->rxBufPtr = 0;
/*
* initialize tx desc query
*/
if( (pDrvCtrl ->TranFifoBuf) == NULL )
{
ENDLOGMSG( ( "END: at91EndFdInitialize find TX fifo have no buffer, something gong wrong ! ", 1,2,3,4,5,6 ));
at91EndFdFree( pDrvCtrl );
return (ERROR);
}
for( count = 0; count < TX_FD_NUM; count ++ )
{
(pDrvCtrl ->pTxBufStart)[ count ].bufaddr =
pDrvCtrl ->TranFifoBuf + count*(pDrvCtrl ->TranPkgSize);
(pDrvCtrl ->pTxBufStart)[ count ].owner = 0; /*init owner to software */
}
pDrvCtrl ->TxTailPtr = pDrvCtrl ->TxPtr = 0;
pDrvCtrl ->TXFifoStat = TXFIFOEMPTY;
pDrvCtrl->fdInitialized = TRUE;
return OK;
}
/******************************************************************************
* at91EndFdFree - 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 at91EndFdFree
(
at91end_device* pDrvCtrl /* device to be freed */
)
{
UINT32 count;
char* tmpcl;
/*
if (pDrvCtrl->fdInitialized == FALSE)
return;
*/
/*
if( pDrvCtrl ->RecvBufDesc )
{
for ( count = 0; count < RX_FD_NUM; count++ )
{
tmpcl = pDrvCtrl ->clPointBuf[ count ];
if( tmpcl )
{
netClFree (pDrvCtrl->end.pNetPool, tmpcl );
}
(pDrvCtrl ->RecvBufDesc)[count].bufaddr = 0;
pDrvCtrl ->clPointBuf[ count ] = NULL;
}
}
*/
pDrvCtrl->fdInitialized = FALSE;
}
#endif /* INCLUDE_SNDS_END */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -