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

📄 dm642.c

📁 dm642网络传输程序
💻 C
📖 第 1 页 / 共 2 页
字号:

        /*
        // 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 & EMAC_FMK( MACINVECTOR, TXPEND, 1<<0 ) )
    {
        Desc = EMAC_RGET( TX0INTACK );
        EMAC_RSET( TX0INTACK, Desc );

        emacDequeueTx( (EMAC_Desc *)Desc );
    }

    // Look for RX interrupt (channel 0)
    if( intflags & EMAC_FMK( MACINVECTOR, RXPEND, 1<<0 ) )
    {
        Desc = EMAC_RGET( RX0INTACK );
        EMAC_RSET( RX0INTACK, Desc );

        emacDequeueRx( (EMAC_Desc *)Desc );
    }

    // Enable EMAC/MDIO interrupts in wrapper
    EMAC_FSETS( 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
    */

    /*
    // Globally disable EMAC/MDIO interrupts in wrapper and put both
    // EMAC and MDIO modules into reset
    */
    EMAC_RSET( EWCTL, EMAC_FMKS( EWCTL, INTEN, DISABLE ) |
                      EMAC_FMKS( EWCTL, EMACRST, YES ) |
                      EMAC_FMKS( EWCTL, MDIORST, YES ) );

    /* Wait about 100 cycles */
    for( i=0; i<5; i++ )
        tmpval = EMAC_RGET( EWCTL );

    /* Leave EMAC/MDIO interrupts disabled and take both
       EMAC and MDIO modules out of reset */
    EMAC_RSET( EWCTL, EMAC_FMKS( EWCTL, INTEN, DISABLE ) |
                      EMAC_FMKS( EWCTL, EMACRST, NO ) |
                      EMAC_FMKS( EWCTL, MDIORST, NO ) );

    /* Wait about 100 cycles */
    for( i=0; i<5; i++ )
        tmpval = EMAC_RGET( EWCTL );

    /* Program the interrupt pacer */
    EMAC_RSET( EWINTTCNT, 4000 );

    /* Start the MII Configuration */
    hMDIO = MDIO_open( MDIO_MODEFLG_AUTONEG );

    /*
    //  Setup the EMAC
    */

    /* Reset MAC Control */
    EMAC_RSET( MACCONTROL, 0 );

    /* Must manually init HDPs to NULL */
    pRegAddr = EMAC_ADDR(TX0HDP);
    for( i=0; i<8; i++ )
        *pRegAddr++ = 0;
    pRegAddr = EMAC_ADDR(RX0HDP);
    for( i=0; i<8; i++ )
        *pRegAddr++ = 0;

    /*
    // While MIIEN is clear in MACCONTROL, we can write directly to
    // the statistics registers (there are "EMAC_NUMSTATS" of them).
    */
    pRegAddr = EMAC_ADDR(RXGOODFRAMES);
    for( i=0; i<EMAC_NUMSTATS; i++ )
        *pRegAddr++ = 0;

    /* Setup device MAC address */
    EMAC_RSET( MACADDRL0, *(pPDI->bMacAddr+5) );
    EMAC_RSET( MACADDRM, *(pPDI->bMacAddr+4) );
    tmpval = 0;
    for( i=3; i>=0; i-- )
        tmpval = (tmpval<<8) | *(pPDI->bMacAddr+i);
    EMAC_RSET( MACADDRH, tmpval );

    /* For us buffer offset will always be zero */
    EMAC_RSET( RXBUFFEROFFSET, 0 );

    /* Reset RX (M)ulticast (B)roadcast (P)romiscuous Enable register */
    EMAC_RSET( RXMBPENABLE, 0 );
    EMAC_RSET( MACHASH1, 0 );
    EMAC_RSET( MACHASH2, 0 );

    /* Clear Unicast RX on channel 0-7 */
    EMAC_RSET( RXUNICASTCLEAR, 0xFF );

    /* Set the pass RX CRC mode */
    EMAC_FSETS( RXMBPENABLE, RXPASSCRC, INCLUDE );

    /* Set MAC loopback if requested */
    //  EMAC_FSETS( MACCONTROL, LOOPBACK, ENABLE );

    /*
    // Enable TX and RX channel interrupts (set mask bits)
    // Enable Host interrupts
    */
    EMAC_RSET( RXINTMASKCLEAR, 0xFF );
    EMAC_RSET( TXINTMASKCLEAR, 0xFF );
    EMAC_RSET( RXINTMASKSET, 1 );
    EMAC_RSET( TXINTMASKSET, 1 );
    EMAC_RSET( MACINTMASKSET, EMAC_FMK(MACINTMASKSET,HOSTERRINT,1) |
                              EMAC_FMK(MACINTMASKSET,STATINT,1) );

    /*
    // Setup Receive Buffers
    */

    /* Pointer to first descriptor to use on RX */
    pDesc = (EMAC_Desc *)_EMAC_DSC_BASE_ADDR;

    /* Number of descriptors for RX channel */
    utemp1 = EMAC_MAX_RX;

    /* Init Rx channel */
    mmZeroInit( &chRx, sizeof(EMAC_DescCh) );
    chRx.DescMax    = utemp1;
    chRx.pDescFirst = pDesc;
    chRx.pDescLast  = pDesc + (utemp1 - 1);
    chRx.pDescRead  = pDesc;
    chRx.pDescWrite = pDesc;

    /* Fill the descriptor table */
    emacEnqueueRx(0);

    /*
    // If we didn't get the number of descriptor buffers that we
    // wanted to, abort now.
    */
    if( chRx.DescCount < utemp1 )
    {
        /* Free all RX descriptors */
        while( hPkt = PBMQ_deq( &chRx.DescQueue ) )
            PBM_free(hPkt);

        /* Close the MDIO Module */
        MDIO_close( hMDIO );

        /* Return the error condition */
        return( 0 );
    }

    /*
    // Setup Transmit Buffers
    */

    /* Pointer to first descriptor to use on TX */
    pDesc += utemp1;

    /* Number of descriptors (max) for TX channel */
    utemp1 = (_EDMA_DSC_ENTRY_COUNT-utemp1);

    /* Init TX channel */
    mmZeroInit( &chTx, sizeof(EMAC_DescCh) );
    chTx.DescMax    = utemp1;
    chTx.pDescFirst = pDesc;
    chTx.pDescLast  = pDesc + (utemp1 - 1);
    chTx.pDescRead  = pDesc;
    chTx.pDescWrite = pDesc;


    /*
    // Enable RX, TX, and MII
    //
    // Note in full duplex mode we also need to set the FULLDUPLEX
    // bit in MACCRONTROL. However, we don't know what to set until
    // we have a link. Also, we must be able to dynamically change
    // this bit if the cable is unplugged and re-linked with a different
    // duplex.
    */
    EMAC_FSETS( TXCONTROL, TXEN, ENABLE );
    EMAC_FSETS( RXCONTROL, RXEN, ENABLE );
    EMAC_FSETS( MACCONTROL, MIIEN, ENABLE );

    /* Startup RX */
    EMAC_RSET( RX0HDP, (Uint32)chRx.pDescRead );

    /* Enable global interrupt in wrapper */
    ICR = IntFlag;
    EMAC_FSETS( EWCTL, INTEN, ENABLE );

    return(1);
}

