📄 mxf.c
字号:
// Let tasks fall out of TX or RX
FatalError = 1;
TSK_sleep( 100 );
// Stop the device
WRITE32( GMAC_CONTROL, 0 );
TSK_sleep( 100 );
// Clear our interrupts
EDMA_intClear( EdmaTxEvent );
EDMA_intClear( EdmaRxEvent );
// Cleanup TX and RX memory
if( TxState==STATE_DMA )
{
// Free the packet
if( hDMATxPkt )
PBM_free( hDMATxPkt );
hDMATxPkt = 0;
TxState = STATE_IDLE;
}
if( RxState==STATE_DMA )
{
// Free the packet
if( hDMARxPkt )
PBM_free( hDMARxPkt );
hDMARxPkt = 0;
RxState = STATE_IDLE;
}
// 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 of the send buffer to the device.
//
// If the packet is not properly aligned, it will align it
//--------------------------------------------------------------------
static void gmSendPacket( PBM_Handle hPkt )
{
unsigned int i;
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 );
buffer = pktPanicBuf;
}
// Clean the cache for external addesses
if( (UINT32)buffer & 0x80000000 )
OEMCacheClean( (void *)buffer, length );
// Set the frame size
i = READ32(GMAC_AUX2)&0xffff | (length << 16);
WRITE32( GMAC_AUX2, i );
// Setup source and count
EDMA_RSETH(hEDMA_tx,SRC,(UINT32)buffer);
EDMA_RSETH(hEDMA_tx,CNT,(length+3)>>2);
// Synch the cache
if( (UINT32)buffer & 0x80000000 )
OEMCacheCleanSynch();
// Read control one more time to add CE space access
i = READ32(GMAC_CONTROL);
// Start the DMA
hDMATxPkt = hPkt;
TxState = STATE_DMA;
EDMA_setChannel( hEDMA_tx );
}
//--------------------------------------------------------------------
// gmRxPacket()
//
// This function is called with RxState = STATE_DMA
// It will start the copy 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;
}
// Clear any RX framesync event
EDMA_clearChannel(hEDMA_rxControl);
#if EDMA_FS_TP1
// Reset the clock for TP1 interrupt
*(unsigned int*)_TIMER_CTL1_ADDR = 0x0; // Disable clock
*(unsigned int*)_TIMER_CNT1_ADDR = 0x1; // Set count to one
*(unsigned int*)_TIMER_CTL1_ADDR = 0x480; // Start clock (inverted input)
#endif
// Manually 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);
// Clean the cache
if( (UINT32)pibuf & 0x80000000 )
OEMCacheClean( (void *)pibuf, length );
// Convert remaining length to 16 byte frame count
tlen = (tlen+15)>>4;
if( !tlen )
{
// Runt packet - free the packet
PBM_free( hPkt );
}
else
{
// DMA keeps frame 'count-1'
tlen--;
// Setup RX EDMA
EDMA_RSETH(hEDMA_rx,OPT,EdmaOptRx);
EDMA_RSETH(hEDMA_rx,SRC,GMAC_RRD);
EDMA_RSETH(hEDMA_rx,CNT,(tlen<<16) | 4);
EDMA_RSETH(hEDMA_rx,DST,((UINT32)pibuf) + 12);
EDMA_RSETH(hEDMA_rx,IDX,0);
EDMA_RSETH(hEDMA_rx,RLD,(4 << 16) | EdmaRldAddr);
// Remember the first 24 bytes and what our
// packet pointers are.
DMAData1 = data2;
DMAData2 = data3;
DMAData3 = data4;
hDMARxPkt = hPkt;
// Synch the cache
if( (UINT32)pibuf & 0x80000000 )
OEMCacheCleanSynch();
// Enable external FrameSync signals
EDMA_enableChannel(hEDMA_rxControl);
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;
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;
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 );
}
//--------------------------------------------------------------------
// gmIsrEDMATx()
//
// TX Completion Event
//--------------------------------------------------------------------
static void gmIsrEDMATx( int arg )
{
UINT32 data;
uint mask;
(void)arg;
// Disable GP interrupts
mask = gmDisableIER( HW_IFLAG );
// If state is DMA, send the packet we just DMA'd
if( TxState==STATE_DMA )
{
// Free the packet
if( hDMATxPkt )
PBM_free( hDMATxPkt );
hDMATxPkt = 0;
// Send the frame
data = READ32(GMAC_CONTROL)|GM_ST1;
WRITE32( GMAC_CONTROL, data );
TxState = STATE_SEND;
}
// Ack any pending device interrupt
if( READ32( GMAC_ISR ) & 0xFF00 )
{
ICR = HW_IFLAG;
gmIsr();
}
// Restore interrupts
gmEnableIER( mask );
}
//--------------------------------------------------------------------
// gmIsrEDMARx()
//
// RX Completion Event
//--------------------------------------------------------------------
static void gmIsrEDMARx( int arg )
{
uint *pibuf;
PDINFO *pi;
uint mask;
(void)arg;
// Disable GP interrupts
mask = gmDisableIER( HW_IFLAG );
// 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;
// Finish the RX packet in progress
if( RxState==STATE_DMA )
{
// Disable further RX FrameSync signals
EDMA_disableChannel(hEDMA_rxControl);
if( hDMARxPkt )
{
// Get a pointer to our buffer - add on PREPAD
pibuf = (uint *)(PBM_getDataBuffer(hDMARxPkt)+PKT_PREPAD);
*pibuf++ = DMAData1;
*pibuf++ = DMAData2;
*pibuf = DMAData3;
PBMQ_enq( &PBMQ_rx, hDMARxPkt );
hDMARxPkt = 0;
RxState = STATE_IDLE;
// Notify we have a packet
FlashActiveLED = 1;
STKEVENT_signal( pi->hEvent, STKEVENT_ETHERNET, 1 );
}
}
// Ack any pending device interrupt
if( READ32( GMAC_ISR ) & 0xFF00 )
{
ICR = HW_IFLAG;
gmIsr();
}
// Restore interrupts
gmEnableIER( mask );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -