📄 emac_diag.c
字号:
/***************************************************************************** Copyright Storlink Corp 2005. All rights reserved. *--------------------------------------------------------------------------* Name : emac_diag.c* Description : * Ethernet Diagnostic ** History** Date Writer Description* ----------- ----------- -------------------------------------------------* 05/25/2005 Gary Chen Implement by following the algorithm of Xi Chen*****************************************************************************/#include <define.h>#include <board_config.h>#include <sl2312.h>#ifndef MIDWAY#include "emac_sl2312.h"/************************************************************* * Global Variable *************************************************************/#undef EMAC_DIAG_ENABLE_FLOW_CTRL// #define DIAG_BY_LA 1#ifdef BOARD_DCACHE_ON typedef struct { unsigned char tx_desc_array[TX_DESC_NUM * sizeof(EMAC_DESCRIPTOR_T)] __attribute__((aligned(32))); unsigned char rx_desc_array[RX_DESC_NUM * sizeof(EMAC_DESCRIPTOR_T)] __attribute__((aligned(32))); unsigned char buffer[EMAC_BUF_SIZE] __attribute__((aligned(32))); } EMAC_NONCACHE_MEM_T; typedef struct { EMAC_NONCACHE_MEM_T buf; unsigned char free[BOARD_DRAM_NONCACHE_SIZE - sizeof(EMAC_NONCACHE_MEM_T)]; } EMAC_NONCACHE_AREA_T; EMAC_NONCACHE_MEM_T *emac_noncache_memp = (EMAC_NONCACHE_MEM_T *)BOARD_DRAM_NONCACHE_BASE; static unsigned char *tx_desc_array; static unsigned char *rx_desc_array; static unsigned char *rx_buf_array;#else static unsigned char tx_desc_array[TX_DESC_NUM * sizeof(EMAC_DESCRIPTOR_T)] __attribute__((aligned(32))); static unsigned char rx_desc_array[RX_DESC_NUM * sizeof(EMAC_DESCRIPTOR_T)] __attribute__((aligned(32))); static unsigned char rx_buf_array[EMAC_BUF_SIZE] __attribute__((aligned(32)));#endifextern EMAC_INFO_T emac_private_data;extern unsigned int full_duplex;extern unsigned int flow_control_enable;int emac_bridge_diag_mode;static EMAC_DESCRIPTOR_T null_rxbd;#define tp emac_private_data/************************************************//* function declare *//************************************************/#define emac_read_reg(offset) REG32(EMAC_BASE_ADDR + offset)#define emac_write_reg(offset, data, mask) REG32(EMAC_BASE_ADDR + offset) = \ (emac_read_reg(offset) & (~mask)) | \ (data & mask)static void emac_diag_start(void);static void emac_diag_stop(void);static void emac_diag_hw_stop(void);static void emac_diag_hw_start(void);extern void emac_enable_tx_rx(void);extern void emac_disable_tx_rx(void);static int emac_diag_init_chip(void);static void emac_diag_init_desc_buf(void);static void emac_diag_isr(void);static void emac_diag_rx_isr_begin(EMAC_INFO_T *tpp);static void emac_diag_tx_isr_begin(EMAC_INFO_T *tpp);extern int emac_clear_counter (void);extern void emac_set_phy_status(void);extern void emac_get_phy_status(void);extern char *sys_get_mac_addr(int index);/************************************************//* function body *//************************************************//*----------------------------------------------------------------------* emac_set_xi_diag_mode*----------------------------------------------------------------------*/void emac_set_xi_diag_mode(int mode){ unsigned long old_ints; char *status_msg[2]={"disabled", "enabled"}; register EMAC_INFO_T *tpp; tpp = (EMAC_INFO_T *)&emac_private_data; if (mode) { REG32(SL2312_GLOBAL_BASE + GLOBAL_RESET) = 0x20; // Reset EMAC emac_diag_start(); emac_bridge_diag_mode = 1; emac_write_reg(EMAC_RX_FLTR,0x0000001f,0x0000001f);#ifdef BOARD_DCACHE_ON if (!hal_get_dcache_status()) { HAL_DISABLE_INTERRUPTS(old_ints); HAL_DCACHE_INVALIDATE_ALL(); HAL_DCACHE_ENABLE(); HAL_RESTORE_INTERRUPTS(old_ints); }#endif printf("MMU: %s, I-CACHE: %s, D-CACHE: %s\n", status_msg[hal_get_mmu_status()], status_msg[hal_get_icache_status()], status_msg[hal_get_dcache_status()]); emac_reset_statistics();#ifndef MIDWAY REG32(SL2312_GLOBAL_BASE+GLOBAL_MISC_CTRL) |= GLOBAL_FLASH_EN_BIT; //0x00000001 ;#endif hal_register_irq_entry((void *)emac_diag_isr); hal_interrupt_unmask(SL2312_INTERRUPT_EMAC); // should be last } else { hal_interrupt_mask(SL2312_INTERRUPT_EMAC); // should be first hal_interrupt_acknowledge(SL2312_INTERRUPT_EMAC); // should be first hal_register_irq_entry(NULL); emac_bridge_diag_mode = 0;#ifdef BOARD_DCACHE_ON if (hal_get_dcache_status()) { HAL_DISABLE_INTERRUPTS(old_ints); HAL_ICACHE_INVALIDATE_ALL(); HAL_DCACHE_INVALIDATE_ALL(); HAL_DCACHE_DISABLE(); }#endif emac_write_reg(EMAC_RX_FLTR,0x00000005,0x0000001f); hal_interrupt_acknowledge(SL2312_INTERRUPT_TIMER1); // should be first hal_interrupt_unmask(SL2312_INTERRUPT_TIMER1); HAL_ENABLE_INTERRUPTS(); }}/*----------------------------------------------------------------------* emac_diag_start*----------------------------------------------------------------------*/static void emac_diag_start(void){ /* allocates tx/rx descriptor and buffer memory */ emac_diag_init_desc_buf(); /* set PHY register to start autonegition process */ emac_set_phy_status(); /* EMAC initialization */ if ( emac_diag_init_chip() ) { printf ("EMAC init fail\n"); } /* enable tx/rx register */ emac_enable_tx_rx(); /* start DMA process */ emac_diag_hw_start(); /* clear statistic counter */ emac_clear_counter(); return ;}/*----------------------------------------------------------------------* emac_diag_stop*----------------------------------------------------------------------*/static void emac_diag_stop(void){ /* stop tx/rx packet */ emac_disable_tx_rx(); /* stop the chip's Tx and Rx DMA processes */ emac_diag_hw_stop(); }/*----------------------------------------------------------------------* emac_diag_init_chip*----------------------------------------------------------------------*/static int emac_diag_init_chip(void){ EMAC_RBNR_T rbnr_val,rbnr_mask; EMAC_CONFIG2_T config2_val; EMAC_CONFIG0_T config0,config0_mask; EMAC_CONFIG1_T config1; UINT32 data; /* chip reset */ /* set RMII mode for testing */ if (full_duplex == 1) { emac_write_reg(EMAC_STATUS,0x00000017,0x0000001f); /* 100M full duplex */ } else { emac_write_reg(EMAC_STATUS,0x00000013,0x0000001f); /* 100M half duplex */ } emac_set_mac_addr(sys_get_mac_addr(0), sys_get_mac_addr(1)); /* set RX_FLTR register to receive all multicast packet */ emac_write_reg(EMAC_RX_FLTR,0x00000005,0x0000001f);// emac_write_reg(EMAC_RX_FLTR,0x00000001,0x0000001f); /* set per packet buffer size */ config1.bits32 = 0; config1.bits.buf_size = 11; /* buffer size = 2048-byte */ emac_write_reg(EMAC_CONFIG1,config1.bits32,0x0000000f); /* set flow control threshold */ config2_val.bits32 = 0; config2_val.bits.set_threshold = RX_DESC_NUM/4; config2_val.bits.rel_threshold = RX_DESC_NUM*3/4; emac_write_reg(EMAC_CONFIG2,config2_val.bits32,0xffffffff); /* init remaining buffer number register */ rbnr_val.bits32 = 0; rbnr_val.bits.buf_remain = RX_DESC_NUM; rbnr_mask.bits32 = 0; rbnr_mask.bits.buf_remain = 0xffff; emac_write_reg(EMAC_RBNR,rbnr_val.bits32,rbnr_mask.bits32); /* disable TX/RX and disable internal loop back */ config0.bits32 = 0; config0_mask.bits32 = 0; config0.bits.max_len = 2;#ifdef EMAC_DIAG_ENABLE_FLOW_CTRL config0.bits.fc_en = 1; /* enable flow control */#else config0.bits.fc_en = 0; /* disable flow control */#endif config0.bits.dis_rx = 1; /* disable rx */ config0.bits.dis_tx = 1; /* disable tx */ config0.bits.loop_back = 0; /* enable/disable EMAC loopback */ config0_mask.bits.max_len = 3; config0_mask.bits.fc_en = 1; config0_mask.bits.dis_rx = 1; config0_mask.bits.dis_tx = 1; config0_mask.bits.loop_back = 1; config0.bits.adj_ifg = 7; config0_mask.bits.adj_ifg = 0x0f; emac_write_reg(EMAC_CONFIG0,config0.bits32,config0_mask.bits32); #ifdef EMAC_DIAG_ENABLE_FLOW_CTRL flow_control_enable = 1; /* enable flow control flag */#else flow_control_enable = 0; /* disable flow control flag */#endif return (0);}/*----------------------------------------------------------------------* emac_diag_init_desc_buf*----------------------------------------------------------------------*/static void emac_diag_init_desc_buf(void){ int i; EMAC_DESCRIPTOR_T *desc; unsigned char *bufp;#ifdef BOARD_DCACHE_ON tx_desc_array = (unsigned char *)&emac_noncache_memp->tx_desc_array[0]; rx_desc_array = (unsigned char *)&emac_noncache_memp->rx_desc_array[0]; rx_buf_array = (unsigned char *)&emac_noncache_memp->buffer[0];#endif tp.tx_desc = (EMAC_DESCRIPTOR_T *)tx_desc_array; tp.rx_desc = (EMAC_DESCRIPTOR_T *)rx_desc_array; tp.bufs = rx_buf_array; /* TX descriptors initial */ tp.tx_head = 0; tp.tx_tail = 0; /* TX descriptors initial */ desc = tp.tx_desc; for (i = 0; i < TX_DESC_NUM; i++) { memset((char *)desc, 0, sizeof(*desc)); desc->frame_ctrl.bits_tx.own = CPU; /* set owner to CPU */ desc->frame_ctrl.bits_tx.buffer_size = 0; /* set tx buffer size for descriptor */ desc->buf_adr = 0; desc->next_desc.next_descriptor = (unsigned long)(desc + 1) | 0x0000000b; desc++; } desc--; desc->next_desc.next_descriptor = (unsigned long)tp.tx_desc | 0x0000000b; /* RX descriptors initial */ tp.rx_head = 0; tp.rx_tail = RX_DESC_NUM-1; desc = tp.rx_desc; for (i = 0; i < RX_DESC_NUM; i++) { memset((char *)desc, 0, sizeof(*desc)); desc->frame_ctrl.bits_rx.own = DMA; /* set owner bit to DMA */ desc->frame_ctrl.bits_rx.buffer_size = RX_BUF_SIZE; /* set rx buffer size for descriptor */ desc->buf_adr = (unsigned int)tp.bufs+i*RX_BUF_SIZE; memset(desc->buf_adr, 0, RX_BUF_SIZE); desc->next_desc.next_descriptor = (unsigned long)(desc + 1) | 0x0000000b; desc++; } desc--; memset((char *)&null_rxbd, 0, sizeof(EMAC_DESCRIPTOR_T)); // desc->next_desc.next_descriptor = (unsigned int)&null_rxbd | 0x0000000b; desc->next_desc.next_descriptor = 0x0000000b;} /*----------------------------------------------------------------------* emac_diag_hw_start*----------------------------------------------------------------------*/void emac_diag_hw_start(void){ EMAC_TXDMA_CURR_DESC_T tx_desc; EMAC_RXDMA_CURR_DESC_T rx_desc; EMAC_TXDMA_CTRL_T txdma_ctrl,txdma_ctrl_mask; EMAC_RXDMA_CTRL_T rxdma_ctrl,rxdma_ctrl_mask; EMAC_DMA_STATUS_T dma_status,dma_status_mask; /* program TxDMA Current Descriptor Address register for first descriptor */ tx_desc.bits32 = (unsigned int)(tp.tx_desc); tx_desc.bits.eofie = 1; tx_desc.bits.dec = 0; tx_desc.bits.sof_eof = 0x03; emac_write_reg(EMAC_TXDMA_CURR_DESC,tx_desc.bits32,0xffffffff); emac_write_reg(0xff2c,tx_desc.bits32,0xffffffff); /* tx next descriptor address */ /* program RxDMA Current Descriptor Address register for first descriptor */ rx_desc.bits32 = (unsigned int)(tp.rx_desc); rx_desc.bits.eofie = 1; rx_desc.bits.dec = 0; rx_desc.bits.sof_eof = 0x03; emac_write_reg(EMAC_RXDMA_CURR_DESC,rx_desc.bits32,0xffffffff); emac_write_reg(0xff3c,rx_desc.bits32,0xffffffff); /* rx next descriptor address */ /* enable EMAC interrupt & disable loopback */ dma_status.bits32 = 0; dma_status.bits.loop_back = 0; /* disable DMA loop-back mode */ dma_status.bits.m_tx_fail = 1; dma_status.bits.m_cnt_full = 0;#ifdef EMAC_DIAG_ENABLE_FLOW_CTRL dma_status.bits.m_rx_pause_on = 1; dma_status.bits.m_tx_pause_on = 1; dma_status.bits.m_rx_pause_off = 1; dma_status.bits.m_tx_pause_off = 1;#endif dma_status.bits.m_rx_overrun = 1; dma_status.bits.m_tx_underrun = 1; dma_status_mask.bits32 = 0; dma_status_mask.bits.loop_back = 1; dma_status_mask.bits.m_tx_fail = 1; dma_status_mask.bits.m_cnt_full = 1; dma_status_mask.bits.m_rx_pause_on = 1; dma_status_mask.bits.m_tx_pause_on = 1; dma_status_mask.bits.m_rx_pause_off = 1; dma_status_mask.bits.m_tx_pause_off = 1; dma_status_mask.bits.m_rx_overrun = 1; dma_status_mask.bits.m_tx_underrun = 1; emac_write_reg(EMAC_DMA_STATUS,dma_status.bits32,dma_status_mask.bits32); /* program tx dma control register */ txdma_ctrl.bits32 = 0; txdma_ctrl.bits.td_start = 0; txdma_ctrl.bits.td_continue = 0; txdma_ctrl.bits.td_chain_mode = 1; /* chain mode */ txdma_ctrl.bits.td_prot = 0; txdma_ctrl.bits.td_burst_size = 2; txdma_ctrl.bits.td_bus = 0; txdma_ctrl.bits.td_endian = 0; txdma_ctrl.bits.td_finish_en = 1; txdma_ctrl.bits.td_fail_en = 1; txdma_ctrl.bits.td_perr_en = 1; txdma_ctrl.bits.td_eod_en = 0; /* disable Tx End of Descriptor Interrupt */ txdma_ctrl.bits.td_eof_en = 1; txdma_ctrl_mask.bits32 = 0; txdma_ctrl_mask.bits.td_start = 1; txdma_ctrl_mask.bits.td_continue = 1; txdma_ctrl_mask.bits.td_chain_mode = 1; txdma_ctrl_mask.bits.td_prot = 15; txdma_ctrl_mask.bits.td_burst_size = 3;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -