📄 fec.c
字号:
* 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: * 0 success * 1 otherwise */intfec_send (int ch, uint8 *dst, uint8 *src, uint16 type, NBUF *nbuf){ FECBD *pTxBD; /* Check the length */ if ((nbuf->length + ETH_HDR_LEN) > ETH_MTU) return 1; /* * 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 */ pTxBD = fecbd_tx_alloc(ch); if (pTxBD != NULL) { /* There was an empty slot in the TxBD ring */ /* Put the buffer into the TxBD ring queue */ queue_add(&txbd_queue[ch],(QNODE *)nbuf); /* Setup the buffer descriptor for transmission */ pTxBD->data = nbuf->data; pTxBD->length = nbuf->length + ETH_HDR_LEN;// pTxBD->status = 0; pTxBD->status |= (TX_BD_R | TX_BD_L); /* Continue the Tx DMA task (in case it was waiting for a new TxBD) */ fec_tx_continue(ch); } else { /* The TxBD ring was full */ /* Add this packet to the send holding queue */ queue_add(&send_queue[ch],(QNODE *)nbuf); } return 0;}/********************************************************************//* * Enable interrupts on the selected FEC * * Parameters: * ch FEC channel * pri Interrupt Priority * lvl Interrupt Level */voidfec_irq_enable(int ch){ int fec_vbase, vector; void fec0_irq_handler(void); void fec1_irq_handler(void); if (ch == 0) fec_vbase = 64 + 23; else if (ch == 1) fec_vbase = 64 + 49; for (vector = fec_vbase; vector <= fec_vbase + 13; vector++) { if (ch == 0) { /* Put the handler in the vector table */ mcf5xxx_set_handler(vector, (ADDRESS)fec0_irq_handler); } else if (ch == 1) { /* Put the handler in the vector table */ mcf5xxx_set_handler(vector, (ADDRESS)fec1_irq_handler); } } /* Enable FEC interrupts to the ColdFire core * Setup each ICR with a unique interrupt level combination */ fec_vbase -= 64; /* FEC Rx Frame */ MCF_INTC0_ICR(fec_vbase+4) = MCF_INTC_ICR_IL(INTC_LVL_FEC); /* FEC Rx Buffer */ MCF_INTC0_ICR(fec_vbase+5) = MCF_INTC_ICR_IL(INTC_LVL_FEC); /* FEC Tx Frame */ MCF_INTC0_ICR(fec_vbase+0) = MCF_INTC_ICR_IL(INTC_LVL_FEC); /* FEC Tx Buffer */ MCF_INTC0_ICR(fec_vbase+1) = MCF_INTC_ICR_IL(INTC_LVL_FEC); /* FEC FIFO Underrun */ MCF_INTC0_ICR(fec_vbase+2) = MCF_INTC_ICR_IL(INTC_LVL_FEC+1); /* FEC Collision Retry Limit */ MCF_INTC0_ICR(fec_vbase+3) = MCF_INTC_ICR_IL(INTC_LVL_FEC+1); /* FEC MII */ //MCF_INTC0_ICR(fec_vbase+6) = MCF_INTC_ICR_IL(INTC_LVL_FEC(ch)); /* FEC Late Collision */ MCF_INTC0_ICR(fec_vbase+7) = MCF_INTC_ICR_IL(INTC_LVL_FEC+1); /* FEC Heartbeat Error */ MCF_INTC0_ICR(fec_vbase+8) = MCF_INTC_ICR_IL(INTC_LVL_FEC+1); /* FEC Graceful Stop Comlete */ MCF_INTC0_ICR(fec_vbase+9) = MCF_INTC_ICR_IL(INTC_LVL_FEC+1); /* FEC Bus Error */ MCF_INTC0_ICR(fec_vbase+10) = MCF_INTC_ICR_IL(INTC_LVL_FEC+1); /* FEC Babbling Transmit */ MCF_INTC0_ICR(fec_vbase+11) = MCF_INTC_ICR_IL(INTC_LVL_FEC+1); /* FEC Babbling Receive */ MCF_INTC0_ICR(fec_vbase+12) = MCF_INTC_ICR_IL(INTC_LVL_FEC+1); /* Enable the FEC interrupts in the mask register */ if (ch == 0) { MCF_INTC0_IMRH &= ~(MCF_INTC_IMRH_INT_MASK32 | MCF_INTC_IMRH_INT_MASK33 | MCF_INTC_IMRH_INT_MASK34 | MCF_INTC_IMRH_INT_MASK35 ); MCF_INTC0_IMRL &= ~(MCF_INTC_IMRL_INT_MASK23 | MCF_INTC_IMRL_INT_MASK24 | MCF_INTC_IMRL_INT_MASK25 | MCF_INTC_IMRL_INT_MASK26 | MCF_INTC_IMRL_INT_MASK27 | MCF_INTC_IMRL_INT_MASK28 | MCF_INTC_IMRL_INT_MASK29 | MCF_INTC_IMRL_INT_MASK30 | MCF_INTC_IMRL_INT_MASK31 | MCF_INTC_IMRL_MASKALL); } else if (ch == 1) MCF_INTC0_IMRH &= ~(MCF_INTC_IMRH_INT_MASK49 | MCF_INTC_IMRH_INT_MASK50 | MCF_INTC_IMRH_INT_MASK51 | MCF_INTC_IMRH_INT_MASK52 | MCF_INTC_IMRH_INT_MASK53 | MCF_INTC_IMRH_INT_MASK54 | MCF_INTC_IMRH_INT_MASK55 | MCF_INTC_IMRH_INT_MASK56 | MCF_INTC_IMRH_INT_MASK57 | MCF_INTC_IMRH_INT_MASK58 | MCF_INTC_IMRH_INT_MASK59 | MCF_INTC_IMRH_INT_MASK60 | MCF_INTC_IMRH_INT_MASK61); /* 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 on the selected FEC * * Parameters: * ch FEC channel */voidfec_irq_disable(int ch){ int vector, fec_vbase; fec_vbase = 64 + 23; for (vector = fec_vbase; vector <= fec_vbase + 13; vector++) { /* Disable interrupts to the ColdFire core */ MCF_INTC0_ICR(vector - 64) = 0; } /* Mask all FEC interrupts */ MCF_FEC_EIMR = MCF_FEC_EIMR_MASK_ALL; /* Mask the FEC interrupt in the interrupt controller */ if (ch == 0) { MCF_INTC0_IMRH |= 0 | MCF_INTC_IMRH_INT_MASK32 | MCF_INTC_IMRH_INT_MASK33 | MCF_INTC_IMRH_INT_MASK34 | MCF_INTC_IMRH_INT_MASK35; MCF_INTC0_IMRL |= 0 | MCF_INTC_IMRL_INT_MASK23 | MCF_INTC_IMRL_INT_MASK24 | MCF_INTC_IMRL_INT_MASK25 | MCF_INTC_IMRL_INT_MASK26 | MCF_INTC_IMRL_INT_MASK27 | MCF_INTC_IMRL_INT_MASK28 | MCF_INTC_IMRL_INT_MASK29 | MCF_INTC_IMRL_INT_MASK30 | MCF_INTC_IMRL_INT_MASK31; } }/********************************************************************//* * FEC interrupt handler * * Parameters: * nif NIF structure */static voidfec_irq_handler(NIF* nif){ uint32 event, eir; /* 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_PRINT 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[nif->ch].errors++; fec_log[nif->ch].un++; #ifdef DEBUG printf("FEC Tx FIFO Underflow\n"); #endif } if (event & MCF_FEC_EIR_RL) { fec_log[nif->ch].errors++; fec_log[nif->ch].rl++; #ifdef DEBUG printf("FEC Collision Retry Limit\n"); #endif //fec_resend(nif->ch); } if (event & MCF_FEC_EIR_LC) { fec_log[nif->ch].errors++; fec_log[nif->ch].lc++; #ifdef DEBUG printf("FEC Late Collision\n"); #endif //fec_resend(nif->ch); } if (event & MCF_FEC_EIR_EBERR) { fec_log[nif->ch].errors++; fec_log[nif->ch].eberr++; #ifdef DEBUG printf("FEC/DMA fatal bus error!\n"); #endif fec_eth_stop(nif->ch); } if (event & MCF_FEC_EIR_MII) { fec_log[nif->ch].mii++; } if (event & MCF_FEC_EIR_RXB || event & MCF_FEC_EIR_RXF) { fec_rx_handler(nif); } if (event & MCF_FEC_EIR_TXB || event & MCF_FEC_EIR_TXF) { fec_tx_handler(nif, event); } if (event & MCF_FEC_EIR_GRA) { fec_log[nif->ch].gra++; } if (event & MCF_FEC_EIR_BABT) { fec_log[nif->ch].errors++; fec_log[nif->ch].babt++; #ifdef DEBUG printf("FEC Babbling transmit error\n"); #endif } if (event & MCF_FEC_EIR_BABR) { fec_log[nif->ch].errors++; fec_log[nif->ch].babr++; #ifdef DEBUG printf("FEC Babbling receive error\n"); #endif } if (event & MCF_FEC_EIR_HBERR) { fec_log[nif->ch].errors++; fec_log[nif->ch].hberr++; #ifdef DEBUG printf("HBERR\n"); #endif }}__interrupt__void fec0_irq_handler(void){ fec_irq_handler(&nif[0]);}__interrupt__static void fec1_irq_handler(void){ fec_irq_handler(&nif[1]);}/********************************************************************//* * Configure the selected Ethernet port and enable all operations * * Parameters: * cfg FEC configuration structure * sys_clk System clock frequency - used for MII speed calculation * * Return Value: * 0 if the Ethernet was successfully started * non-zero otherwise */intfec_eth_start(FEC_CONFIG *cfg, int sys_clk){ int status; /* Disable FEC interrupts */ fec_irq_disable(cfg->ch); /* Initialize the event log */ fec_log_init(cfg->ch); /* Initialize the buffer descriptor ring */ status = fecbd_init(cfg->ch, cfg->nrxbd, cfg->ntxbd); if (status) { #ifdef DEBUG_PRINT printf("\nfecbd_init() failed with status code %d: ",status); if (status == ERR_MALLOC) printf("ERR_MALLOC\n"); else if (status == ERR_NBUFALLOC) printf("ERR_NBUFALLOC\n"); #endif return -1; } /* Initialize the PHY interface */ if ((cfg->mode == FEC_MODE_MII || cfg->mode == FEC_MODE_RMII) && cfg->initphy == YES) { fec_mii_init(cfg->ch, sys_clk); if (eth_phy_autoneg(cfg->phyaddr, cfg->speed, cfg->duplex)) { #ifdef DEBUG_PRINT printf("eth_phy_autoneg() failed\n"); #endif fecbd_flush(cfg->ch); return -1; } } /* Initialize the FEC */ fec_reset(cfg->ch); fec_init(cfg->ch, cfg->mode, cfg->duplex, cfg->prom, cfg->mac); fec_mib_init(cfg->ch); /* Initialize and enable FEC interrupts */ fec_irq_enable(cfg->ch);/* MCF_SCM_MPR |= 0 | MCF_SCM_MPR_MPROT2(7) | MCF_SCM_MPR_MPROT3(7);*/// MCF_SCM_MPR = MCF_SCM_MPR_MPR(1); /* Enable the FEC channel */ MCF_FEC_ECR |= MCF_FEC_ECR_ETHER_EN; /* Start the Rx FEC DMA */ //fec_rx_continue(cfg->ch); return 0;}/********************************************************************//* * Stop the selected Ethernet port * * Parameters: * ch FEC channel */voidfec_eth_stop(int ch){ int level; /* Disable interrupts */ level = asm_set_ipl(7); /* Gracefully disable the transmitter */ fec_tx_stop(ch); /* Disable FEC interrupts */ fec_irq_disable(ch); /* Disable the FEC channel */ MCF_FEC_ECR &= ~MCF_FEC_ECR_ETHER_EN; /* Clean up the BDs and buffer queues */ fecbd_flush(ch); /* Restore interrupt level */ asm_set_ipl(level);}/********************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -