⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mxf.c

📁 dm642网络传输程序
💻 C
📖 第 1 页 / 共 3 页
字号:
    // 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 + -