📄 fec.c
字号:
/* * File: fec.c * Purpose: Driver for the Fast Ethernet Controller (FEC) * * Notes: */#include "common.h"#include "fec.h"/********************************************************************//* * Log of FEC events */FEC_EVENT_LOG fec_log[2];/* * Queues for FEC buffers */QUEUE txbd_queue[2];QUEUE rxbd_queue[2];QUEUE send_queue[2];/********************************************************************//* * Write a value to a PHY's MII register. * * Parameters: * ch FEC channel * phy_addr Address of the PHY. * reg_addr Address of the register in the PHY. * data Data to be written to the PHY register. * * Return Values: * 0 on failure * 1 on success. * * Please refer to your PHY manual for registers and their meanings. * mii_write() polls for the FEC's MII interrupt event and clears it. * If after a suitable amount of time the event isn't triggered, a * value of 0 is returned. */intfec_mii_write(int ch, int phy_addr, int reg_addr, int data){ int timeout; uint32 eimr; /* Clear the MII interrupt bit */ MCF_FEC_EIR = MCF_FEC_EIR_MII; /* Mask the MII interrupt */ eimr = MCF_FEC_EIMR; MCF_FEC_EIMR &= ~MCF_FEC_EIMR_MII; /* Write to the MII Management Frame Register to kick-off the MII write */ MCF_FEC_MMFR = 0 | MCF_FEC_MMFR_ST_01 | MCF_FEC_MMFR_OP_WRITE | MCF_FEC_MMFR_PA(phy_addr) | MCF_FEC_MMFR_RA(reg_addr) | MCF_FEC_MMFR_TA_10 | MCF_FEC_MMFR_DATA(data); /* Poll for the MII interrupt (interrupt should be masked) */ for (timeout = 0; timeout < MII_TIMEOUT; timeout++) { if (MCF_FEC_EIR & MCF_FEC_EIR_MII) break; } if(timeout == MII_TIMEOUT) return 0; /* Clear the MII interrupt bit */ MCF_FEC_EIR = MCF_FEC_EIR_MII; /* Restore the EIMR */ MCF_FEC_EIMR = eimr; return 1;}/********************************************************************//* * Read a value from a PHY's MII register. * * Parameters: * ch FEC channel * phy_addr Address of the PHY. * reg_addr Address of the register in the PHY. * data Pointer to storage for the Data to be read * from the PHY register (passed by reference) * * Return Values: * 0 on failure * 1 on success. * * Please refer to your PHY manual for registers and their meanings. * mii_read() polls for the FEC's MII interrupt event and clears it. * If after a suitable amount of time the event isn't triggered, a * value of 0 is returned. */intfec_mii_read(int ch, int phy_addr, int reg_addr, uint16* data){ int timeout; uint32 eimr; /* Clear the MII interrupt bit */ MCF_FEC_EIR = MCF_FEC_EIR_MII; /* Mask the MII interrupt */ eimr = MCF_FEC_EIMR; MCF_FEC_EIMR &= ~MCF_FEC_EIMR_MII; /* Write to the MII Management Frame Register to kick-off the MII read */ MCF_FEC_MMFR = 0 | MCF_FEC_MMFR_ST_01 | MCF_FEC_MMFR_OP_READ | MCF_FEC_MMFR_PA(phy_addr) | MCF_FEC_MMFR_RA(reg_addr) | MCF_FEC_MMFR_TA_10; /* Poll for the MII interrupt (interrupt should be masked) */ for (timeout = 0; timeout < MII_TIMEOUT; timeout++) { if (MCF_FEC_EIR & MCF_FEC_EIR_MII) break; } if(timeout == MII_TIMEOUT) return 0; /* Clear the MII interrupt bit */ MCF_FEC_EIR = MCF_FEC_EIR_MII; /* Restore the EIMR */ MCF_FEC_EIMR = eimr; *data = (uint16)(MCF_FEC_MMFR & 0x0000FFFF); return 1;}/********************************************************************//* * Initialize the MII interface controller * * Parameters: * ch FEC channel * sys_clk System Clock Frequency (in MHz) */voidfec_mii_init(int ch, int sys_clk){ /* * Initialize the MII clock (EMDC) frequency * * Desired MII clock is 2.5MHz * MII Speed Setting = System_Clock / (2.5MHz * 2) * (plus 1 to make sure we round up) */ MCF_FEC_MSCR = MCF_FEC_MSCR_MII_SPEED((sys_clk/5)+1); /* * Make sure the external interface signals are enabled */ MCF_GPIO_PNQPAR = MCF_GPIO_PNQPAR_IRQ3_FEC_MDIO | MCF_GPIO_PNQPAR_IRQ5_FEC_MDC;}/********************************************************************//* Initialize the MIB counters * * Parameters: * ch FEC channel */voidfec_mib_init(int ch){//To do MCF_FEC_MIBC |= MCF_FEC_MIBC_MIB_DISABLE; MCF_FEC_RMON_T_DROP = MCF_FEC_RMON_T_PACKETS = MCF_FEC_RMON_T_BC_PKT = MCF_FEC_RMON_T_MC_PKT = MCF_FEC_RMON_T_CRC_ALIGN = MCF_FEC_RMON_T_UNDERSIZE = MCF_FEC_RMON_T_OVERSIZE = MCF_FEC_RMON_T_FRAG = MCF_FEC_RMON_T_JAB = MCF_FEC_RMON_T_COL = MCF_FEC_RMON_T_P64 = MCF_FEC_RMON_T_P65TO127 = MCF_FEC_RMON_T_P128TO255 = MCF_FEC_RMON_T_P256TO511 = MCF_FEC_RMON_T_P512TO1023 = MCF_FEC_RMON_T_P1024TO2047 = MCF_FEC_RMON_T_P_GTE2048 = MCF_FEC_RMON_T_OCTETS = MCF_FEC_IEEE_T_DROP = MCF_FEC_IEEE_T_FRAME_OK = MCF_FEC_IEEE_T_1COL = MCF_FEC_IEEE_T_MCOL = MCF_FEC_IEEE_T_DEF = MCF_FEC_IEEE_T_LCOL = MCF_FEC_IEEE_T_EXCOL = MCF_FEC_IEEE_T_MACERR = MCF_FEC_IEEE_T_CSERR = MCF_FEC_IEEE_T_SQE = MCF_FEC_IEEE_T_FDXFC = MCF_FEC_IEEE_T_OCTETS_OK = MCF_FEC_RMON_R_PACKETS = MCF_FEC_RMON_R_BC_PKT = MCF_FEC_RMON_R_MC_PKT = MCF_FEC_RMON_R_CRC_ALIGN = MCF_FEC_RMON_R_UNDERSIZE = MCF_FEC_RMON_R_OVERSIZE = MCF_FEC_RMON_R_FRAG = MCF_FEC_RMON_R_JAB = MCF_FEC_RMON_R_RESVD_0 = MCF_FEC_RMON_R_P64 = MCF_FEC_RMON_R_P65TO127 = MCF_FEC_RMON_R_P128TO255 = MCF_FEC_RMON_R_P256TO511 = MCF_FEC_RMON_R_P512TO1023 = MCF_FEC_RMON_R_P1024TO2047 = MCF_FEC_RMON_R_P_GTE2048 = MCF_FEC_RMON_R_OCTETS = MCF_FEC_IEEE_R_DROP = MCF_FEC_IEEE_R_FRAME_OK = MCF_FEC_IEEE_R_CRC = MCF_FEC_IEEE_R_ALIGN = MCF_FEC_IEEE_R_MACERR = MCF_FEC_IEEE_R_FDXFC = MCF_FEC_IEEE_R_OCTETS_OK = 0; MCF_FEC_MIBC &= ~MCF_FEC_MIBC_MIB_DISABLE;}/********************************************************************//* Display the MIB counters * * Parameters: * ch FEC channel */voidfec_mib_dump(int ch){//To do printf("\n MIB%d RMON Counters\n---------------\n",ch); printf("MCF_FEC_RMON_T_DROP: %4d\n",MCF_FEC_RMON_T_DROP); printf("MCF_FEC_RMON_T_PACKETS: %4d\n",MCF_FEC_RMON_T_PACKETS); printf("MCF_FEC_RMON_T_BC_PKT: %4d\n",MCF_FEC_RMON_T_BC_PKT); printf("MCF_FEC_RMON_T_MC_PKT: %4d\n",MCF_FEC_RMON_T_MC_PKT); printf("MCF_FEC_RMON_T_CRC_ALIGN: %4d\n",MCF_FEC_RMON_T_CRC_ALIGN); printf("MCF_FEC_RMON_T_UNDERSIZE: %4d\n",MCF_FEC_RMON_T_UNDERSIZE); printf("MCF_FEC_RMON_T_OVERSIZE: %4d\n",MCF_FEC_RMON_T_OVERSIZE); printf("MCF_FEC_RMON_T_FRAG: %4d\n",MCF_FEC_RMON_T_FRAG); printf("MCF_FEC_RMON_T_JAB: %4d\n",MCF_FEC_RMON_T_JAB); printf("MCF_FEC_RMON_T_COL: %4d\n",MCF_FEC_RMON_T_COL); printf("MCF_FEC_RMON_T_P64: %4d\n",MCF_FEC_RMON_T_P64); printf("MCF_FEC_RMON_T_P65TO127: %4d\n",MCF_FEC_RMON_T_P65TO127); printf("MCF_FEC_RMON_T_P128TO255: %4d\n",MCF_FEC_RMON_T_P128TO255); printf("MCF_FEC_RMON_T_P256TO511: %4d\n",MCF_FEC_RMON_T_P256TO511); printf("MCF_FEC_RMON_T_P512TO1023: %4d\n",MCF_FEC_RMON_T_P512TO1023); printf("MCF_FEC_RMON_T_P1024TO2047: %4d\n",MCF_FEC_RMON_T_P1024TO2047); printf("MCF_FEC_RMON_T_P_GTE2048: %4d\n",MCF_FEC_RMON_T_P_GTE2048); printf("MCF_FEC_RMON_T_OCTETS: %4d\n",MCF_FEC_RMON_T_OCTETS); printf("MCF_FEC_RMON_R_PACKETS: %4d\n",MCF_FEC_RMON_R_PACKETS); printf("MCF_FEC_RMON_R_BC_PKT: %4d\n",MCF_FEC_RMON_R_BC_PKT); printf("---------------\n\n");}/********************************************************************//* Initialize the FEC log * * Parameters: * ch FEC channel */voidfec_log_init(int ch){ memset(&fec_log[ch],0,sizeof(FEC_EVENT_LOG));}/********************************************************************//* Display the FEC log * * Parameters: * ch FEC channel */voidfec_log_dump(int ch){ // #ifdef DEBUG_PRINT printf("\n FEC%d Log\n---------------\n",ch); printf("Errors: %4d\n",fec_log[ch].errors); printf("hberr: %4d\n",fec_log[ch].hberr); printf("babr: %4d\n",fec_log[ch].babr); printf("babt: %4d\n",fec_log[ch].babt); printf("gra: %4d\n",fec_log[ch].gra); printf("txf: %4d\n",fec_log[ch].txf); printf("rxf: %4d\n",fec_log[ch].rxf); printf("mii: %4d\n",fec_log[ch].mii); printf("lc: %4d\n",fec_log[ch].lc); printf("rl: %4d\n",fec_log[ch].rl); printf("\nRFSW:\n"); printf("inv: %4d\n",fec_log[ch].rfsw_inv); printf("m: %4d\n",fec_log[ch].rfsw_m); printf("bc: %4d\n",fec_log[ch].rfsw_bc); printf("mc: %4d\n",fec_log[ch].rfsw_mc); printf("lg: %4d\n",fec_log[ch].rfsw_lg); printf("no: %4d\n",fec_log[ch].rfsw_no); printf("cr: %4d\n",fec_log[ch].rfsw_cr); printf("ov: %4d\n",fec_log[ch].rfsw_ov); printf("tr: %4d\n",fec_log[ch].rfsw_tr); // printf("---------------\n\n"); // #endif}/********************************************************************//* * Display some of the registers for debugging * * Parameters: * ch FEC channel */voidfec_reg_dump(int ch){ #ifdef DEBUG_PRINT printf("\n------------- FEC%d -------------\n",ch); printf("to be completed...\n"); printf("--------------------------------\n\n"); #endif}/********************************************************************//* * Set the duplex on the selected FEC controller * * Parameters: * ch FEC channel * duplex FEC_MII_FULL_DUPLEX or FEC_MII_HALF_DUPLEX */voidfec_duplex (int ch, MII_DUPLEX duplex){ switch (duplex) { case MII_HDX: MCF_FEC_RCR |= MCF_FEC_RCR_DRT; MCF_FEC_TCR &= (uint32)~MCF_FEC_TCR_FDEN; break; case MII_FDX: default: MCF_FEC_RCR &= (uint32)~MCF_FEC_RCR_DRT; MCF_FEC_TCR |= MCF_FEC_TCR_FDEN; break; }}/********************************************************************//* * Set the speed on the selected FEC controller * * Parameters: * ch FEC channel * speed MII_10BASE_T or MII_100BASE_TX */voidfec_rmii_speed (int ch, MII_SPEED speed){ switch (speed) { case MII_10BASE_T: MCF_FEC_RCR |= MCF_FEC_RCR_MII_MODE; break; case MII_100BASE_TX: default: break; }}/********************************************************************//* * Generate the hash table settings for the given address * * Parameters: * addr 48-bit (6 byte) Address to generate the hash for * * Return Value: * The 6 most significant bits of the 32-bit CRC result */uint8fec_hash_address(const uint8* addr){ uint32 crc; uint8 byte; int i, j; crc = 0xFFFFFFFF; for(i=0; i<6; ++i) { byte = addr[i]; for(j=0; j<8; ++j) { if((byte & 0x01)^(crc & 0x01)) { crc >>= 1; crc = crc ^ 0xEDB88320; } else crc >>= 1; byte >>= 1; } } return (uint8)(crc >> 26);}/********************************************************************//* * Set the Physical (Hardware) Address and the Individual Address * Hash in the selected FEC * * Parameters: * ch FEC channel * pa Physical (Hardware) Address for the selected FEC */voidfec_set_address (int ch, const uint8 *pa){ uint8 crc; /* * Set the Physical Address
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -