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

📄 mcf5xxx_fec.c

📁 motorola 针对coldfire 5275 评估板的Dbug bootloader源程序
💻 C
📖 第 1 页 / 共 2 页
字号:
                 * 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();
                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();

            /*
             * 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();
        }
    }
}
/********************************************************************/
/*
 * 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.
 */
void
fec_tx_continue(void)
{
    /*
     * Continue/restart the FEC DMA
     */
    MCF_FEC_TDAR = MCF_FEC_TDAR_X_DES_ACTIVE;
}
/********************************************************************/
/*
 * Stop all transmissions on the selected FEC and kill the DMA task
 */
void
fec_tx_stop (void)
{
    int i;
    uint32 mask;

    /* Save off the EIMR value */
    mask = MCF_FEC_EIMR;

    /* Mask all interrupts */
    MCF_FEC_EIMR = 0;

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

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

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

    /* Restore the interrupt mask register value */
    MCF_FEC_EIMR = 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. 
 */
void
fec_tx_handler(void)
{
    FECBD *pTxBD;
    NBUF *pNbuf;

    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.txf++;
        else
            fec_log.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
 *
 * Parameters:
 *  nif     Pointer to Network Interface (NIF) structure
 *  dst     Destination MAC Address
 *  src     Source MAC Address
 *  type    Ethernet Frame Type
 *  nbuf    Pointer to the network buffer
 *
 * Return Value:
 *  1       success
 *  0       otherwise
 */
int
fec_send (NIF *nif, uint8 *dst, uint8 *src, uint16 type, NBUF *nbuf)
{
    FECBD *pTxBD;
    (void) nif;

    /* Check the length */
    if ((nbuf->length + ETH_HDR_LEN) > ETH_MTU)
        return 0;

    /* 
     * Copy the destination address, source address, and Ethernet 
     * type into the packet 
     */
    memcpy(&nbuf->data[0],  dst,   6);
    memcpy(&nbuf->data[6],  src,   6);
    memcpy(&nbuf->data[12], &type, 2);

    /*
     * Grab the next available Tx Buffer Descriptor
     */
    if ((pTxBD = fecbd_tx_alloc()) == NULL)
        return 0;

    /*
     * Put the network buffer into the Tx waiting queue
     */
    nbuf_add(NBUF_TX_RING, nbuf);

    /* 
     * Setup the buffer descriptor for transmission
     */
    pTxBD->data = nbuf->data;
    pTxBD->length = nbuf->length + ETH_HDR_LEN;
    pTxBD->status |= (TX_BD_R | TX_BD_L | TX_BD_TC);

    /*
     * Continue the Tx DMA task (in case it was waiting for a new
     * TxBD to be ready)
     */
    fec_tx_continue();

    return 1;
}
/********************************************************************/
/* 
 * Resend the last packet that was already prepared and sent
 */
void
fec_resend (void)
{
    FECBD *pTxBD;
    NBUF *pNbuf;
    

    /*
     * Grab the most recently sent TxBD
     */
    pTxBD = fecbd_tx_free();
    ASSERT(pTxBD != NULL);

    /*
     * Grab the network buffer associated with this buffer descriptor
     */
    pNbuf = nbuf_remove(NBUF_TX_RING);
    ASSERT(pNbuf);
    ASSERT(pNbuf->data == pTxBD->data);

    /*
     * Grab the next available Tx Buffer Descriptor
     */
    while ((pTxBD = fecbd_tx_alloc()) == NULL) 
        ;

    /*
     * Put the network buffer back into the Tx waiting queue
     */
    nbuf_add(NBUF_TX_RING, pNbuf);

    /*
     * Reset the TxBD status flags
     */
    pTxBD->data = pNbuf->data;
    pTxBD->length = pNbuf->length + ETH_HDR_LEN;
    pTxBD->status |= (TX_BD_R | TX_BD_L | TX_BD_TC);

    /*
     * Continue the Tx DMA task (in case it was waiting for a new
     * TxBD to be ready)
     */
    fec_tx_continue();
}
/********************************************************************/
/*
 * Enable interrupts from the FEC
 */
void
fec_irq_enable(void)
{
    /*
     * Clear any pending FEC interrupt events
     */
    MCF_FEC_EIR = MCF_FEC_EIR_CLEAR_ALL;

    /*
     * Unmask all FEC interrupts
     */
    MCF_FEC_EIMR = MCF_FEC_EIMR_UNMASK_ALL;
}
/********************************************************************/
/*
 * Disable interrupts from the FEC
 */
void
fec_irq_disable(void)
{
    /*
     * Mask all FEC interrupts
     */
    MCF_FEC_EIMR = MCF_FEC_EIMR_MASK_ALL;
}
/********************************************************************/
/*
 * FEC interrupt handler
 */
int
fec_irq_handler(void* arg1, void* arg2)
{
    uint32 event, eir;
    (void) arg2;
    
    /*
     * Determine which interrupt(s) asserted by AND'ing the
     * pending interrupts with those that aren't masked.
     */
    eir = MCF_FEC_EIR;
    event = eir & MCF_FEC_EIMR;

    #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 = event;
    if (event & MCF_FEC_EIR_UN)
    {
        fec_log.errors++;
        fec_log.un++;
        #ifdef DEBUG
        printf("FEC Tx FIFO Underflow\n");
        #endif
    }
    if (event & MCF_FEC_EIR_RL)
    {
        fec_log.errors++;
        fec_log.rl++;
        #ifdef DEBUG
        printf("FEC Collision Retry Limit\n");
        #endif
        fec_resend();
    }
    if (event & MCF_FEC_EIR_LC)
    {
        fec_log.errors++;
        fec_log.lc++;
        #ifdef DEBUG
        printf("FEC Late Collision\n");
        #endif
        fec_resend();
    }
    if (event & MCF_FEC_EIR_EBERR)
    {
        fec_log.errors++;
        fec_log.eberr++;
        #ifdef DEBUG
        printf("FEC/DMA fatal bus error!\n");
        #endif
        fec_eth_stop();
    }
    if (event & MCF_FEC_EIR_MII)
    {
        fec_log.mii++;
    }
    if (event & MCF_FEC_EIR_RXB || event & MCF_FEC_EIR_RXF)
    {
        fec_rx_handler((NIF *)arg1);
    }
    if (event & MCF_FEC_EIR_TXB || event & MCF_FEC_EIR_TXF)
    {
        fec_tx_handler();
    }
    if (event & MCF_FEC_EIR_GRA)
    {
        fec_log.gra++;
    }
    if (event & MCF_FEC_EIR_BABT)
    {
        fec_log.errors++;
        fec_log.babt++;
        #ifdef DEBUG
        printf("FEC Babbling transmit error\n");
        #endif
    }
    if (event & MCF_FEC_EIR_BABR)
    {
        fec_log.errors++;
        fec_log.babr++;
        #ifdef DEBUG
        printf("FEC Babbling receive error\n");
        #endif
    }
    if (event & MCF_FEC_EIR_HBERR)
    {
        fec_log.errors++;
        fec_log.hberr++;
        #ifdef DEBUG
        printf("HBERR\n");
        #endif
    }
    
    return TRUE;
}
/********************************************************************/
/*
 * Configure the selected Ethernet port and enable all operations
 *
 * Parameters:
 *  trcvr   Transceiver mode (MII, 7-Wire or internal loopback)
 *  mac     Physical (MAC) Address
 */
void
fec_eth_setup(uint8 trcvr, const uint8 *mac)
{
    /*
     * Disable FEC interrupts
     */
    fec_irq_disable();

    /*
     * Initialize the event log
     */
    fec_log_init();

    /*
     * Initialize the network buffers and fec buffer descriptors
     */
    nbuf_init();
    fecbd_init();

    /*
     * Initialize the FEC
     */
    fec_reset();
    fec_init(trcvr,mac);

    if (trcvr == FEC_MODE_MII)
    {
        /*
         * Initialize the MII interface
         */
        fec_mii_init(SYSTEM_CLOCK);
    }

    /*
     * Initialize and enable FEC interrupts
     */
    fec_irq_enable();

    /*
     * Enable the FEC channel
     */
    MCF_FEC_ECR |= MCF_FEC_ECR_ETHER_EN;

    /*
     * Start the Rx FEC DMA 
     */
    fec_rx_continue();
}
/********************************************************************/
/*
 * Reset the Ethernet port
 */
void
fec_eth_reset(void)
{
    fec_reset();
}
/********************************************************************/
/*
 * Stop the Ethernet port
 */
void
fec_eth_stop(void)
{
    int level;
    
    /*
     * Disable interrupts
     */
    level = asm_set_ipl(7);

    /*
     * Disable FEC interrupts
     */
    fec_irq_disable();

    /*
     * Gracefully disable the transmitter
     */
    fec_tx_stop();

    /*
     * Disable the FEC channel
     */
    MCF_FEC_ECR &= ~MCF_FEC_ECR_ETHER_EN;

    #ifdef DEBUG
        nbuf_debug_dump();
        fecbd_dump();
        fec_log_dump();
    #endif

    /* 
     * Flush the network buffers
     */
    nbuf_flush();

    /* 
     * Restore interrupt level
     */
    asm_set_ipl(level);
}
/********************************************************************/

#endif /* #ifdef DBUG_NETWORK */

⌨️ 快捷键说明

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