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

📄 csl_emac.c

📁 这是测试SEED-VPM642系统中网络的接口的测试的程序。(闭环)
💻 C
📖 第 1 页 / 共 4 页
字号:

    /* Keep the old count around */
    CountOrg = pdc->DescCount;

    /* Fill RX Packets Until Full */
    while( pdc->DescCount < pdc->DescMax )
    {
        /* Get a buffer from the application */
        pPkt = (*localDev.Config.pfcbGetPacket)(pdc->pd->hApplication);

        /* If no more buffers are available, break out of loop */
        if( !pPkt )
            break;

        /* Fill in the descriptor for this buffer */
        pDesc = pdc->pDescWrite;

        /* Move the write pointer and bump count */
        if( pdc->pDescWrite == pdc->pDescLast )
            pdc->pDescWrite = pdc->pDescFirst;
        else
            pdc->pDescWrite++;
        pdc->DescCount++;

        /* Supply buffer pointer with application supplied offset */
        pDesc->pNext     = 0;
        pDesc->pBuffer   = pPkt->pDataBuffer + pPkt->DataOffset;
        pDesc->BufOffLen = localDev.PktMTU;
        pDesc->PktFlgLen = EMAC_DSC_FLAG_OWNER;

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

        /* Push the packet buffer on the local descriptor queue */
        pqPush( &pdc->DescQueue, pPkt );
    }

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

/*--------------------------------------------------------------------*\
* emacDequeueRx()
*
* Dequeue all completed RX packets and give buffers to application
\*--------------------------------------------------------------------*/
static void emacDequeueRx( EMAC_DescCh *pdc, EMAC_Desc *pDescAck )
{
    EMAC_Pkt     *pPkt;
    EMAC_Pkt     *pPktNew;
    EMAC_Desc   *pDescNewRxFirst,*pDescNewRxLast=0;
    uint        tmp;
    Uint32      PktFlgLen;

    /* Remember the first new descriptor slot */
    pDescNewRxFirst = pdc->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 = pdc->pDescRead->PktFlgLen;

        /* Recover the buffer and free it */
        pPkt = pqPop( &pdc->DescQueue );
        if( pPkt )
        {
            /* Fill in the necessary packet header fields */
            pPkt->Flags = PktFlgLen & 0xFFFF0000;
            pPkt->ValidLen = pPkt->PktLength = PktFlgLen & 0xFFFF;
            pPkt->PktChannel = 0;
            pPkt->PktFrags = 1;

            /* Pass the packet to the application */
            pPktNew = (*localDev.Config.pfcbRxPacket)
                                           (pdc->pd->hApplication,pPkt);
        }

        /* See if this was the last buffer */
        if( pdc->pDescRead == pDescAck )
            tmp = 0;

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

        /* See if we got a replacement packet */
        if( pPktNew )
    {
            /* We know we can immediately queue this packet */

            /* Fill in the descriptor for this buffer */
            pDescNewRxLast = pdc->pDescWrite;

            /* Move the write pointer and bump count */
            if( pdc->pDescWrite == pdc->pDescLast )
                pdc->pDescWrite = pdc->pDescFirst;
            else
                pdc->pDescWrite++;
            pdc->DescCount++;

            /* Supply buffer pointer with application supplied offset */
            pDescNewRxLast->pBuffer   = pPktNew->pDataBuffer + pPktNew->DataOffset;
            pDescNewRxLast->BufOffLen = localDev.PktMTU;
            pDescNewRxLast->PktFlgLen = EMAC_DSC_FLAG_OWNER;

            /* Push the packet buffer on the local descriptor queue */
            pqPush( &pdc->DescQueue, pPktNew );
        }
    }

    /*
    // 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;

        /* Make the previous buffer point to us */
        if( pDescNewRxFirst == pdc->pDescFirst )
            pdc->pDescLast->pNext = pDescNewRxFirst;
        else
            (pDescNewRxFirst-1)->pNext = pDescNewRxFirst;
    }

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


/*-----------------------------------------------------------------------*\
* STANDARD API FUNCTIONS
*
* Note on Exclusion (Serialization):
*   The application is charged with verifying that only one of the
* following API calls may only be executing at a given time across
* all threads and all interrupt functions.
*
\*-----------------------------------------------------------------------*/


/*-----------------------------------------------------------------------*\
* EMAC_enumerate()
*
* Enumerates the EMAC peripherals installed in the system and returns an
* integer count. The EMAC devices are enumerated in a consistent
* fashion so that each device can be later referenced by its physical
* index value ranging from "1" to "n" where "n" is the count returned
* by this function.
\*-----------------------------------------------------------------------*/
uint EMAC_enumerate( void )
{
    return(1);
}


