www.pudn.com > TCPIP.rar > IP.C


 
#include    "cpu_reg.h" 
#include	"string.h" 
#include	"ip.h" 
 
extern const Uint16 MyMAC[3]; 
extern const Uint16 MyIP[2]; 
extern const Uint16 RemoteIP[2]; 
extern const Uint16 SubnetMask[2]; 
extern const Uint16 GatewayIP[2]; 
extern Uint16 	RecdIpFrameLenth; 
extern Uint16 	TxFrameSize; 
extern Uint16 	RemoteMAC[3];             // 48 bit MAC 
extern Uint16 	RecdFrameMAC[3]; 
extern Uint16 	RecdFrameIP[2]; 
 
extern Uint16  	RxSuccessFlag; 
extern Uint16 	ARPAnswerSuccessFlag; 
extern Uint16	TxEthnetFrameBuffer[1518/2]; 
extern Uint16	RxEthnetFrameBuffer[1518/2]; 
 
extern	int		ms; 
 
Uint16	TxBufFlag; 
Uint16	bnry,curr; 
Uint16 UDPUserDataLenth;  
Uint16 IpEdition;                                //IP版本 
Uint16 IpServiceType; 
Uint16 IpIdent; 
Uint16 MyUdpPort; 
 
 
void delay(int k) 
{ 
   while(k--); 
} 
 
Uint16	SwapByte(Uint16	value) 
		{ 
    		Uint16	temp; 
    		temp=(value<<8)|(value>>8); 
    		return(temp); 
		}								 
 
//============================================================================== 
/********************************************************************** 
**函数原型:    void  page(uchar pagenumber) 
**入口参数:   	Uint16	pagenumber: 要切换的页 
**出口参数:		无 
**返 回 值:	无       
**说    明:	选择页,可选择0,1,2三页,第四页ne000兼容芯片保留  
************************************************************************/ 
void	page(Uint16 pagenumber) 
		{ 
			Uint16	temp; 
			temp = Reg00;				//command register 
			temp = temp & 0x3B ; 			//注意txp位不能要 
			pagenumber=pagenumber <<6; 
			temp=temp | pagenumber; 
			Reg00=temp; 
		} 
 
 
/********************************************************************** 
**函数原型:     void 	Init8019() 
**入口参数:		无 
**出口参数:		无 
**返 回 值:		无               
**说    明:		对芯片的工作寄存器进行设置,各个寄存器的用法可参考文档和 
**				络芯片的数据手册 
************************************************************************/ 
void	Init8019() 
		{ 
			ms =0; 
			while(ms<100); 
/********************************************************************** 
 
1.Reg00命令寄存器: CR,命令寄存器,地址偏移量00H,为一个字节 
  位:  7   6   5   4   3   2   1   0  
名字: PS1 PS0 RD2 RD1 RD0 TXP STA STP  
//============================================ 
2. 
RD2,RD1,RD0: 这3个位代表要执行的功能。 
 0   0   1 : 读网卡内存 
 0   1   0 : 写网卡内存 
 0   1   1 : 发送网卡数据包 
 1   *   * : 完成或结束DMA的读写操作 
//============================================ 
3.TXP位置1时发送数据包,发完自动清零 
//============================================ 
4. 
STA,STP:	这两个位用来启动命令或停止命令 
 1   0 		启动命令 
 0   1 		停止命令 
//============================================ 
********************************************************/ 
			Reg00=0x21;   //使芯片处于停止模式,这时进行寄存器设置 
			ms = 0; 
			while(ms<100); //延时100毫秒,确保芯片进入停止模式 
			page(0); 
			delay(10); 
			Reg0a= 0x00;   //清rbcr0 
			delay(5); 
			Reg0b= 0x00;   //清rbcr1 
			delay(5); 
			Reg0c= 0xe0;  //RCR,监视模式,不接收数据包 
			delay(5); 
			Reg0d= 0xe2;  //TCR,loop back模式 
			delay(5); 
			Reg01= 0x4c;   //pstart = 0x4c 
			delay(5); 
			Reg02= 0x80;   //pstop = 0x80 
			delay(5); 
			Reg03= 0x4c;   //bnry = 4c 
			delay(5); 
			Reg04= 0x40;  //TPSR,发送起始页寄存器 
			delay(5); 
			Reg07= 0xff;  //清除所有中断标志位,中断状态寄存器 
			delay(5); 
			Reg0f= 0x00;  //中断屏蔽寄存器清0,禁止中断 
			delay(5); 
			Reg0e= 0xc9;  // 数据配置寄存器,16位dma方式 
			 
			page(1); 
			delay(10); 
			Reg07= 0x4d; 
			delay(5); 
			Reg08= 0x00; 
			delay(5); 
			Reg09= 0x00; 
			delay(5); 
			Reg0a= 0x00; 
			delay(5); 
			Reg0b= 0x00; 
			delay(5); 
			Reg0c= 0x00; 
			delay(5); 
			Reg0d= 0x00; 
			delay(5); 
			Reg0e= 0x00; 
			delay(5); 
			Reg0f= 0x00; 
			delay(5); 
			 
    		Reg01=0x02; 
			delay(5); 
    		Reg02=0xE0; 
			delay(5); 
    		Reg03=0x4C; 
			delay(5); 
    		Reg04=0xA0; 
			delay(5); 
    		Reg05=0x7E; 
			delay(5); 
    		Reg06=0x7A; 
			delay(5); 
			 
			page(3); 
			delay(10); 
			Reg01 = 0x30; 
			delay(5); 
			Reg04 = 0x80; 
			delay(5); 
			 
			page(0); 
			delay(10); 
			Reg0c= 0xce;  //将芯片设置成正常模式,跟外部网络连接 
			delay(5);			 
			Reg0d= 0xe0; 
			delay(5); 
			Reg00= 0x22;  //启动芯片开始工作 
			delay(5); 
			 
//----------------------------------- 
			Reg07= 0xff;  //清除所有中断标志位 
			ms = 0; 
			while(ms<100); 
		} 
 
 
Uint16 CalcCheckSum(Uint16 *Start, Uint16 Count, Uint16 IsTCP, Uint16 IsUDP) 
{ 
    Uint32 Sum; 
   
    Sum = 0; 
    if ((IsTCP)||(IsUDP))  
    { 
        Sum += MyIP[0]; 
        Sum += MyIP[1]; 
        Sum += RemoteIP[0]; 
        Sum += RemoteIP[1]; 
        Sum += SwapWord(Count*2); 
        if(IsTCP) 
             Sum += SwapWord(PROTOCOL_TCP); 
        else 
             Sum += SwapWord(PROTOCOL_UDP); 
    } 
    while (Count > 0)  
    { 
        Sum += *Start; 
        Start ++; 
        Count --; 
    } 
    Sum = (Sum & 0xFFFF) + ((Sum >> 16)&0xFFFF); 
    if(Sum&0xFFFF0000) 
        Sum++; 
    return((Uint16)((~Sum)&0xFFFF)); 
} 
 
 
//============================================================================= 
/********************************************************************** 
**函数原型:    void 		SendFrame(Uint16 *TxdNetBuff,Uint16  length) 
**入口参数:		Uint16    	*TxdNetBuff	:指向发送缓冲区 
**              uint length					:发送数据包的长度 
**出口参数:		无 
**返 回 值:	无               
**说    明:	发送数据包,以太网底层驱动程序,所有的数据发送都要通过该程序 
************************************************************************/ 
void	SendFrame(Uint16	*TxdNetBuff,Uint16 length) 
		{ 
			Uint16		i,ii; 
		   	if(length<46/2) 
       			{ 
          			for(i=length;i<60/2;i++)	TxEthnetFrameBuffer[i]=0; 
          			length=60/2; 
       			} 
			 
			page(0); 
			delay(10);						//切换至第0页 
			length = length <<1; 
			TxBufFlag=!TxBufFlag;			//设置两个发缓区,提高发送效率 
			if(TxBufFlag) 
				{Reg09=0x40 ;}				//设置发送页地址 
			else 
				{Reg09=0x46 ;}				//设置发送页地址 
     
			Reg08=0x00; 					//read page address low 
			delay(1); 
			Reg0b = length >>8;				//写发送长度高位 
			delay(1); 
			Reg0a = length & 0x00ff;        //写发送长度低位   
			delay(1); 
			Reg00=0x12;						//write dma, page0 
 
			for(i=0;i>8;  //high byte counter 
			delay(1); 
			Reg05=length&0xff;//low byte counter 
			delay(1); 
			Reg07=0xff; 
			delay(1); 
			Reg00=0x3e;       //to sendpacket; 
	} 
 
/********************************************************************** 
**函数原型:    Uint16        Rec_NewPacket() 
**入口参数:		无 
**出口参数:		无 
**返 回 值:	0          没有新数据包 
**              1          接收到新数据包 
**说    明:	查询是否有新数据包并接收进缓冲区 
************************************************************************/ 
Uint16	RecFrame() 
		{ 
			Uint16	i,ii; 
			Uint16	Temp,length; 
			union{ 
					Uint16	total;	 
					struct{ 
							Uint16	high:8; 
							Uint16	low:8; 
						  }e; 
				 }d; 
			for(i=0;i<1518/2;i++)	RxEthnetFrameBuffer[i] = 0;				 		  		 
			page(0); 
			delay(10); 
			bnry = Reg03;				//bnry page have read 读页指针 
			bnry = bnry & 0x00FF; 
			page(1); 
			delay(10); 
			curr = Reg07;				//curr writepoint 8019写页指针 
			curr = curr & 0x00FF; 
			page(0); 
			delay(10); 
			if((curr==0))return(0);	//读的过程出错 
			bnry++; 
			if(bnry>0x7f)	bnry=0x4c; 
			if(bnry!=curr)			//此时表示有新的数据包在缓冲区里 
    			{					//在任何操作都最好返回page0 
     				page(0); 
     				delay(10); 
     //======================================= 
     				Reg09=bnry;		//读页地址的高字节 
     				delay(5); 
     				Reg08=0x00; 	//读页地址的低字节 
     				delay(5); 
     				Reg0b=0x00;		//读取字节计数高字节 
     				delay(5); 
     				Reg0a=18;       //读取字节计数高字节 
     				delay(5); 
     				Reg00=0x0a;     //启动Remote DMA读操作 
	 				delay(5);	 
     				for(i=0;i<9;i++)	//读取一包的前18个字节:4字节的8019头部,6字节目的地址,6字节原地址,2字节协议 
                    	{ 
                       		RxEthnetFrameBuffer[i]=Reg10; 
                       		delay(1); 
                      	} 
 //=======================================中止DMA操作 
     				Reg0b=0x00;	// 
     				delay(1); 
     				Reg0a=0x00;	// 
     				delay(1); 
     				Reg00=0x22;	//结束或放弃DMA操作 
     				delay(1); 
 //======================================= 
					 
					d.total = RxEthnetFrameBuffer[0]; 
					length = RxEthnetFrameBuffer[1]; 
     				if(((d.e.low & 0x01)==0)||(d.e.high > 0x7f) || (d.e.high < 0x4c)||( length > 1517)) 
    					{//接收状态错误或下一数据包的起始页地址错误或接收的数据包长度>1500字节 
       						page(1); 
       						delay(10); 
							curr=Reg07; 	//page1 
							page(0);		//切换回page0 
							delay(10); 
        					bnry = curr -1; 
        					if(bnry < 0x4c) 	bnry =0x7f; 
        					Reg03=bnry; 	//write to bnry      
        					delay(1); 
        					Reg07=0xff; 
							return(0); 
              			} 
//============================================= 
             
     				else//表示数据包是完好的.读取剩下的数据 
     					{ 
     						Temp = SwapByte(RxEthnetFrameBuffer[8]);		 
        					if((Temp == Frame_IP)||(Temp == Frame_ARP)) 
								{ //协议为IP或ARP才接收 
                					Reg09 = bnry;   				//read page address high 
                					delay(1); 
                					Reg08 = 4;      				//read page address low 
                					delay(1); 
                					Reg0b = length>>8;  //read count high 
                					delay(1); 
                					Reg0a = length & 0xff;//read count low; 
                					delay(1); 
                					Reg00=0x0a;                             //read dma 
                					delay(1); 
						        	length=(length+1)/2; 
                					for(ii=2;ii>8)|(Data<<8)); 
} 
 
void WriteDWord(Uint16 *Address,Uint32 Data) 
{ 
    Uint16 Temp; 
    Temp=(Uint16)(Data>>16); 
    *Address=SwapWord(Temp); 
    Temp=(Uint16)(Data&0x0000FFFF); 
    *(Address+1)=SwapWord(Temp); 
} 
 
void CopyFrameFromBE(Uint16 Offset,Uint16 Size) 
{ 
    Uint16 i,Temp; 
    for(i=0;i>8) 
    { 
         case ICMP_ECHO: Prepare_ICMP_Answer(); 
                         break; 
    } 
} 
 
void Prepare_ICMP_Answer(void) 
{ 
    Uint16 ICMPDataCount; 
    Uint16 CalcCkSum; 
 
    ICMPDataCount=RecdIpFrameLenth-IP_HEADER_SIZE - ICMP_HEADER_SIZE; 
//Ethnet 
    memcpy((TxEthnetFrameBuffer+ETH_HEADER_START),&RecdFrameMAC,3); 
    memcpy((TxEthnetFrameBuffer+ETH_HEADER_START+3),&MyMAC,3); 
    *(TxEthnetFrameBuffer+ETH_HEADER_START+6)=SwapWord(Frame_IP); 
//IP 
    *(TxEthnetFrameBuffer+IP_HEADER_START+0)=SwapWord(Ip_Edition); 
    *(TxEthnetFrameBuffer+IP_HEADER_START+1)=SwapWord(RecdIpFrameLenth*2); 
    *(TxEthnetFrameBuffer+IP_HEADER_START+2)=SwapWord(0); 
    *(TxEthnetFrameBuffer+IP_HEADER_START+3)=SwapWord(0); 
    *(TxEthnetFrameBuffer+IP_HEADER_START+4)=SwapWord((DEFUALT_TTL<<8)|PROTOCOL_ICMP); 
    *(TxEthnetFrameBuffer+IP_HEADER_START+5)=0; 
    memcpy((TxEthnetFrameBuffer+IP_HEADER_START+6),&MyIP,2); 
    memcpy((TxEthnetFrameBuffer+IP_HEADER_START+8),&RecdFrameIP,2); 
 
    CalcCkSum=CalcCheckSum((TxEthnetFrameBuffer+IP_HEADER_START),IP_HEADER_SIZE,0,0); 
    if(!CalcCkSum) 
         CalcCkSum=0xFFFF; 
    *(TxEthnetFrameBuffer+IP_HEADER_START+5)=CalcCkSum; 
//ICMP     
    *(TxEthnetFrameBuffer+ICMP_HEADER_START+0)=SwapWord(ICMP_ECHO_REPLY<<8); 
    *(TxEthnetFrameBuffer+ICMP_HEADER_START+1)=0; 
//    CopyFrameFrom8900(ICMP_HEADER_START+2,ICMPDataCount); 
    memcpy((TxEthnetFrameBuffer+ICMP_HEADER_START+2),(RxEthnetFrameBuffer+RTL8019_HEADER_SIZE+ICMP_HEADER_START+2),ICMPDataCount); 
    CalcCkSum=CalcCheckSum((TxEthnetFrameBuffer+ICMP_HEADER_START),(ICMPDataCount+ICMP_HEADER_SIZE),0,0); 
    if(!CalcCkSum) 
        CalcCkSum=0xFFFF; 
    *(TxEthnetFrameBuffer+ICMP_HEADER_START+1)=CalcCkSum; 
    TxFrameSize=ETH_HEADER_SIZE+IP_HEADER_SIZE+ICMP_HEADER_SIZE+ICMPDataCount; 
    SendFrame(TxEthnetFrameBuffer,TxFrameSize); 
} 
 
/***************UDP*******************/ 
 
void Process_UDP_Frame(void) 
{ 
    Uint16 UdpLenth; 
     
    CopyFrameFromBE(RTL8019_HEADER_SIZE+UDP_HEADER_START,4); 
    if(*(RxEthnetFrameBuffer+RTL8019_HEADER_SIZE+UDP_HEADER_START+1)==MY_UDP_PORT) 
    { 
         UdpLenth=*(RxEthnetFrameBuffer+RTL8019_HEADER_SIZE+UDP_HEADER_START+2)/2; 
         UDPUserDataLenth=UdpLenth-UDP_HEADER_SIZE; 
    } 
} 
 
void Prepare_UDP_Frame(Uint16 RemoteUdpPort,Uint16 TxUDPDataNum) 
{ 
 
    Uint16 CalcCkSum; 
//ETHNET     
    memcpy((TxEthnetFrameBuffer+ETH_HEADER_START+0),&RemoteMAC,3); 
    memcpy((TxEthnetFrameBuffer+ETH_HEADER_START+2),&MyMAC,3); 
    *(TxEthnetFrameBuffer+ETH_HEADER_START+6)=SwapWord(Frame_IP); 
//IP 
    *(TxEthnetFrameBuffer+IP_HEADER_START+0)=SwapWord(Ip_Edition); 
    *(TxEthnetFrameBuffer+IP_HEADER_START+1)=SwapWord(TxUDPDataNum+IP_HEADER_SIZE+UDP_HEADER_SIZE); 
    *(TxEthnetFrameBuffer+IP_HEADER_START+2)=SwapWord(0x0000); 
    *(TxEthnetFrameBuffer+IP_HEADER_START+3)=SwapWord(0x0000); 
    *(TxEthnetFrameBuffer+IP_HEADER_START+4)=SwapWord((DEFUALT_TTL<<8)|PROTOCOL_UDP); 
    *(TxEthnetFrameBuffer+IP_HEADER_START+5)=0; 
    memcpy((TxEthnetFrameBuffer+IP_HEADER_START+6),&MyIP,2); 
    memcpy((TxEthnetFrameBuffer+IP_HEADER_START+8),&RemoteIP,2); 
    CalcCkSum=CalcCheckSum((TxEthnetFrameBuffer+IP_HEADER_START),IP_HEADER_SIZE,0,0); 
    if(!CalcCkSum) 
         CalcCkSum=0xFFFF; 
    *(TxEthnetFrameBuffer+IP_HEADER_START+5)=CalcCkSum; 
//UDP                                                   
    *(TxEthnetFrameBuffer+UDP_HEADER_START+0)=SwapWord(MY_UDP_PORT); 
    *(TxEthnetFrameBuffer+UDP_HEADER_START+1)=SwapWord(RemoteUdpPort); 
    *(TxEthnetFrameBuffer+UDP_HEADER_START+2)=SwapWord(TxUDPDataNum+UDP_HEADER_SIZE); 
    *(TxEthnetFrameBuffer+UDP_HEADER_START+3)=0; 
 
    CalcCkSum=CalcCheckSum((TxEthnetFrameBuffer+UDP_HEADER_START),(TxUDPDataNum+UDP_HEADER_SIZE),0,1); 
    if(!CalcCkSum) 
         CalcCkSum=0xFFFF; 
    *(TxEthnetFrameBuffer+UDP_HEADER_START+3)=CalcCkSum; 
    TxFrameSize=ETH_HEADER_SIZE+IP_HEADER_SIZE+UDP_HEADER_SIZE+TxUDPDataNum; 
    SendFrame(TxEthnetFrameBuffer,TxFrameSize); 
} 
 
/***************TCP/IP*****************/ 
 
void ProcessEthBroadcastFrame(void) 
{ 
    Uint16 TargetIP[2],FrameLenth; 
     
	FrameLenth=5; 
    CopyFrameFromBE(RTL8019_HEADER_SIZE+6,FrameLenth); 
    memcpy(&RecdFrameMAC,(RxEthnetFrameBuffer+ETH_HEADER_START+RTL8019_HEADER_SIZE+3),3); 
    if(*(RxEthnetFrameBuffer+ETH_HEADER_START+RTL8019_HEADER_SIZE+6)==Frame_ARP) 
    { 
         if(*(RxEthnetFrameBuffer+ARP_HEADER_START+RTL8019_HEADER_SIZE)==HARDW_ETH) 
         { 
              if(*(RxEthnetFrameBuffer+ARP_HEADER_START+RTL8019_HEADER_SIZE+1)==Frame_IP) 
              { 
                   if(*(RxEthnetFrameBuffer+ARP_HEADER_START+RTL8019_HEADER_SIZE+2)==IP_HLEN_PLEN) 
                   { 
                        if(*(RxEthnetFrameBuffer+ARP_HEADER_START+RTL8019_HEADER_SIZE+3)==OP_ARP_REQUEST) 
                        { 
                             memcpy(&RecdFrameIP,(RxEthnetFrameBuffer+ARP_HEADER_START+RTL8019_HEADER_SIZE+7),2); 
                             memcpy(&TargetIP,(RxEthnetFrameBuffer+ARP_HEADER_START+RTL8019_HEADER_SIZE+12),2); 
                             if((MyIP[0]==TargetIP[0]) && (MyIP[1]==TargetIP[1])) 
                                  ArpAnswer();     
                        } 
                   } 
              } 
         } 
    }                
} 
 
void ProcessEthIAFrame(void) 
{ 
    Uint16 FrameType,IpHeaderLenth,ProtocolType; 
     
    CopyFrameFromBE(RTL8019_HEADER_SIZE+6,1);     
    memcpy(&RecdFrameMAC,(RxEthnetFrameBuffer+ETH_HEADER_START+RTL8019_HEADER_SIZE+3),3); 
    FrameType=*(RxEthnetFrameBuffer+ETH_HEADER_START+RTL8019_HEADER_SIZE+6); 
    switch(FrameType) 
    { 
         case Frame_ARP: 
         { 
              CopyFrameFromBE(ARP_HEADER_START+RTL8019_HEADER_SIZE+0,4); 
              if(*(RxEthnetFrameBuffer+ARP_HEADER_START+RTL8019_HEADER_SIZE+2)==IP_HLEN_PLEN) 
              { 
                   if(*(RxEthnetFrameBuffer+ARP_HEADER_START+RTL8019_HEADER_SIZE+3)==OP_ARP_ANSWER) 
                   { 
                        memcpy(&RecdFrameMAC,(RxEthnetFrameBuffer+ARP_HEADER_START+RTL8019_HEADER_SIZE+4),3); 
                        memcpy(&RecdFrameIP,(RxEthnetFrameBuffer+ARP_HEADER_START+RTL8019_HEADER_SIZE+7),2); 
                        ARPAnswerSuccessFlag=1; 
                   } 
              } 
         } 
         break; 
         case Frame_IP: 
         { 
              CopyFrameFromBE(IP_HEADER_START+RTL8019_HEADER_SIZE+0,1); 
              IpHeaderLenth=*(RxEthnetFrameBuffer+IP_HEADER_START+RTL8019_HEADER_SIZE); 
              if((IpHeaderLenth&0xFF00)==Ip_Edition) 
              { 
                   IpHeaderLenth=5*(32/8)/2; 
                   CopyFrameFromBE(IP_HEADER_START+RTL8019_HEADER_SIZE+1,IpHeaderLenth-1-4); 
                   RecdIpFrameLenth=*(RxEthnetFrameBuffer+IP_HEADER_START+RTL8019_HEADER_SIZE+1)/2; 
                   ProtocolType=*(RxEthnetFrameBuffer+IP_HEADER_START+RTL8019_HEADER_SIZE+4)&0x00FF; 
                   memcpy(&RecdFrameIP,(RxEthnetFrameBuffer+IP_HEADER_START+RTL8019_HEADER_SIZE+6),2); 
                   switch(ProtocolType) 
                   { 
                        case PROTOCOL_ICMP:  Process_ICMP_Frame(); 
                                             break; 
                        case PROTOCOL_TCP :  Process_TCP_Frame(); 
                                             break; 
                        case PROTOCOL_UDP :  Process_UDP_Frame(); 
                                             break; 
                   } 
              } 
         } 
         default: break; 
    } 
} 
 
void DoNetworkStuff() 
{     
    Uint16 Temp; 
    page(0); 
    Temp=Reg0c; 
    Temp&=0x20; 
    if(Temp) 
         ProcessEthBroadcastFrame(); 
    else     
         ProcessEthIAFrame();  
}