/*--------------------------------------------------------------------*\
* emacDequeueTx()
*
* Dequeue all completed TX packets and return buffers to application
\*--------------------------------------------------------------------*/
static void emacDequeueTx( EMAC_Desc *pDescAck )
{
    PBM_Handle  hPkt;
    Uint32      PktFlgLen;
    register uint  i,j = (uint)chTx.pDescRead;

    /* Get the status of the ACK descriptor */
    PktFlgLen = pDescAck->PktFlgLen;

    /* Calc the new "Read" descriptor */
    if( pDescAck == chTx.pDescLast )
        chTx.pDescRead = chTx.pDescFirst;
    else
        chTx.pDescRead = pDescAck+1;

    i = (uint)chTx.pDescRead;

    /* Turn i into a descriptor count */
    if( j < i )
        i = (i-j)/sizeof(EMAC_Desc);
    else
        i = chTx.DescMax - ((j-i)/sizeof(EMAC_Desc));

    chTx.DescCount -= i;

    /* Pop & Free Buffers 'till the last Descriptor */
    while( i-- )
    {
        // Recover the packet and free it
        hPkt = PBMQ_deq( &chTx.DescQueue );
        if( hPkt )
            PBM_free( hPkt );
    }

    // If the transmitter stopped and we have more descriptors, then restart
    if( (PktFlgLen & EMAC_DSC_FLAG_EOQ) && chTx.DescCount )
        EMAC_RSET( TX0HDP, (Uint32)chTx.pDescRead );
}


/*--------------------------------------------------------------------*\
* emacEnqueueRx()
*
* Fill any empty RX descriptors with new buffers from the application
\*--------------------------------------------------------------------*/
static void emacEnqueueRx( uint fRestart )
{
    PBM_Handle  hPkt;
    EMAC_Desc   *pDesc;
    uint        CountOrg;
    UINT8       *buffer;

    // Keep the old count around
    CountOrg = chRx.DescCount;

    // Fill RX Packets Until Full
    while( chRx.DescCount < chRx.DescMax )
    {
        // Try and get a buffer.
        hPkt = PBM_alloc( 1518 + PKT_PREPAD );

        if( !hPkt )
            break;

        PBM_setDataOffset( hPkt, PKT_PREPAD );
        buffer = PBM_getDataBuffer(hPkt) + PKT_PREPAD;

        // Clean the cache for external addesses
        if( (UINT32)buffer & 0x80000000 )
            OEMCacheClean( (void *)buffer, 1518 );

        // Fill in the descriptor for this buffer
        pDesc = chRx.pDescWrite;

        // Move the write pointer and bump count
        if( chRx.pDescWrite == chRx.pDescLast )
            chRx.pDescWrite = chRx.pDescFirst;
        else
            chRx.pDescWrite++;
        chRx.DescCount++;

        // Fill in the descriptor
        pDesc->pNext     = 0;
        pDesc->pBuffer   = buffer;
        pDesc->BufOffLen = 1518;
        pDesc->PktFlgLen = EMAC_DSC_FLAG_OWNER;

        // Enqueue this packet onto the desc queue
        PBMQ_enq( &chRx.DescQueue, hPkt );

        // Synch the cache
        if( (UINT32)buffer & 0x80000000 )
            OEMCacheCleanSynch();

        // Make the previous buffer point to us
        if( pDesc == chRx.pDescFirst )
             chRx.pDescLast->pNext = pDesc;
        else
            (pDesc-1)->pNext = pDesc;
    }

    /* Restart RX if we had ran out of descriptors and got some here */
    if( fRestart && !CountOrg && chRx.DescCount )
        EMAC_RSET( RX0HDP, (Uint32)chRx.pDescRead );
}