/*-----------------------------------------------------------------------*\
* EMAC_open()
*
* Opens the EMAC peripheral at the given physical index and initializes
* it to an embryonic state.
*
* The calling application must supply a operating configuration that
* includes a callback function table. Data from this config structure is
* copied into the device's internal instance structure so the structure
* may be discarded after EMAC_open() returns. In order to change an item
* in the configuration, the the EMAC device must be closed and then
* re-opened with the new configuration.
*
* The application layer may pass in an hApplication callback handle,
* that will be supplied by the EMAC device when making calls to the
* application callback functions.
*
* An EMAC device handle is written to phEMAC. This handle must be saved
* by the caller and then passed to other EMAC device functions.
*
* The default receive filter prevents normal packets from being received
* until the receive filter is specified by calling EMAC_receiveFilter().
*
* A device reset is achieved by calling EMAC_close() followed by EMAC_open().
*
* The function returns zero on success, or an error code on failure.
*
* Possible error codes include:
*   EMAC_ERROR_ALREADY   - The device is already open
*   EMAC_ERROR_INVALID   - A calling parameter is invalid
*
\*-----------------------------------------------------------------------*/
uint EMAC_open( int physicalIndex, Handle hApplication,
                EMAC_Config *pEMACConfig, Handle *phEMAC )
{
    int             i;
    volatile Uint32 *pRegAddr;
    Uint32          tmpval;
    EMAC_Pkt        *pPkt;
    uint            utemp1;
    EMAC_Desc       *pDesc;

    /* We only handle a single instance */
    if( physicalIndex != 1 )
        return( EMAC_ERROR_INVALID );

    /* If the device is alread open, return an error */
    if( openFlag )
        return( EMAC_ERROR_ALREADY );

    /*
    //  Validate the supplied configuration structure
    */
    if( !pEMACConfig || !phEMAC )
        return( EMAC_ERROR_INVALID );

    /* Rx pool must be at least 8 to 192 */
    if( pEMACConfig->RxMaxPktPool < 8 || pEMACConfig->RxMaxPktPool > 192 )
        return( EMAC_ERROR_INVALID );

    /* MAC address must be supplied and not a multicast address */
    if( pEMACConfig->MacAddr[0] & 1 )
        return( EMAC_ERROR_INVALID );
    for( i=0; i<6 && !(pEMACConfig->MacAddr[i]); i++ )
    if( i==6 )
        return( EMAC_ERROR_INVALID );

    /* Tx Channels must be 1-8 */
    if( pEMACConfig->TxChannels < 1 || pEMACConfig->TxChannels > 8 )
        return( EMAC_ERROR_INVALID );

    /* Callback functions must be supplied */
    if( !pEMACConfig->pfcbGetPacket || !pEMACConfig->pfcbFreePacket ||
            !pEMACConfig->pfcbRxPacket || !pEMACConfig->pfcbStatus ||
            !pEMACConfig->pfcbStatistics )
        return( EMAC_ERROR_INVALID );


    /* MDIO settings must be valid - at least one bit must be set */
    if( !(pEMACConfig->MdioModeFlags & ( MDIO_MODEFLG_AUTONEG |
                MDIO_MODEFLG_HD10  | MDIO_MODEFLG_FD10 |
                MDIO_MODEFLG_HD100 | MDIO_MODEFLG_FD100 )) )
        return( EMAC_ERROR_INVALID );

    /*
    // Init the instance structure
    */

    /* Default everything in our instance structure to zero */
    memset( &localDev, 0, sizeof(EMAC_Device) );

    /* Set the hApplication and RxFilter */
    localDev.hApplication = hApplication;
    localDev.RxFilter     = EMAC_RXFILTER_NOTHING;

    /* Setup the new configuration */
    localDev.Config = *pEMACConfig;


    /*
    //  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 );

    /* Start the MII Configuration */
    localDev.hMDIO = MDIO_open( pEMACConfig->MdioModeFlags );

    /*
    //  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, localDev.Config.MacAddr[5] );
    EMAC_RSET( MACADDRM, localDev.Config.MacAddr[4] );
    tmpval = 0;
    for( i=3; i>=0; i-- )
        tmpval = (tmpval<<8) | localDev.Config.MacAddr[i];
    EMAC_RSET( MACADDRH, tmpval );

    /*
    // Setup Special Receive Conditions (loopback, error frames, etc)
    */

    /* 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 and adjust max buffer accordingly */
    if( localDev.Config.ModeFlags & EMAC_CONFIG_MODEFLG_RXCRC )
    {
        EMAC_FSETS( RXMBPENABLE, RXPASSCRC, INCLUDE );
        localDev.PktMTU = 1518;
    }
    else
        localDev.PktMTU = 1514;

    /* If PASSERROR is set, enable both ERROR and short frames */
    if( localDev.Config.ModeFlags & EMAC_CONFIG_MODEFLG_PASSERROR )
    {
        EMAC_FSETS( RXMBPENABLE, RXCEFEN, ENABLE );
        EMAC_FSETS( RXMBPENABLE, RXCSFEN, ENABLE );
    }

    /* If PASSCONTROL is set, enable control frames */

⌨️ 快捷键说明

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