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

📄 hardware.c

📁 rtl8019的程序
💻 C
字号:
#define HARDWARE_ENTITY
/*
****************************************************************
*
*
*                rtl8019 hardware driver
* file:hardware.c
* created by gm
* data  2008.8.20
*
*
*
****************************************************************
*/

#include "includes.h"

INT8U My_Mac[]=MY_MAC_ID; 
INT8U My_Ip[]=MY_IP_ID;


/*
************************************************
*
*                 Read and Write rtl8019 chip
*
*描述:读写指定地址处数据的函数
*参数:
*       addr   rtl内部地址
*       data   要写入的数据,16bit
*返回值:
*        
************************************************
*/
static unsigned char  get_reg(unsigned int address)
{
	return (*(volatile unsigned char *)address);
}

//读芯片内部寄存器函数
static void put_reg(unsigned int address,unsigned char data)
{
	(*(volatile unsigned char *)address)=data;
}

static void udelay(unsigned int i)
{
	unsigned j;
	for(;i!=0;i--)
	for(j=0;j<2000;j++);
}

static void eth_reset(void)
{
	unsigned char temp;
	
	temp=get_reg(RTL8019_RESET);
	put_reg(RTL8019_RESET,temp);
	put_reg(RTL8019_INTERRUPTSTATUS,0xff);
	udelay(200);
}

void rtl8019_get_enetaddr(unsigned char *addr)
{
	unsigned int i;
	unsigned char temp;
	
	eth_reset();
	
	put_reg (RTL8019_COMMAND, RTL8019_REMOTEDMARD);
	put_reg (RTL8019_DATACONFIGURATION, 0x48);
	put_reg (RTL8019_REMOTESTARTADDRESS0, 0x00);
	put_reg (RTL8019_REMOTESTARTADDRESS1, 0x00);
	put_reg (RTL8019_REMOTEBYTECOUNT0, 12);
	put_reg (RTL8019_REMOTEBYTECOUNT1, 0x00);
	put_reg (RTL8019_COMMAND, RTL8019_REMOTEDMARD);
	
	for (i = 0; i < 6; i++) 
	{
		temp = get_reg (RTL8019_DMA_DATA);
		*addr++ = temp;
		temp = get_reg (RTL8019_DMA_DATA);
	//	printf ("%x:", temp);
	}
	
	while ((!get_reg (RTL8019_INTERRUPTSTATUS) & 0x40));
	//printf ("\b \n");
	put_reg (RTL8019_REMOTEBYTECOUNT0, 0x00);
	put_reg (RTL8019_REMOTEBYTECOUNT1, 0x00);
	put_reg (RTL8019_COMMAND, RTL8019_PAGE0);
}

void eth_halt (void)
{
	put_reg (RTL8019_COMMAND, 0x01);
}

int eth_init (void)
{
	eth_reset ();
	put_reg (RTL8019_COMMAND, RTL8019_PAGE0STOP);
	put_reg (RTL8019_DATACONFIGURATION, 0x48);
	put_reg (RTL8019_REMOTEBYTECOUNT0, 0x00);
	put_reg (RTL8019_REMOTEBYTECOUNT1, 0x00);
	put_reg (RTL8019_RECEIVECONFIGURATION, 0x00);	/*00; */
	put_reg (RTL8019_TRANSMITPAGE, RTL8019_TPSTART);
	put_reg (RTL8019_TRANSMITCONFIGURATION, 0x02);
	put_reg (RTL8019_PAGESTART, RTL8019_PSTART);
	put_reg (RTL8019_BOUNDARY, RTL8019_PSTART);
	put_reg (RTL8019_PAGESTOP, RTL8019_PSTOP);
	put_reg (RTL8019_INTERRUPTSTATUS, 0xff);
	put_reg (RTL8019_INTERRUPTMASK, 0x11);	/*b; */
	put_reg (RTL8019_COMMAND, RTL8019_PAGE1STOP);
	put_reg (RTL8019_PHYSICALADDRESS0,My_Mac[0]);
	put_reg (RTL8019_PHYSICALADDRESS1,My_Mac[1]);
	put_reg (RTL8019_PHYSICALADDRESS2,My_Mac[2]);
	put_reg (RTL8019_PHYSICALADDRESS3,My_Mac[3]);
	put_reg (RTL8019_PHYSICALADDRESS4,My_Mac[4]);
	put_reg (RTL8019_PHYSICALADDRESS5,My_Mac[5]);
	put_reg (RTL8019_MULTIADDRESS0, 0x00);
	put_reg (RTL8019_MULTIADDRESS1, 0x41);
	put_reg (RTL8019_MULTIADDRESS2, 0x00);
	put_reg (RTL8019_MULTIADDRESS3, 0x80);
	put_reg (RTL8019_MULTIADDRESS4, 0x00);
	put_reg (RTL8019_MULTIADDRESS5, 0x00);
	put_reg (RTL8019_MULTIADDRESS6, 0x00);
	put_reg (RTL8019_MULTIADDRESS7, 0x00);
	put_reg (RTL8019_CURRENT, RTL8019_PSTART);
	put_reg (RTL8019_COMMAND, RTL8019_PAGE0);
	put_reg (RTL8019_TRANSMITCONFIGURATION, 0xe0);	/*e0; */

	return 0;
}

