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

📄 mcf5xxx_fecx.c

📁 motorola 针对coldfire 5275 评估板的Dbug bootloader源程序
💻 C
📖 第 1 页 / 共 3 页
字号:
    else
        MCF_FEC_IALR(ch) |= (uint32)(1 << crc);
}
/********************************************************************/
/*
 * Reset the selected FEC controller
 *
 * Parameters:
 *  ch      FEC channel
 */
void
fec_reset (uint8 ch)
{
    int i;

    #if (FEC_NUM_CH == 1)
        ch = 0;
    #else
        ASSERT(ch < FEC_NUM_CH);
    #endif

    /* Set the Reset bit and clear the Enable bit */
    MCF_FEC_ECR(ch) = MCF_FEC_ECR_RESET;

    /* Wait at least 8 clock cycles */
    for (i=0; i<10; ++i)
        nop();
}
/********************************************************************/
/*
 * Initialize the selected FEC
 *
 * Parameters:
 *  ch      FEC channel
 *  mode    External interface mode (MII, 7-wire, or internal loopback)
 *  pa      Physical (Hardware) Address for the selected FEC
 */
void
fec_init (uint8 ch, uint8 mode, const uint8 *pa)
{
    #if (FEC_NUM_CH == 1)
        ch = 0;
    #else
        ASSERT(ch < FEC_NUM_CH);
    #endif

    /*
     * Clear the Individual and Group Address Hash registers
     */
    MCF_FEC_IALR(ch) = 0;
    MCF_FEC_IAUR(ch) = 0;
    MCF_FEC_GALR(ch) = 0;
    MCF_FEC_GAUR(ch) = 0;

    /*
     * Set the Physical Address for the selected FEC
     */
    fec_set_address(ch, pa);

    /* 
     * Set Rx Buffer Size 
     */
    MCF_FEC_EMRBR(ch) = (uint16)RX_BUF_SZ;

    /* 
     * Point to the start of the circular Rx buffer descriptor queue 
     */
    MCF_FEC_ERDSR(ch) = fecbd_get_start(Rx);

    /* 
     * Point to the start of the circular Tx buffer descriptor queue 
     */
    MCF_FEC_ETDSR(ch) = fecbd_get_start(Tx);

    /*
     * Mask all FEC interrupts
     */
    MCF_FEC_EIMR(ch) = MCF_FEC_EIMR_MASK_ALL;

    /*
     * Clear all FEC interrupt events
     */
    MCF_FEC_EIR(ch) = MCF_FEC_EIR_CLEAR_ALL;

    /*
     * Initialize the Receive Control Register
     */
    MCF_FEC_RCR(ch) = 0
        | MCF_FEC_RCR_MAX_FL(ETH_MAX_FRM)
    #ifdef FEC_PROMISCUOUS
        | MCF_FEC_RCR_PROM
    #endif
        | MCF_FEC_RCR_FCE;

    if (mode == FEC_MODE_MII)
        MCF_FEC_RCR(ch) |= MCF_FEC_RCR_MII_MODE;

    else if (mode == FEC_MODE_LOOPBACK)
        MCF_FEC_RCR(ch) |= MCF_FEC_RCR_LOOP;

    /*
     * Initialize the Transmit Control Register
     */
    MCF_FEC_TCR(ch) = MCF_FEC_TCR_FDEN;
}
/********************************************************************/
/*
 * Continue the Rx FEC DMA
 *
 * This routine is called after the DMA has halted after
 * encountering a Rx buffer descriptor that wasn't marked as
 * empty.  There is no harm in calling the continue DMA routine
 * if the DMA was not paused.
 *
 * Parameters:
 *  ch      FEC channel
 */
void
fec_rx_continue(uint8 ch)
{
    /*
     * Continue/restart the FEC DMA
     */
    MCF_FEC_RDAR(ch) = MCF_FEC_RDAR_R_DES_ACTIVE;
}
/********************************************************************/
/*
 * Receive Frame interrupt handler - this handler is called by the 
 * FEC/DMA interrupt handler indicating that a packet was successfully
 * transferred out of the Rx FIFO.
 *
 * Parameters:
 *  nif     Pointer to Network Interface structure
 *  ch      FEC channel
 */
