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

📄 emac_sl2312.c

📁 某个ARM9板子的实际bootloader 对裁剪
💻 C
📖 第 1 页 / 共 2 页
字号:
/***************************************************************************** Copyright  Storlink Corp 2005.  All rights reserved.                *--------------------------------------------------------------------------* Name			: emac_sl2312.c* Description	: *		Ethernet device driver for Storlink SL2312 Chip** History**	Date		Writer		Description*	-----------	-----------	-------------------------------------------------*	04/25/2005	Gary Chen	Create and implement from Jason's Redboot code*****************************************************************************/#include <define.h>#include <board_config.h>#include <sl2312.h>#ifndef MIDWAY#include "emac_sl2312.h"#define diag_printf			printf    unsigned int FLAG_SWITCH = 0;	/* if 1-->switch chip presented. if 0-->switch chip unpresented */int vlan_enabled = 0;/************************************************************* *         Global Variable *************************************************************/EMAC_INFO_T emac_private_data;//static unsigned int     tx_free_desc = TX_DESC_NUM;static unsigned int     flow_control_enable = 0;//static unsigned int     tx_desc_virtual_base = 0;//static unsigned int     rx_desc_virtual_base = 0;//static unsigned int     tx_buf_virtual_base = 0;//static unsigned int     rx_buf_virtual_base = 0;unsigned int     		full_duplex = 1;unsigned int			chip_id=0;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    tx_buf_array[TX_BUF_TOT_LEN] __attribute__((aligned(32)));static unsigned char    rx_buf_array[RX_BUF_TOT_LEN] __attribute__((aligned(32)));/************************************************//*                 function declare             *//************************************************/void emac_set_mac_addr(unsigned char *mac1, unsigned char *mac2);void emac_enable_tx_rx(void);void emac_disable_tx_rx(void);extern void emac_set_phy_status(void);extern void emac_get_phy_status(void);extern char *sys_get_mac_addr(int index);/****************************************//*	SPI Function Declare		*//****************************************/extern void SPI_default(int vlan_enabled);extern unsigned int SPI_get_identifier(void);extern void enet_get_mac_addr(unsigned char* mac);/****************************************//*	VLAN Function Declare		        *//****************************************//************************************************//*                 function body                *//************************************************/#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 int emac_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;    config0.bits.fc_en = 0; /* enable flow control */    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;    emac_write_reg(EMAC_CONFIG0,config0.bits32,config0_mask.bits32);    	flow_control_enable = 0; /* disable flow control flag */	return (0);}void emac_enable_tx_rx(void){	EMAC_CONFIG0_T	config0,config0_mask;    /* enable TX/RX */    config0.bits32 = 0;    config0_mask.bits32 = 0;    config0.bits.dis_rx = 0;  /* enable rx */    config0.bits.dis_tx = 0;  /* enable tx */    config0_mask.bits.dis_rx = 1;    config0_mask.bits.dis_tx = 1;    emac_write_reg(EMAC_CONFIG0,config0.bits32,config0_mask.bits32);    }void emac_disable_tx_rx(void){	EMAC_CONFIG0_T	config0,config0_mask;    /* enable TX/RX */    config0.bits32 = 0;    config0_mask.bits32 = 0;    config0.bits.dis_rx = 1;  /* disable rx */    config0.bits.dis_tx = 1;  /* disable tx */    config0_mask.bits.dis_rx = 1;    config0_mask.bits.dis_tx = 1;    emac_write_reg(EMAC_CONFIG0,config0.bits32,config0_mask.bits32);    }    #if 0static void emac_tx_interrupt(void){	EMAC_INFO_T     		*tp = (EMAC_INFO_T *)&emac_private_data;    EMAC_DESCRIPTOR_T	    *tx_hw_complete_desc;    unsigned int desc_cnt=0;    unsigned int i;	/* get tx H/W completed descriptor virtual address */	tx_hw_complete_desc = (EMAC_DESCRIPTOR_T *)(emac_read_reg(EMAC_TXDMA_CURR_DESC) & 0xfffffff0);	/* check tx status and accumulate tx statistics */    for (;;)    {        if (tp->tx_finished_desc == tx_hw_complete_desc)   /* complete tx processing */         {            break;        }        	if (tp->tx_finished_desc->frame_ctrl.bits_tx.own == CPU)    	{    	    if ( (tp->tx_finished_desc->frame_ctrl.bits_tx.derr) ||    	         (tp->tx_finished_desc->frame_ctrl.bits_tx.perr) )    	    {    	        diag_printf("emac_tx_interrupt::Descriptor Processing Error !!!\n");    	    }    	                          if (tp->tx_finished_desc->frame_ctrl.bits_tx.success_tx == 1)            {//                tp->stats.tx_bytes += tp->tx_finished_desc->flag_status.bits_tx_flag.frame_count;//                tp->stats.tx_packets ++;            }            else            {//                tp->stats.tx_errors++;            }            desc_cnt = tp->tx_finished_desc->frame_ctrl.bits_tx.desc_count;        	for (i=1; i<desc_cnt; i++)  /* multi_descriptor */        	{        	    /* release Tx descriptor to CPU */                tp->tx_finished_desc = (EMAC_DESCRIPTOR_T *)((tp->tx_finished_desc->next_desc.next_descriptor & 0xfffffff0));                tp->tx_finished_desc->frame_ctrl.bits_tx.own = CPU;         	}            tp->tx_finished_desc = (EMAC_DESCRIPTOR_T *)((tp->tx_finished_desc->next_desc.next_descriptor & 0xfffffff0));     	}    }//    REG32(SL2312_GLOBAL_BASE+GLOBAL_MISC_CTRL) &= ~GLOBAL_PFLASH_EN_BIT;//~0x00000001;    	    }	#endifstatic void emac_weird_interrupt(void){}void sl2312_emac_deliver(void){	EMAC_INFO_T 			*tp = (EMAC_INFO_T *)&emac_private_data;    EMAC_DESCRIPTOR_T   	*rx_desc;	unsigned int 			pkt_len;	unsigned int        	own;	unsigned int        	desc_count;	EMAC_RXDMA_FIRST_DESC_T	rxdma_busy;    own = tp->rx_cur_desc->frame_ctrl.bits32 >> 31;    if (own == CPU) /* check owner bit */    {        rx_desc = tp->rx_cur_desc;        /* check error interrupt */        if ( (rx_desc->frame_ctrl.bits_rx.derr==1)||(rx_desc->frame_ctrl.bits_rx.perr==1) )        {	        diag_printf("emac_rx_interrupt::Rx Descriptor Processing Error !!!\n");	    }	    	    /* get frame information from the first descriptor of the frame */        pkt_len = rx_desc->flag_status.bits_rx_status.frame_count-4;  /*total byte count in a frame*/		desc_count = rx_desc->frame_ctrl.bits_rx.desc_count; /* get descriptor count per frame */		if ((pkt_len > 0) && (rx_desc->frame_ctrl.bits_rx.frame_state == 0x000)) /* good frame */		{            // (sc->funs->eth_drv->recv)(sc, pkt_len);            // queue it            tp->rx_pkts++;            enet_input(rx_desc->buf_adr, pkt_len);		}	    	    rx_desc->frame_ctrl.bits_rx.own = DMA; /* release rx descriptor to DMA */        /* point to next rx descriptor */                     tp->rx_cur_desc = (EMAC_DESCRIPTOR_T *)(tp->rx_cur_desc->next_desc.next_descriptor & 0xfffffff0); 		        /* release buffer to Remaining Buffer Number Register */        if (flow_control_enable ==1)        {            emac_write_reg(EMAC_BNCR, desc_count, 0x0000ffff);        }	}        /* if RX DMA process is stoped , restart it */    	rxdma_busy.bits.rd_first_des_ptr = emac_read_reg(EMAC_RXDMA_FIRST_DESC);	if (rxdma_busy.bits.rd_busy == 0)	{    	EMAC_RXDMA_CTRL_T rxdma_ctrl,rxdma_ctrl_mask;	    rxdma_ctrl.bits32 = 0;    	rxdma_ctrl.bits.rd_start = 1;    /* start RX DMA transfer */	    rxdma_ctrl.bits.rd_continue = 1; /* continue RX DMA operation */	    rxdma_ctrl_mask.bits32 = 0;    	rxdma_ctrl_mask.bits.rd_start = 1;   	    rxdma_ctrl_mask.bits.rd_continue = 1; 	    emac_write_reg(EMAC_RXDMA_CTRL,rxdma_ctrl.bits32,rxdma_ctrl_mask.bits32);    }}/* The interrupt handler does all of the Rx thread work and cleans up   after the Tx thread. *///static void emac_interrupt (int irq, void *dev_instance, struct pt_regs *regs)void emac_sl2312_poll(void){	EMAC_RXDMA_FIRST_DESC_T	rxdma_busy;	EMAC_TXDMA_FIRST_DESC_T	txdma_busy;    EMAC_TXDMA_CTRL_T       txdma_ctrl,txdma_ctrl_mask;    EMAC_RXDMA_CTRL_T       rxdma_ctrl,rxdma_ctrl_mask;	EMAC_DMA_STATUS_T	    status;		    // for (;;)    {        /* read DMA status */	    status.bits32 = emac_read_reg(EMAC_DMA_STATUS);	    /* clear DMA status */        emac_write_reg(EMAC_DMA_STATUS,status.bits32,status.bits32);	                if ((status.bits32 & 0xffffc000)==0)        {            // break;            return;        }            	    if (status.bits.rx_overrun == 1)	    {	    	emac_private_data.rx_overrun++;            /* if RX DMA process is stoped , restart it */    	        rxdma_busy.bits32 = emac_read_reg(EMAC_RXDMA_FIRST_DESC) ;	        if (rxdma_busy.bits.rd_busy == 0)	        {	            /* restart Rx DMA process */    	        rxdma_ctrl.bits32 = 0;    	        rxdma_ctrl.bits.rd_start = 1;    /* start RX DMA transfer */	            rxdma_ctrl.bits.rd_continue = 1; /* continue RX DMA operation */	            rxdma_ctrl_mask.bits32 = 0;    	        rxdma_ctrl_mask.bits.rd_start = 1;   	            rxdma_ctrl_mask.bits.rd_continue = 1; 	            emac_write_reg(EMAC_RXDMA_CTRL,rxdma_ctrl.bits32,rxdma_ctrl_mask.bits32);            }	    }	    if (status.bits.tx_underrun == 1)	    {            /* if TX DMA process is stoped , restart it */            emac_private_data.tx_underrun++;	        txdma_busy.bits32 = emac_read_reg(EMAC_TXDMA_FIRST_DESC);	        if (txdma_busy.bits.td_busy == 0)	        {		        /* restart Tx DMA process */		        txdma_ctrl.bits32 = 0;		        txdma_ctrl.bits.td_start = 1;		        txdma_ctrl.bits.td_continue = 1;		        txdma_ctrl_mask.bits32 = 0;		        txdma_ctrl_mask.bits.td_start = 1;		        txdma_ctrl_mask.bits.td_continue = 1;		        emac_write_reg(EMAC_TXDMA_CTRL,txdma_ctrl.bits32,txdma_ctrl_mask.bits32);	        }	    }	            /* receive rx interrupt */    	if ( ((status.bits.rs_eofi==1)||(status.bits.rs_finish==1))||    	     ((status.bits.ts_eofi==1)||(status.bits.ts_finish==1)) )    	{//    		emac_rx_interrupt(dev);             sl2312_emac_deliver();	        }                /* receive tx interrupt *///    	if ( ((status.bits.ts_eofi==1)||(status.bits.ts_finish==1)) )//    	{//    		emac_tx_interrupt(dev);//    	}    	    	/* check uncommon events */	        if ((status.bits32 & 0x633fc000)!=0)        {            emac_weird_interrupt();        }    	}		return;}static void emac_hw_start(void){	EMAC_INFO_T     		*tp = (EMAC_INFO_T *)&emac_private_data;	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_dma);	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_dma);	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 = 1;	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;	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;    

⌨️ 快捷键说明

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