static unsigned char nic_to_pc (void)
{
	unsigned char rec_head_status;
	unsigned char next_packet_pointer;
	unsigned char packet_length0;
	unsigned char packet_length1;
	unsigned short rxlen = 0;
	unsigned int i = 4;
	unsigned char current_point;


	static INT8U REC_BUFF_NUM=0;

	INT8U  *REC_BUFF_PTR_BYTES;

	/*
	 * The RTL8019's first 4B is packet status,page of next packet
	 * and packet length(2B).So we receive the fist 4B.
	 */
	put_reg (RTL8019_REMOTESTARTADDRESS1, get_reg (RTL8019_BOUNDARY));
	put_reg (RTL8019_REMOTESTARTADDRESS0, 0x00);
	put_reg (RTL8019_REMOTEBYTECOUNT1, 0x00);
	put_reg (RTL8019_REMOTEBYTECOUNT0, 0x04);

	put_reg (RTL8019_COMMAND, RTL8019_REMOTEDMARD);

	rec_head_status = get_reg (RTL8019_DMA_DATA);
	next_packet_pointer = get_reg (RTL8019_DMA_DATA);
	packet_length0 = get_reg (RTL8019_DMA_DATA);
	packet_length1 = get_reg (RTL8019_DMA_DATA);

	put_reg (RTL8019_COMMAND, RTL8019_PAGE0);
	/*Packet length is in two 8bit registers */
	rxlen = packet_length1;
	rxlen = (((rxlen << 8) & 0xff00) + packet_length0);
	rxlen -= 4;

	if (rxlen > PKTSIZE_ALIGN)
	{
//		printf ("hfrkpacket too big!\n");
		while(1);  //调试
	}
	
	//准备一个缓冲区,接收数据
	if(REC_BUFF_NUM==MAX_BUFF_NUM)
	{
		REC_BUFF_NUM=0x00;
	}
	REC_BUFF_PTR_BYTES=REC_BUFF[REC_BUFF_NUM].bytes;
	
	/*Receive the packet */
	put_reg (RTL8019_REMOTESTARTADDRESS0, 0x04);
	put_reg (RTL8019_REMOTESTARTADDRESS1, get_reg (RTL8019_BOUNDARY));

	put_reg (RTL8019_REMOTEBYTECOUNT0, (rxlen & 0xff));
	put_reg (RTL8019_REMOTEBYTECOUNT1, ((rxlen >> 8) & 0xff));


	put_reg (RTL8019_COMMAND, RTL8019_REMOTEDMARD);

	for (i = rxlen; i > 0; i--)
		*REC_BUFF_PTR_BYTES++ = get_reg (RTL8019_DMA_DATA);
		
    // Pass the packet up to the protocol layers. 
	Rec_Ethernet_Packed(REC_BUFF[REC_BUFF_NUM].bytes);

	while (!(get_reg (RTL8019_INTERRUPTSTATUS)) & 0x40);	// wait for the op.dma操作结束 


	put_reg (RTL8019_COMMAND, RTL8019_PAGE1);
	current_point = get_reg (RTL8019_CURRENT);
	put_reg (RTL8019_COMMAND, RTL8019_PAGE0);
	put_reg (RTL8019_BOUNDARY, next_packet_pointer);
	return current_point;
}