void
fec_rx_handler(NIF *nif)
{
    ETH_HDR *eth_hdr;
    FECBD *pRxBD;
    NBUF *cur_nbuf, *new_nbuf;
    uint8 ch = (uint8)nif->ch;
    int keep;

    while ((pRxBD = fecbd_rx_alloc()) != NULL)
    {
        keep = TRUE;
        
        if (pRxBD->status & RX_BD_L)
            fec_log[ch].rxf++;
        else
            fec_log[ch].rxb++;

        if (pRxBD->status & RX_BD_ERROR)
        {
            keep = FALSE;
            if (pRxBD->status & RX_BD_NO)
                fec_log[ch].rfsw_no++;
            if (pRxBD->status & RX_BD_CR)
                fec_log[ch].rfsw_cr++;
            if (pRxBD->status & RX_BD_OV)
                fec_log[ch].rfsw_ov++;
            if (pRxBD->status & RX_BD_TR)
                fec_log[ch].rfsw_tr++;
        }
        else
        {
            if (pRxBD->status & RX_BD_LG)
                fec_log[ch].rfsw_lg++;
            if (pRxBD->status & RX_BD_M)
                fec_log[ch].rfsw_m++;
            if (pRxBD->status & RX_BD_BC)
                fec_log[ch].rfsw_bc++;
            if (pRxBD->status & RX_BD_MC)
                fec_log[ch].rfsw_mc++;
        }

        if (keep)
        {
            /* 
             * Pull the network buffer off the Rx ring queue 
             */
            cur_nbuf = nbuf_remove(NBUF_RX_RING);
            ASSERT(cur_nbuf);
            ASSERT(cur_nbuf->data == pRxBD->data);

            /*
             * Copy the buffer descriptor information to the network buffer
             */
            cur_nbuf->length = (pRxBD->length - (ETH_HDR_LEN + ETH_CRC_LEN));
            cur_nbuf->offset = ETH_HDR_LEN;

            /*
             * Get a new buffer pointer for this buffer descriptor
             */
            new_nbuf = nbuf_alloc();
            if (new_nbuf == NULL)
            {
                #ifdef DEBUG
                    printf("nbuf_alloc() failed\n");
                #endif
                /*
                 * Can't allocate a new network buffer, so we
                 * have to trash the received data and reuse the buffer
                 * hoping that some buffers will free up in the system
                 * and this frame will be re-transmitted by the host
                 */
                pRxBD->length = RX_BUF_SZ;
                pRxBD->status &= (RX_BD_W | RX_BD_INTERRUPT);
                pRxBD->status |= RX_BD_E;
                nbuf_add(NBUF_RX_RING, cur_nbuf);
                fec_rx_continue(ch);
                continue;
            }

            /*
             * Add the new network buffer to the Rx ring queue
             */
            nbuf_add(NBUF_RX_RING, new_nbuf);

            /*
             * Re-initialize the buffer descriptor - pointing it
             * to the new data buffer.  The previous data buffer
             * will be passed up the stack
             */
            pRxBD->data = new_nbuf->data;
            pRxBD->length = RX_BUF_SZ;
            pRxBD->status &= (RX_BD_W | RX_BD_INTERRUPT);
            pRxBD->status |= RX_BD_E;


            /*
             * Let the DMA know that there is a new Rx BD (in case the 
             * ring was full and the DMA was waiting for an empty one)
             */
            fec_rx_continue(ch);

            /*
             * Get pointer to the frame data inside the network buffer
             */
            eth_hdr = (ETH_HDR *)cur_nbuf->data;
            
            /*
             * Pass the received packet up the network stack if the 
             * protocol is supported in our network interface (NIF)
             */
            if (nif_protocol_exist(nif,eth_hdr->type))
            {
                nif_protocol_handler(nif, eth_hdr->type, cur_nbuf);
            }
            else
                nbuf_free(cur_nbuf);
        }
        else 
        {
            /* 
             * This frame isn't a keeper
             * Reset the status and length, but don't need to get another
             * buffer since we are trashing the data in the current one
             */
            pRxBD->length = RX_BUF_SZ;
            pRxBD->status &= (RX_BD_W | RX_BD_INTERRUPT);
            pRxBD->status |= RX_BD_E;

            /*
             * Move the current buffer from the beginning to the end of the 
             * Rx ring queue
             */
            cur_nbuf = nbuf_remove(NBUF_RX_RING);
            nbuf_add(NBUF_RX_RING, cur_nbuf);

            /*
             * Let the DMA know that there are new Rx BDs (in case
             * it is waiting for an empty one)
             */
            fec_rx_continue(ch);
        }
    }
}
/********************************************************************/
/*
 * Continue the Tx FEC DMA
 *
 * This routine is called after the DMA has halted after
 * encountering a Tx buffer descriptor that wasn't marked as
 * ready.  There is no harm in calling the continue DMA routine
 * if the DMA was not paused.
 *
 * Parameters:
 *  ch      FEC channel
 */
void
fec_tx_continue(uint8 ch)
{
    #if (FEC_NUM_CH == 1)
        ch = 0;
    #else
        ASSERT(ch < FEC_NUM_CH);
    #endif

    /*
     * Continue/restart the FEC DMA
     */
    MCF_FEC_TDAR(ch) = MCF_FEC_TDAR_X_DES_ACTIVE;
}
/********************************************************************/
/*
 * Stop all transmissions on the selected FEC and kill the DMA task
 *
 * Parameters:
 *  ch  FEC channel
 */
void
fec_tx_stop (uint8 ch)
{
    int i;
    uint32 mask;

    #if (FEC_NUM_CH == 1)
        ch = 0;
    #else
        ASSERT(ch < FEC_NUM_CH);
    #endif

    /* Save off the EIMR value */
    mask = MCF_FEC_EIMR(ch);

    /* Mask all interrupts */
    MCF_FEC_EIMR(ch) = 0;

    /* Issue the Graceful Transmit Stop */
    MCF_FEC_TCR(ch) |= MCF_FEC_TCR_GTS;

    /* Wait for the Graceful Stop Complete interrupt */
    i = 500000;
    while(!(MCF_FEC_EIR(ch) & MCF_FEC_EIR_GRA))
    {
        if (--i == 0)
            break;
    }

    /* Clear the Graceful Stop Complete interrupt */
    MCF_FEC_EIR(ch) = MCF_FEC_EIR_GRA;

    /* Restore the interrupt mask register value */
    MCF_FEC_EIMR(ch) = mask;
}
/********************************************************************/
/*
 * Trasmit Frame interrupt handler - this handler is called by the 
 * FEC/DMA interrupt handler indicating that a packet was successfully
 * transferred into the Tx FIFO. 
 *
 * Parameters:
 *  nif     NIF structure
 */
void
fec_tx_handler(NIF *nif)
{
    uint32 event, eir;
    uint8 ch = (uint8)nif->ch;
    FECBD *pTxBD;
    NBUF *pNbuf;
    
    ASSERT(ch < FEC_NUM_CH);

    /*
     * Determine which interrupt(s) asserted by AND'ing the
     * pending interrupts with those that aren't masked.
     */
    eir = MCF_FEC_EIR(ch);
    event = eir & MCF_FEC_EIMR(ch);
    #ifdef DEBUG
    if (event != eir)
        printf("Pending but not enabled: 0x%08X\n",(event ^ eir));
    #endif
    
    /*
     * Clear the event(s) in the EIR immediately
     */
    MCF_FEC_EIR(ch) = event;

    while ((pTxBD = fecbd_tx_free()) != NULL)
    {
        /*
         * Grab the network buffer associated with this buffer descriptor
         */
        pNbuf = nbuf_remove(NBUF_TX_RING);
        ASSERT(pNbuf);
        ASSERT(pNbuf->data == pTxBD->data);
        
        if (pTxBD->status & TX_BD_L)
            fec_log[ch].txf++;
        else
            fec_log[ch].txb++;
        
        /*
         * Free up the network buffer that was just transmitted
         */
        nbuf_free(pNbuf);

        /*
         * Re-initialize the Tx BD
         */
        pTxBD->data = NULL;
        pTxBD->length = 0;
    }    
}
/********************************************************************/
/*
 * Send a packet out the selected FEC
 *
 * Parameters:
 *  ch      FEC channel
 *  nif     Pointer to Network Interface (NIF) structure
 *  dst     Destination MAC Address

⌨️ 快捷键说明

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