📄 mxi.c
字号:
WRITE32( GMAC_CONTROL, 0x0 );
// Reset the FIFO
WRITE32( GMAC_AUX2, 0xe800 );
Delay(2);
WRITE32( GMAC_AUX2, 0x2800 );
//
// Clear all internal memory
//
// Set BP = 0x1FF
WRITE32( GMAC_ISR, 0x01FF0000 );
// Set TWP
WRITE32( GMAC_TXRING1, 0x0 );
// Set TRP
WRITE32( GMAC_TXRING2, 0x0 );
j = 0;
page = 0;
for( i=0; i<32768; i++ )
{
WRITE32( GMAC_TWD, 0 );
j += 4;
if( !(j & 0xFF) )
{
page += 0x10000;
page &= 0xfff0000;
WRITE32( GMAC_TXRING1, page );
}
}
}
//--------------------------------------------------------------------
// gmReset()
//
// Reset GMAC, initialize, and prepare to start
//--------------------------------------------------------------------
static void gmReset()
{
// Hard Reset
WRITE32( GMAC_RESET_ON, 0 );
Delay(4);
WRITE32( GMAC_RESET_OFF, 0 );
Delay(4);
// Soft Reset
WRITE32( GMAC_CONTROL, GM_RESET );
Delay(2);
WRITE32( GMAC_CONTROL, 0x0 );
// Reset the FIFO
WRITE32( GMAC_AUX2, 0xe800 );
Delay(2);
WRITE32( GMAC_AUX2, 0x2800 );
// Set auto-recover on Rx DMA
WRITE32( GMAC_AUX3, GM_AUTORCVR );
// Set RRP and RHBP
WRITE32( GMAC_RXRING2, 0x01FF0000 );
// Set RWP
WRITE32( GMAC_RXRING1, 0x00000000 );
// Set TLBP and TWP
WRITE32( GMAC_TXRING1, 0x0 );
// Set TRP
WRITE32( GMAC_TXRING2, 0x0 );
// Enable Autoneg, linktest, 16 bit mode, and TX Fifo count registers
WRITE32( GMAC_CONFIG, GM_LTE|GM_ANE|GM_PBW|GM_TXFIFOCNTEN );
// Clear interrupt mask and set BP
WRITE32( GMAC_ISR, 0x00000000 );
// Reset the FIFO
WRITE32( GMAC_AUX2, 0xe800 );
Delay(2);
WRITE32( GMAC_AUX2, 0x2800 );
// Enable interrupts (and set BP)
WRITE32( GMAC_ISR, 0x00000000|INTMASK );
// Tansmitter is not free until we start
pGMI->TxFree = 0;
// Reset any pending error
FatalError = 0;
}
//--------------------------------------------------------------------
// gmStart()
//
// Start GMAC Rx and Tx state machines
//--------------------------------------------------------------------
static void gmStart()
{
UINT32 control;
// Initialize states
TxState = STATE_IDLE;
RxState = STATE_IDLE;
pGMI->TxFree = 1;
// Setup Rx Filter Mode
HwPktSetRx( pGMI );
// Start receive
control = READ32( GMAC_CONTROL ) & 0x0000FF00;
control |= GM_SR;
// Turn on local loopback if hEther is NULL
if( !pGMI->hEther )
control |= GM_LB0;
WRITE32( GMAC_CONTROL, control );
}
//--------------------------------------------------------------------
// gmStop()
//
// Stop GMAC, abort current Rx and Tx
//--------------------------------------------------------------------
static void gmStop()
{
uint mask;
// Disable GP interrupt
mask = gmDisableIER( HW_IFLAG );
// Stop anyone from entering HwPktTxNext()
pGMI->TxFree = 0;
// Let tasks fall out of TX or RX
FatalError = 1;
TSK_sleep( 100 );
// Stop the device
WRITE32( GMAC_CONTROL, 0 );
TSK_sleep( 100 );
// Reset the part
gmReset();
// Flush the Tx Queue
while( PBMQ_count(&pGMI->PBMQ_tx) )
PBM_free( PBMQ_deq(&pGMI->PBMQ_tx) );
// Restore interrupts
gmEnableIER( mask );
}
//--------------------------------------------------------------------
// gmSendPacket()
//
// This function is called with TxState = STATE_IDLE
// It will start the copy the buffer to GMAC and start the send.
//
// If the packet is not properly aligned, it will align it
//--------------------------------------------------------------------
static void gmSendPacket( PBM_Handle hPkt )
{
unsigned int i;
UINT32 *pi;
UINT8 *buffer;
int length;
// This should never happen, but check for it anyway
if( FatalError || (READ32(GMAC_CONTROL) & (GM_ST0|GM_ST1)) )
{
FatalError = 1;
TxState = STATE_SEND;
PBM_free( hPkt );
return;
}
// Get a pointer to where the data starts and its length
buffer = PBM_getDataBuffer(hPkt) + PBM_getDataOffset(hPkt);
length = PBM_getValidLen(hPkt);
// This should never happen either, but check for it anyway
if( (UINT32)buffer & 0x3 )
{
TxPanic++;
mmCopy( pktPanicBuf, buffer, length );
pi = (UINT32 *)pktPanicBuf;
}
else
pi = (UINT32 *)buffer;
// Set the frame size
i = READ32(GMAC_AUX2)&0xffff | (length << 16);
WRITE32( GMAC_AUX2, i );
// Send out all the data
length = (length+3)>>2;
while( length-- )
WRITE32( GMAC_WRTXFIFOD, *pi++ );
// Send the frame
i = READ32(GMAC_CONTROL)|GM_ST1;
WRITE32( GMAC_CONTROL, i );
TxState = STATE_SEND;
// We can now free the packet
PBM_free( hPkt );
}
//--------------------------------------------------------------------
// gmRxPacket()
//
// This function is called with RxState = STATE_DMA
// It will copy packet data from GMAC to the receive buffer.
//
// If there is a problem, the routine returns sets the
// RxState to IDLE and returns 0, else it returns 1.
//--------------------------------------------------------------------
static int gmRxPacket()
{
register uint data1, data2, data3, data4;
PBM_Handle hPkt;
unsigned int status;
uint *pibuf;
int length,tlen;
if( FatalError )
goto RxExit;
// Rx a packet
if( READ32( GMAC_AUX1 ) & GM_DREQB )
{
FatalError=1;
goto RxExit;
}
// Read the first 16 bytes
data1 = READ32( GMAC_RRD );
data2 = READ32( GMAC_RRD );
data3 = READ32( GMAC_RRD );
data4 = READ32( GMAC_RRD );
// Decode length, nextpage, and status
length = (data1 >> 12) & 0x0FFF;
status = (data1 >> 24) & 0x0FF;
// Try to recover on startup error
if( !length || length > 1518 )
{
FatalError=1;
goto RxExit;
}
if( !(status & 0x80) )
{
RxGood++;
// Try and get a buffer. If we can't, toss the packet.
// Max packet size is unusual: ((((1518-12)-1)/16)+1)*16+12
// and then we add on the prepad (this is because the
// Macronix transfers data in 16 byte bursts and that the
// first burst has only 12 bytes of data). The above
// comes out to 1532, plus the prepad.
hPkt = PBM_alloc( 1532 + PKT_PREPAD );
}
else
{
RxBad++;
hPkt = 0;
}
// Pull the packet out - good or bad
tlen = length - 12;
if( !hPkt )
{
// Get the rest of the packet
while( tlen > 0 )
{
data2 = 0;
while( READ32( GMAC_AUX1 ) & GM_DREQB )
if( ++data2 == 1000 )
{
FatalError=1;
goto RxExit;
}
data1 = READ32( GMAC_RRD );
data2 = READ32( GMAC_RRD );
data3 = READ32( GMAC_RRD );
data4 = READ32( GMAC_RRD );
tlen -= 16;
}
}
else
{
// Fill in the packet size, offset and Ether handle
PBM_setValidLen( hPkt, length );
PBM_setDataOffset( hPkt, PKT_PREPAD );
PBM_setIFRx( hPkt, pGMI->hEther );
// Get a pointer to our buffer - add on PREPAD
pibuf = (uint *)(PBM_getDataBuffer(hPkt)+PKT_PREPAD);
// Copy the data we already have
*pibuf++ = data2;
*pibuf++ = data3;
*pibuf++ = data4;
// Get the rest of the packet
while( tlen > 0 )
{
data1 = 0;
while( READ32( GMAC_AUX1 ) & GM_DREQB )
if( ++data1 == 1000 )
{
PBM_free( hPkt );
FatalError=1;
goto RxExit;
}
data1 = READ32( GMAC_RRD );
data2 = READ32( GMAC_RRD );
data3 = READ32( GMAC_RRD );
data4 = READ32( GMAC_RRD );
*pibuf++ = data1;
*pibuf++ = data2;
*pibuf++ = data3;
*pibuf++ = data4;
tlen -= 16;
}
PBMQ_enq( &PBMQ_rx, hPkt );
RxState = STATE_IDLE;
return(1);
}
RxExit:
RxState = STATE_IDLE;
return(0);
}
//--------------------------------------------------------------------
// gmIsr()
//
// General purpose ISR function. Here we will signal the
// scheduler that a packet is available on GMAC, or if the only
// message it a TX completion, we'll start the next send.
//--------------------------------------------------------------------
static void gmIsr()
{
uint flags,NeedEvent = 0;
uint data1,data2;
PDINFO *pi;
// Normally we would have to associate a PDINFO structure
// with the device that fired this interrupt. Here though,
// we only support one device, so we just set it to our global.
pi = pGMI;
do
{
// Read the interrupt flags and ACK
flags = READ32( GMAC_ISR ) & 0xFF00;
// Check for new Rx packet
while( !FatalError && RxState == STATE_IDLE )
{
data1 = READ32(GMAC_RXRING1) >> 16;
data2 = READ32(GMAC_RXRING2) & 0xFFFF;
if( data1 == data2 )
break;
RxState = STATE_DMA;
NeedEvent |= gmRxPacket();
}
// Check for Tx Complete
if( TxState==STATE_SEND && !(READ32(GMAC_CONTROL)&(GM_ST0|GM_ST1)) )
{
TxState = STATE_IDLE;
if( PBMQ_count(&pi->PBMQ_tx) )
HwPktTxNext( pi );
else
pi->TxFree = 1;
}
WRITE32( GMAC_ISR, ( 0x00000000 | flags | INTMASK ) );
} while( flags );
// Notify we have a packet
if( NeedEvent )
{
FlashActiveLED = 1;
STKEVENT_signal( pi->hEvent, STKEVENT_ETHERNET, 1 );
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -