📄 c6455.c
字号:
// Enable Section
if( pi->Filter >= ETH_PKTFLT_DIRECT )
EMAC_REGS->RXUNICASTSET = 1;
if( pi->Filter >= ETH_PKTFLT_BROADCAST )
CSL_FINST( EMAC_REGS->RXMBPENABLE, EMAC_RXMBPENABLE_RXBROADEN, ENABLE );
if( pi->Filter >= ETH_PKTFLT_MULTICAST )
CSL_FINST( EMAC_REGS->RXMBPENABLE, EMAC_RXMBPENABLE_RXMULTEN, ENABLE );
if( pi->Filter >= ETH_PKTFLT_ALLMULTICAST )
{
EMAC_REGS->MACHASH1 = 0xffffffff;
EMAC_REGS->MACHASH1 = 0xffffffff;
}
if( pi->Filter == ETH_PKTFLT_ALL )
CSL_FINST( EMAC_REGS->RXMBPENABLE, EMAC_RXMBPENABLE_RXCAFEN, ENABLE );
}
}
//--------------------------------------------------------------------
// HwPktTxNext()
//
// Transmit Next Packet on Tx Queue
//--------------------------------------------------------------------
void HwPktTxNext( PDINFO *pi )
{
register EMAC_Desc *pDescThis;
register UINT8 *buffer;
register uint length;
PBM_Handle hPkt;
uint intmask;
// Make sure we have a packet to send
if( !(hPkt = PBMQ_deq(&pi->PBMQ_tx)) )
{
pi->TxFree = 1;
return;
}
buffer = PBM_getDataBuffer(hPkt) + PBM_getDataOffset(hPkt);
length = PBM_getValidLen(hPkt);
// Clean the cache for external addesses
if( (UINT32)buffer & EXTMEM )
OEMCacheClean( (void *)buffer, length );
// Disable our device interrupt
intmask = C64_disableIER( IntFlag );
// This can't happen, but check anyway
if( chTx.DescCount == chTx.DescMax )
{
PBM_free( hPkt );
goto send_exit;
}
// Assign the pointer to "this" desc
pDescThis = chTx.pDescWrite;
// Move the write pointer and bump count
if( pDescThis == chTx.pDescLast )
chTx.pDescWrite = chTx.pDescFirst;
else
chTx.pDescWrite++;
chTx.DescCount++;
// Fill out the descriptor
pDescThis->pNext = 0;
pDescThis->pBuffer = buffer;
pDescThis->BufOffLen = length;
pDescThis->PktFlgLen = EMAC_DSC_FLAG_SOP | EMAC_DSC_FLAG_EOP |
length | EMAC_DSC_FLAG_OWNER;
// Enqueue this packet onto the desc queue
PBMQ_enq( &chTx.DescQueue, hPkt );
// Synch the cache
if( (UINT32)buffer & EXTMEM )
OEMCacheCleanSynch();
// Start it sending
if( chTx.DescCount > 1 )
{
// Transmitter is already running.
// Make the previous buffer point to us
if( pDescThis == chTx.pDescFirst )
chTx.pDescLast->pNext = pDescThis;
else
(pDescThis-1)->pNext = pDescThis;
}
else
{
// Transmitter is not running, start it up
EMAC_REGS->TX0HDP = (Uint32)pDescThis ;
}
send_exit:
C64_enableIER( intmask );
}
//--------------------------------------------------------------------
// _HwPktPoll()
//
// Poll routine - CALLED OUTSIDE OF KERNEL MODE
//
// This function is called at least every 100ms, faster in a
// polling environment. The fTimerTick flag is set only when
// called on a 100ms event.
//--------------------------------------------------------------------
void _HwPktPoll( PDINFO *pi, uint fTimerTick )
{
uint intmask;
uint mdioStatus,phy,linkStatus;
(void)pi;
if( fTimerTick && hMDIO )
{
LED_TOGGLE( USER_LED2 );
if( FlashActiveLED )
{
FlashActiveLED = 0;
LED_TOGGLE( USER_LED3 );
}
llEnter();
intmask = C64_disableIER( IntFlag );
// Signal the MDIO
mdioStatus = MDIO_timerTick( hMDIO );
// Track new or lost link
if( mdioStatus == MDIO_EVENT_LINKDOWN ||
mdioStatus == MDIO_EVENT_LINKUP )
{
MDIO_getStatus( hMDIO, &phy, &linkStatus );
// On a new link, set the EMAC duplex
if( mdioStatus == MDIO_EVENT_LINKUP )
{
if( linkStatus == MDIO_LINKSTATUS_FD10 ||
linkStatus == MDIO_LINKSTATUS_FD100 ||
linkStatus == MDIO_LINKSTATUS_FD1000 )
{
CSL_FINST( EMAC_REGS->MACCONTROL, EMAC_MACCONTROL_FULLDUPLEX, ENABLE );
if ( macsel == CSL_DEV_DEVSTAT_MACSEL_RMII )
CSL_FINST(EMAC_REGS->MACCONTROL, EMAC_MACCONTROL_RMIIDUPLEXMODE, FULLDUPLEX );
}
else
{
CSL_FINST( EMAC_REGS->MACCONTROL, EMAC_MACCONTROL_FULLDUPLEX, DISABLE );
if ( macsel == CSL_DEV_DEVSTAT_MACSEL_RMII )
CSL_FINST(EMAC_REGS->MACCONTROL, EMAC_MACCONTROL_RMIIDUPLEXMODE, HALFDUPLEX );
}
if( linkStatus == MDIO_LINKSTATUS_FD1000 )
CSL_FINST(EMAC_REGS->MACCONTROL, EMAC_MACCONTROL_GIG, ENABLE );
if(( (linkStatus == MDIO_LINKSTATUS_HD10 ) ||
( linkStatus == MDIO_LINKSTATUS_FD10 )) &&
( macsel == CSL_DEV_DEVSTAT_MACSEL_RMII ))
CSL_FINST(EMAC_REGS->MACCONTROL, EMAC_MACCONTROL_RMIISPEED, 2_5MHZ );
if(( (linkStatus == MDIO_LINKSTATUS_HD100 ) ||
( linkStatus == MDIO_LINKSTATUS_FD100 )) &&
( macsel == CSL_DEV_DEVSTAT_MACSEL_RMII ))
CSL_FINST(EMAC_REGS->MACCONTROL, EMAC_MACCONTROL_RMIISPEED, 25MHZ );
//The following 2 settings apply only to PG 2.0
if ( macsel == CSL_DEV_DEVSTAT_MACSEL_RMII ) // Take RMII out of reset
CSL_FINST(DEV_REGS->EMACCFG, DEV_EMACCFG_RMIIRST, RELEASE );
if ( macsel == CSL_DEV_DEVSTAT_MACSEL_RGMII ) // Put RGMII in forced link mode
CSL_FINST(EMAC_REGS->MACCONTROL, EMAC_MACCONTROL_RGMIIEN, DISABLE );
// Now that we have a link, send any queued packets
while( !pi->TxFree )
HwPktTxNext( pi );
}
// Tell application
C6455EMAC_linkStatus( phy, linkStatus );
}
// Re-fill Rx buffer queue if needed
if( chRx.DescCount != chRx.DescMax )
emacEnqueueRx( 1 );
C64_enableIER( intmask );
llExit();
}
}
//--------------------------------------------------------------------
// HwInt()
//
// EMAC Hardware Interrupt
//--------------------------------------------------------------------
void HwInt(void)
{
Uint32 intflags,Desc;
uint tmp;
// Disable EMAC/MDIO interrupts in wrapper
CSL_FINST( ECTL_REGS->EWCTL, ECTL_EWCTL_INTEN, DISABLE );
// Read the interrupt cause
intflags = EMAC_REGS->MACINVECTOR ;
// Look for fatal errors first
if( intflags & CSL_FMK( EMAC_MACINVECTOR_HOSTPEND, 1 ) )
{
// A fatal error can only be caused by a software
// logic error. We'll read the fatal error code
// and exit with the EMAC interrupt still disabled.
// This will halt all network functionality. The
// application programmer can manually check the
// status of C6455EMAC_FatalError if the network
// stops working.
C6455EMAC_FatalError = EMAC_REGS->MACSTATUS ;
return;
}
// Look for statistics interrupt
if( intflags & CSL_FMK( EMAC_MACINVECTOR_STATPEND, 1 ) )
{
volatile Uint32 *pRegAddr;
Uint32 statval;
pRegAddr = &EMAC_REGS->RXGOODFRAMES ;
/*
// There are "EMAC_NUMSTATS" statistics registers
// Note that when MIIEN is set in MACCONTROL, these registers
// are "write to decrement".
*/
for( tmp=0; tmp<EMAC_NUMSTATS; tmp++ )
{
statval = *pRegAddr;
*pRegAddr++ = statval;
}
}
// Look for TX interrupt (channel 0)
if( intflags & CSL_FMK( EMAC_MACINVECTOR_TXPEND, 1<<0 ) )
{
Desc = EMAC_REGS->TX0CP;
EMAC_REGS->TX0CP = Desc ;
emacDequeueTx( (EMAC_Desc *)Desc );
}
// Look for RX interrupt (channel 0)
if( intflags & CSL_FMK( EMAC_MACINVECTOR_RXPEND, 1<<0 ) )
{
Desc = EMAC_REGS->RX0CP ;
EMAC_REGS->RX0CP = Desc ;
emacDequeueRx( (EMAC_Desc *)Desc );
}
// Enable EMAC/MDIO interrupts in wrapper
CSL_FINST( ECTL_REGS->EWCTL, ECTL_EWCTL_INTEN, ENABLE );
}
/*--------------------------------------------------------------------*\
* emacInit()
*
* Initialize EMAC. Return "1" if all is OK
\*--------------------------------------------------------------------*/
static uint emacInit()
{
Uint32 tmpval;
int i;
volatile Uint32 *pRegAddr;
uint utemp1;
EMAC_Desc *pDesc;
PBM_Handle hPkt;
/*
// Initialize the EMAC and MDIO devices
*/
ECTL_REGS->EWCTL = CSL_FMKT(ECTL_EWCTL_INTEN, DISABLE );
/* Reset EMAC */
EMAC_REGS->SOFTRESET = 0x1;
while (EMAC_REGS->SOFTRESET != 0x0);
/* Program the interrupt pacer */
ECTL_REGS->EWINTTCNT = 4000;
/* Start the MII Configuration */
hMDIO = MDIO_open( MDIO_MODEFLG_AUTONEG );
/*
// Setup the EMAC
*/
/* Reset MAC Control */
EMAC_REGS->MACCONTROL = 0 ;
/* Must manually init HDPs to NULL */
pRegAddr = &EMAC_REGS->TX0HDP;
for( i=0; i<8; i++ )
*pRegAddr++ = 0;
pRegAddr = &EMAC_REGS->RX0HDP;
for( i=0; i<8; i++ )
*pRegAddr++ = 0;
/*
// While GMIIEN is clear in MACCONTROL, we can write directly to
// the statistics registers (there are "EMAC_NUMSTATS" of them).
*/
pRegAddr = &EMAC_REGS->RXGOODFRAMES;
for( i=0; i<EMAC_NUMSTATS; i++ )
*pRegAddr++ = 0;
/* Initialize the RAM locations */
for (i = 0; i < 32; i++)
{
EMAC_REGS->MACINDEX = i;
EMAC_REGS->MACADDRHI = 0;
EMAC_REGS->MACADDRLO = 0;
}
/* Setup device MAC address */
EMAC_REGS->MACINDEX = 0x0;
tmpval = 0;
for( i=3; i>=0; i-- )
tmpval = (tmpval<<8) | *(pPDI->bMacAddr+i);
EMAC_REGS->MACADDRHI = tmpval;
tmpval = *(pPDI->bMacAddr+5);
EMAC_REGS->MACADDRLO = CSL_FMKT( EMAC_MACADDRLO_VALID, VALID ) |
CSL_FMKT( EMAC_MACADDRLO_MATCHFILT, MATCH ) |
CSL_FMK( EMAC_MACADDRLO_CHANNEL, 0 ) |
(tmpval<<8) |
*(pPDI->bMacAddr+4) ;
/* For us buffer offset will always be zero */
EMAC_REGS->RXBUFFEROFFSET = 0;
/* Reset RX (M)ulticast (B)roadcast (P)romiscuous Enable register */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -