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

📄 eth.c

📁 51avr tcpip http协议
💻 C
字号:
//-----------------------------------------------------------------------------
// Net ETH.C
//
// This module is the Ethernet layer
//-----------------------------------------------------------------------------
#include <string.h>
#include <stdlib.h>
#include "net.h"
#include "serial.h"
#include "arp.h"
#include "ip.h"
#include "eth.h"
#include "general.h"
#include "timer.h"


extern UCHAR arpbuf[];
extern UCHAR  my_hwaddr[]; 
extern UCHAR rcve_buf_allocated;
extern UINT event_word;

UCHAR txd_buffer_select=0;   		//选择网卡的发送缓冲区  


//------------------------------------------------------------------------
// Initialize the Cirrus Logic 8019 chip
//------------------------------------------------------------------------

void page(unsigned char pagenumber)
{
	unsigned char temp;
	temp=reg00;		
	temp &= 0x3B ;
	pagenumber <<= 6;
	temp |= pagenumber;
	reg00=temp;
}

void Rtl8019AS_Reset() //复位网卡
{
    unsigned char temp;
    temp=reg1f;//读网卡的复位端口
	Delay1ms(200);
	reg1f=temp; //写网卡的复位端口
	Delay1ms(200);
}

void ReadRtl8019NodeID(void)//读出网卡的物理地址存到my_ethernet_address.bytes[6]里  
{
	unsigned char i;
	page(0);
	reg09=0;	//读取网卡的ram的地址为0x0000 
	reg08=0;
	reg0b=0;
	reg0a=12;	//读取12个字节
	reg00=0x0a;	//读ram
	for (i=0;i<6;i++)
	{ 
//    	my_hwaddr[i]=reg10;
//    	my_hwaddr[i]=reg10;
   	}
}

void WriteRtl8019NodeID()
{
	page(1);
	reg01=my_hwaddr[0];
	reg02=my_hwaddr[1];
	reg03=my_hwaddr[2];
	reg04=my_hwaddr[3];
	reg05=my_hwaddr[4];
	reg06=my_hwaddr[5];
	page(0);
}


void init_8019(void)
{

	Rtl8019AS_Reset();		//复位8019
//	R8019_CHIP_SELECT;
	reg00=0x21;				//使芯片处于停止模式,这时进行寄存器设置 停止模式下,将不会发送和接收数据包
	Delay1ms(10);			//延时10毫秒,确保芯片进入停止模式
	page(0);
	reg0a=0x00;	reg0b=0x00;
	reg0c= 0xe0;			//monitor mode (no packet receive)
	reg0d= 0xe2;			//loop back mode 使芯片处于mon和loopback模式,跟外部网络断开  
	reg01=0x4c;	reg02=0x80;	reg03=0x4c;	reg04=0x40;
	reg07=0xff;				//清除所有中断标志位
	reg0f=0x00;				//disable all interrupt
	reg0e=0xc8;				//byte dma 8位dma方式
	page(1);
	reg07=0x4d;	reg08=0x00;	reg09=0x00;	reg0a=0x00;	reg0b=0x00;	
	reg0c=0x00;	reg0d=0x00;	reg0e=0x00;	reg0f=0x00;
	reg00=0x22;				//这时让芯片开始工作
	ReadRtl8019NodeID();	//读出网卡的物理地址48位  
	WriteRtl8019NodeID();	//将网卡地址写入到mar寄存器  
	page(0);
	reg0c=0xcc;				//将网卡设置成正常的模式,跟外部网络连接
	reg0d=0xe0;
	reg00=0x22;				//这时让芯片开始工作
	reg07=0xff;				//清除所有中断标志位
}

//------------------------------------------------------------------------
// This functions checks 8019 status then sends an ethernet
// frame to it by calling an assembler function. 
//------------------------------------------------------------------------

void send_frame(UCHAR * outbuf, UINT len)/*发送一个数据包的命令,长度最小为60字节,最大1514字节*/
{
UCHAR i;
UINT ii;

	page(0);
	if(len<60)len=60;
	txd_buffer_select=~txd_buffer_select;
  	if	(txd_buffer_select)
		reg09=0x40 ;	//txdwrite highaddress
	else
        reg09=0x46 ;	//txdwrite highaddress
	reg08=0x00; 		//read page address low
	reg0b=len>>8;		//read count high
	reg0a=len&0xff;		//read count low;
	reg00=0x12;			//write dma, page0
	for	(ii=0;ii<len;ii++)	
	{
	   reg10=*(outbuf+ii);  
	}

	/* 以下3句为中止dma的操作,可以不要            */
	reg0b=0x00;		//read count high   中止DMA操作
	reg0a=0x00;		//read count low;
	reg00=0x22;		//complete dma page 0

	for(i=0;i<16;i++)	//最多重发16次
	{
		for(ii=0;ii<1000;ii++)	//检查txp为是否为低
		{
			if ((reg00&0x04)==0) break;
		}
		if ((reg04&0x01)!=0) break;	//表示发送成功
		reg00=0x3e;
	}
	reg07=0xff;
	if(txd_buffer_select)
		reg04=0x40;	//txd packet start; 
	else
		reg04=0x46;	//txd packet start; 
	reg06=len>>8;	//high byte counter
	reg05=len&0xff;	//low byte counter
	reg07=0xff;
	reg00=0x3e;		//to sendpacket;  
	free(outbuf);
#ifdef DEBUG
	PrintStr("ETH:send  frame.\n");
#endif  
}