int eth_rx (void)
{
	unsigned char temp, current_point;

	put_reg(RTL8019_COMMAND, RTL8019_PAGE0);

	while (1)
	{
		temp = get_reg (RTL8019_INTERRUPTSTATUS);

		if (temp & 0x90)   //若复位和溢出则重新初始化
		{
			eth_reset();
			eth_init();
			udelay(200);
			return 0;
		}

		if (temp & 0x1) 
		{
			
			do 
			{
				put_reg (RTL8019_INTERRUPTSTATUS, 0x01);
				current_point = nic_to_pc ();
			} while (get_reg (RTL8019_BOUNDARY) != current_point);
		}

		if (!(temp & 0x1))   //直到接收缓冲为空为止
			return 0;
	}
}




/*
**************************************************
*函数:void Send_Packet(struct _pkst *TxData)
*功能:
*      rtl发送数据的函数
*      由上层协议调用
*参数:
*      TxData 发送数据的结构 
*
*
*
**************************************************
*/
int eth_send(_pkst *TxData)
{
	static INT8U Tx_Buff_Sel=0;  //控制发送缓冲区的切换
	_pkst *ExPtr;
	INT8U *pdata;                //发送时的数据指针
	INT16U ii,length=0;
	
    //计算本次发送数据的总长度 
    ExPtr=TxData;
    while(ExPtr!=NULL)
    {
    	length+=ExPtr->length;
    	ExPtr=ExPtr->next;
    }  
    
    
    //开始远程dma将数据由cpu->arm
    Tx_Buff_Sel^=1;
    if(Tx_Buff_Sel)   //选择一发送的起始页
    {
    	put_reg(RTL8019_REMOTESTARTADDRESS1,0x40);
    }
    else
    {
    	put_reg(RTL8019_REMOTESTARTADDRESS1,0x46);
    } 
    
    while (get_reg (RTL8019_COMMAND) == RTL8019_TRANSMIT);
    
    put_reg (RTL8019_REMOTESTARTADDRESS0,0x00);  //发送起始的低地址
	put_reg (RTL8019_REMOTEBYTECOUNT0, (length & 0xff));
	put_reg (RTL8019_REMOTEBYTECOUNT1, ((length >> 8) & 0xff));
	put_reg (RTL8019_COMMAND, RTL8019_REMOTEDMAWR);    //开始远程dma传送数据
    
    //一个一个的发送发送结构
    ExPtr=TxData;
    while(ExPtr!=NULL)  //知道结构发送完毕
    {    
     	pdata=ExPtr->pdata;
     	for(ii=0;ii<ExPtr->length;ii++)   // 发送一个数据缓存
     	{
      		put_reg (RTL8019_DMA_DATA,*pdata++);
     	}
     	ExPtr=ExPtr->next;
    }
    ii=length;
    while (ii< 60)   //数据不足填充
    {	
		put_reg (RTL8019_DMA_DATA, 0);
		ii++;
	};

    
    //发送完毕,结束本次dma操作
    while (!(get_reg (RTL8019_INTERRUPTSTATUS)) & 0x40);
    put_reg (RTL8019_INTERRUPTSTATUS, 0x40);
    

    //传送数据到网络
    if(Tx_Buff_Sel)
    {
    	put_reg (RTL8019_TRANSMITPAGE,0x40);
    }
    else
    {	
    	put_reg (RTL8019_TRANSMITPAGE,0x46);
    }
    
    
    put_reg (RTL8019_TRANSMITBYTECOUNT0, (ii & 0xff));
	put_reg (RTL8019_TRANSMITBYTECOUNT1, ((ii >> 8 & 0xff)));
	put_reg (RTL8019_COMMAND, RTL8019_TRANSMIT);

    

	return 0;
}

    
    










	
	
	 	
  
  
  
  
  

⌨️ 快捷键说明

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