/*--------------------------------------------------------------------*\
* emacDequeueRx()
*
* Dequeue all completed RX packets and give buffers to application
\*--------------------------------------------------------------------*/
static void emacDequeueRx( EMAC_Desc *pDescAck )
{
    PBM_Handle  hPkt;
    uint        tmp;
    Uint32      PktFlgLen;
    uint        NeedService = 0;
    EMAC_Desc   *pDescNewRxFirst,*pDescNewRxLast=0,*pTemp;
    UINT8       *buffer;

    /* Remember the first new descriptor slot */
    pDescNewRxFirst = chRx.pDescWrite;

    /*
    // Pop & Free Buffers 'till the last Descriptor
    // One thing we know for sure is that all the decriptors from
    // the read pointer to pDescAsk are linked to each other via
    // their pNext field.
    */
    for( tmp=1; tmp; )
    {
        /* Get the status of this descriptor */
        PktFlgLen = chRx.pDescRead->PktFlgLen;

        // Recover the packet and pass it on
        hPkt = PBMQ_deq( &chRx.DescQueue );
        if( hPkt )
        {
            // Enque the packet and signal the stack
            PBM_setIFRx( hPkt, pPDI->hEther );
            PBM_setValidLen(hPkt,(PktFlgLen & 0xFFFF));
            PBMQ_enq( &PBMQ_rx, hPkt );
            NeedService = 1;
        }

        /* See if this was the last buffer */
        if( chRx.pDescRead == pDescAck )
            tmp = 0;

        /* Move the read pointer and decrement count */
        if( chRx.pDescRead == chRx.pDescLast )
            chRx.pDescRead = chRx.pDescFirst;
        else
            chRx.pDescRead++;
        chRx.DescCount--;

        // Try and get a buffer.
        hPkt = PBM_alloc( 1518 + PKT_PREPAD );

        if( hPkt )
        {
            PBM_setDataOffset( hPkt, PKT_PREPAD );
            buffer = PBM_getDataBuffer(hPkt) + PKT_PREPAD;

            // Clean the cache for external addesses
            if( (UINT32)buffer & 0x80000000 )
                OEMCacheClean( (void *)buffer, 1518 );

            // Fill in the descriptor for this buffer
            pDescNewRxLast = chRx.pDescWrite;

            // Move the write pointer and bump count
            if( chRx.pDescWrite == chRx.pDescLast )
                chRx.pDescWrite = chRx.pDescFirst;
            else
                chRx.pDescWrite++;
            chRx.DescCount++;

            // Fill in the descriptor
            pDescNewRxLast->pBuffer   = buffer;
            pDescNewRxLast->BufOffLen = 1518;
            pDescNewRxLast->PktFlgLen = EMAC_DSC_FLAG_OWNER;

            // Enqueue this packet onto the desc queue
            PBMQ_enq( &chRx.DescQueue, hPkt );
        }
    }

    /*
    // If we added descriptors, make the pNext of the last NULL, and
    // make the previous descriptor point to the new list we added.
    */
    if( pDescNewRxLast )
    {
        pDescNewRxLast->pNext = 0;

        // Synch the cache
        if( (UINT32)buffer & 0x80000000 )
            OEMCacheCleanSynch();

        /* Make the previous buffer point to us */
        if( pDescNewRxFirst == chRx.pDescFirst )
            pTemp = chRx.pDescLast;
        else
            pTemp = pDescNewRxFirst-1;

        /*
        // If these pointers wrapped, the RX engine is stopped
        // Otherwise; tack the new list to the old
        */
        if( pTemp != pDescNewRxLast )
            pTemp->pNext = pDescNewRxFirst;
    }

    /* If the receiver stopped and we have more descriptors, then restart */
    if( (PktFlgLen & EMAC_DSC_FLAG_EOQ) && chRx.DescCount )
        EMAC_RSET( RX0HDP, (Uint32)chRx.pDescRead );

    // Signal the stack if needed
    if( NeedService )
    {
        FlashActiveLED = 1;
        STKEVENT_signal( pPDI->hEvent, STKEVENT_ETHERNET, 1 );
    }
}




⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -