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

📄 fec.c

📁 motorola 针对coldfire 5275 评估板的Dbug bootloader源程序
💻 C
📖 第 1 页 / 共 3 页
字号:
        while(!(MCF_FEC_EIR(ch) & MCF_FEC_EIR_GRA))
        {
            if (!(MCF_FEC_ECR(ch) & MCF_FEC_ECR_ETHER_EN))
                break;
        }

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

    /*
     * Determine the DMA channel running the task for the
     * selected FEC
     */
    channel = dma_get_channel(DMA_FEC_TX(ch));
    ASSERT(channel > 0);

    /* Kill the FEC Tx DMA task */
    MCD_killDma(channel);

    /* 
     * Free up the FEC requestor from the software maintained 
     * initiator list 
     */
    dma_free_initiator(DMA_FEC_TX(ch));

    /* Free up the DMA channel */
    dma_free_channel(DMA_FEC_TX(ch));

    /* Restore the interrupt mask register value */
    MCF_FEC_EIMR(ch) = mask;
}
/********************************************************************/
/*
 * Trasmit Frame interrupt handler - this handler is called by the 
 * DMA interrupt handler indicating that a packet was successfully
 * transferred to the Tx FIFO.
 *
 * Parameters:
 *  ch      FEC channel
 */
void
fec_tx_frame(uint8 ch)
{
    FECBD *pTxBD;
    NBUF *pNbuf;

    while ((pTxBD = fecbd_tx_free(ch)) != NULL)
    {
        fec_log[ch].dtxf++;

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

        /*
         * Free up the network buffer that was just transmitted
         */
        nbuf_free(pNbuf);

        /*
         * Re-initialize the Tx BD
         */
        pTxBD->data = NULL;
        pTxBD->length = 0;
    }    
}

void
fec0_tx_frame(void)
{
    fec_tx_frame(0);
}

void
fec1_tx_frame(void)
{
    fec_tx_frame(1);
}
/********************************************************************/
/*
 * Send a packet out the selected FEC
 *
 * Parameters:
 *  ch      FEC channel
 *  nif     Pointer to Network Interface (NIF) structure
 *  dst     Destination MAC Address
 *  src     Source MAC Address
 *  type    Ethernet Frame Type
 *  length  Number of bytes to be transmitted (doesn't include type, 
 *          src, or dest byte count)
 *  pkt     Pointer packet network buffer
 *
 * Return Value:
 *  1       success
 *  0       otherwise
 */
int
fec_send (uint8 ch, NIF *nif, uint8 *dst, uint8 *src, uint16 type, NBUF *nbuf)
{
    FECBD *pTxBD;
    ASSERT(ch == 0 || ch == 1);
    
    /* 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
     */
    while ((pTxBD = fecbd_tx_alloc(ch)) == NULL) {};

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

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

    return 1;
}

int
fec0_send(NIF *nif, uint8 *dst, uint8 *src, uint16 type, NBUF *nbuf)
{
    return fec_send(0, nif, dst, src, type, nbuf);
}

int
fec1_send(NIF *nif, uint8 *dst, uint8 *src, uint16 type, NBUF *nbuf)
{
    return fec_send(1, nif, dst, src, type, nbuf);
}
/********************************************************************/
/*
 * Enable interrupts on the selected FEC
 *
 * Parameters:
 *  ch      FEC channel
 *  pri     Interrupt Priority
 *  lvl     Interrupt Level
 */
void
fec_irq_enable(uint8 ch, uint8 lvl, uint8 pri)
{
    ASSERT(ch == 0 || ch == 1);
    ASSERT(lvl > 0 && lvl < 8);
    ASSERT(pri < 8);

    /*
     * Setup the appropriate ICR
     */
    MCF_INTC_ICRn((ch == 0) ? 39 : 38) = (uint8)(0
        | MCF_INTC_ICRn_IP(pri)
        | MCF_INTC_ICRn_IL(lvl));

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

    /*
     * Unmask all FEC interrupts
     */
    MCF_FEC_EIMR(ch) = MCF_FEC_EIMR_UNMASK_ALL;

    /*
     * Unmask the FEC interrupt in the interrupt controller
     */
    if (ch == 0)
        MCF_INTC_IMRH &= ~MCF_INTC_IMRH_INT_MASK39;
    else
        MCF_INTC_IMRH &= ~MCF_INTC_IMRH_INT_MASK38;
}
/********************************************************************/
/*
 * Disable interrupts on the selected FEC
 *
 * Parameters:
 *  ch      FEC channel
 */
void
fec_irq_disable(uint8 ch)
{
    ASSERT(ch == 0 || ch == 1);

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

    /*
     * Mask the FEC interrupt in the interrupt controller
     */
    if (ch == 0)
        MCF_INTC_IMRH |= MCF_INTC_IMRH_INT_MASK39;
    else
        MCF_INTC_IMRH |= MCF_INTC_IMRH_INT_MASK38;
}
/********************************************************************/
/*
 * FEC interrupt handler
 * All interrupts are multiplexed into a single vector for each
 * FEC module. The lower level interrupt handler passes in the
 * channel to this handler. Note that the receive interrupt is
 * generated by the Multi-channel DMA FEC Rx task.
 *
 * Parameters:
 * ch       FEC channel
 */
static void
fec_irq_handler(uint8 ch)
{
    uint32 event, eir;
    
    /*
     * 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;

    if (event & MCF_FEC_EIR_RFERR)
    {
        fec_log[ch].total++;
        fec_log[ch].rferr++;
        #ifdef DEBUG
        printf("RFERR\n");
        printf("FECRFSR%d = 0x%08x\n",ch,MCF_FEC_FECRFSR(ch));
        fec_eth_stop(ch);
        #endif
    }
    if (event & MCF_FEC_EIR_XFERR)
    {
        fec_log[ch].total++;
        fec_log[ch].xferr++;
        #ifdef DEBUG
        printf("XFERR\n");
        #endif
    }
    if (event & MCF_FEC_EIR_XFUN)
    {
        fec_log[ch].total++;
        fec_log[ch].xfun++;
        #ifdef DEBUG
        printf("XFUN\n");
        fec_eth_stop(ch);
        #endif
    }
    if (event & MCF_FEC_EIR_RL)
    {
        fec_log[ch].total++;
        fec_log[ch].rl++;
        #ifdef DEBUG
        printf("RL\n");
        #endif
    }
    if (event & MCF_FEC_EIR_LC)
    {
        fec_log[ch].total++;
        fec_log[ch].lc++;
        #ifdef DEBUG
        printf("LC\n");
        #endif
    }
    if (event & MCF_FEC_EIR_MII)
    {
        fec_log[ch].mii++;
    }
    if (event & MCF_FEC_EIR_TXF)
    {
        fec_log[ch].txf++;
    }
    if (event & MCF_FEC_EIR_GRA)
    {
        fec_log[ch].gra++;
    }
    if (event & MCF_FEC_EIR_BABT)
    {
        fec_log[ch].total++;
        fec_log[ch].babt++;
        #ifdef DEBUG
        printf("BABT\n");
        #endif
    }
    if (event & MCF_FEC_EIR_BABR)
    {
        fec_log[ch].total++;
        fec_log[ch].babr++;
        #ifdef DEBUG
        printf("BABR\n");
        #endif
    }
    if (event & MCF_FEC_EIR_HBERR)
    {
        fec_log[ch].total++;
        fec_log[ch].hberr++;
        #ifdef DEBUG
        printf("HBERR\n");
        #endif
    }
}

int
fec0_interrupt_handler(void* arg1, void* arg2)
{
    (void) arg1;
    (void) arg2;
    fec_irq_handler(0);
    return 1;
}

int
fec1_interrupt_handler(void* arg1, void* arg2)
{
    (void) arg1;
    (void) arg2;
    fec_irq_handler(1);
    return 1;
}
/********************************************************************/
/*
 * Configure the selected Ethernet port and enable all operations
 *
 * Parameters:
 *  ch      FEC channel
 *  trcvr   Transceiver mode (MII, 7-Wire or internal loopback)
 *  speed   Maximum operating speed (MII only)
 *  duplex  Full or Half-duplex (MII only)
 *  mac     Physical (MAC) Address
 */
void
fec_eth_setup(uint8 ch, uint8 trcvr, uint8 speed, uint8 duplex, const uint8 *mac)
{
    ASSERT(ch == 0 || ch == 1);

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

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

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

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

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

    /*
     * Initialize and enable FEC interrupts
     */
    fec_irq_enable(ch, FEC_INTC_LVL(ch), FEC_INTC_PRI(ch));

    /*
     * Enable the multi-channel DMA tasks
     */
    fec_rx_start(ch, (int8*)fecbd_get_start(ch,Rx));
    fec_tx_start(ch, (int8*)fecbd_get_start(ch,Tx));

    /*
     * Enable the FEC channel
     */
    MCF_FEC_ECR(ch) |= MCF_FEC_ECR_ETHER_EN;
}
/********************************************************************/
/*
 * Reset the selected Ethernet port
 *
 * Parameters:
 *  ch      FEC channel
 */
void
fec_eth_reset(uint8 ch)
{
// To do
}
/********************************************************************/
/*
 * Stop the selected Ethernet port
 *
 * Parameters:
 *  ch      FEC channel
 */
void
fec_eth_stop(uint8 ch)
{
    int level;
    
    /*
     * Disable interrupts
     */
    level = asm_set_ipl(7);

    /*
     * Gracefully disable the receiver and transmitter
     */
    fec_tx_stop(ch);
    fec_rx_stop(ch);

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

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

    #ifdef DEBUG_PRINT
        nbuf_debug_dump();
        fec_log_dump(ch);
    #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 + -