//------------------------------------------------------------------------
// This functions checks the 8019 receive event status
// word to see if an ethernet frame has arrived.  If so,
// set EVENT_ETH_ARRIVED bit in global event_word
//------------------------------------------------------------------------
void query_8019(void)
{   
unsigned char bnry=0,curr=0;

	page(0);
   	bnry=reg03;		//bnry page have read 读页指针
	page(1);
	curr=reg07;		//curr writepoint 8019写页指针
	page(0);
	if ((curr==0))	return;
	bnry++;
	if (bnry>0x7f)	bnry=0x4c;
	if (bnry!=curr)	//此时表示有新的数据包在缓冲区里
	{
         SREG = 0<<SREG_I;
	     event_word |= EVENT_ETH_ARRIVED;
         SREG = 1<<SREG_I;
	}
 	reg0b=0x00; reg0a=0x00;  reg00=0x22;//complete dma page 0	
}

//------------------------------------------------------------------------
// This function gets an incoming Ethernet frame from the 8019.
// There may be more than 1 waiting but just allocate memory for
// one and read one in.  Use the 8019 to queue incoming packets.
//------------------------------------------------------------------------
UCHAR* rcve_frame(void)//如果收到一个有效的数据包,返回收到的数据,否则返回NULL
{
UCHAR bnry=0,curr=0,next_page=0;
UINT len=0, ii;
UCHAR temp=0;
UCHAR* buf=0;

	page(0);
   	bnry=reg03;		//bnry page have read 读页指针
	page(1);
	curr=reg07;		//curr writepoint 8019写页指针
	page(0);
	if ((curr==0))	return NULL;	//读的过程出错
	next_page=bnry;
	bnry++;
	if (bnry>0x7f)	bnry=0x4c;
	if (bnry!=curr)	//此时表示有新的数据包在缓冲区里
	{
		//读取一包的前4个字节:4字节的8019头部
		page(0);
 		reg09=bnry;		//read page address high
		reg08=0x00; 	//read page address low
		reg0b=0x00;		//read count high
		reg0a=4;		//read count low;
		reg00=0x0a;		//read dma
		
		temp = reg10;		temp = reg10;
		next_page = temp-1;		//next page start-1
		len = reg10;		temp = reg10;
		len += temp<<8;
	 	reg0b=0x00; reg0a=0x00;  reg00=0x22;//complete dma page 0

   		// Allocate enough memory to hold the incoming frame
		buf = (UCHAR*)malloc(len);
		if (buf == NULL)
		{
			// out of RAM
			// Tell 8019 to skip the frame
			page(1);
			curr=reg07; 	//page1
			page(0);		//切换回page0
	        bnry = curr -1;
	        if	(bnry < 0x4c) bnry =0x7f;
	        reg03=bnry; 	//write to bnry   
			reg07=0xff;		//清除中断状态可以不用
			return NULL;
		}
		// This flag keeps track of allocated rcve memory
		rcve_buf_allocated = TRUE;
		// Call the assembler function to get the incoming frame
		reg09=bnry;	//read page address high
		reg08=4; 	//read page address low
		reg0b=len>>8;	//read count high
		reg0a=len&0xff;	//read count low;
		reg00=0x0a;	//read dma
        for(ii=0;ii<len;ii++)
        {
	    	buf[ii]=reg10;
        }
		reg0b=0x00;	reg0a=0x00; reg00=0x22;	//dma complete  page0     
	   	// Return pointer to start of buffer
		bnry=next_page;
		if (bnry<0x4c)  bnry=0x7f;
		reg03=bnry; 	//write to bnry    
        reg07=0xff;
		return (buf);	
	}
	return NULL;
}


void eth_send(UCHAR * outbuf, UCHAR * hwaddr, UINT ptype, UINT len)
{
	ETH_HEADER * eth;
   
   eth = (ETH_HEADER *)outbuf;
	  
	// Add 14 byte Ethernet header
	memcpy(eth->dest_hwaddr, hwaddr, 6);
	memcpy(eth->source_hwaddr, my_hwaddr, 6); 
   eth->frame_type = swapint(ptype);

   // We just added 14 bytes to length
   send_frame(outbuf, len + 14);
}

//------------------------------------------------------------------------
// This is the handler for incoming Ethernet frames
//	This is designed to handle standard Ethernet (RFC 893) frames
// See "TCP/IP Illustrated, Volume 1" Sect 2.2
//------------------------------------------------------------------------
void eth_rcve(UCHAR * inbuf)
{
   ETH_HEADER * eth;
   unsigned int frametype;
   
   eth = (ETH_HEADER *)inbuf;

   frametype = swapint(eth->frame_type);
   
   // Reject frames in IEEE 802 format where Eth type field
   // is used for length.  Todo: Make it handle this format
   if (frametype < 1520)
   {
#ifdef DEBUG
      PrintStr("ETH: IEEE 802 pkt rejected\n");
#endif
      return;      
   }
	
   // Figure out what type of frame it is from Eth header
   // Call appropriate handler and supply address of buffer
   switch (frametype)
   {
	   case ARP_PACKET:
	   arp_rcve(inbuf);
	   break;
		      
	   case IP_PACKET:
	   ip_rcve(inbuf);
      break;

      default:
#ifdef DEBUG
		PrintStr("Error: Unknown pkt rcvd\n");
#endif
      break;
   }
}

⌨️ 快捷键说明

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