📄 rtl8019.c
字号:
delay(1);
Reg00=0x22; //结束或放弃DMA操作
for(i=0;i<6;i++) //最多重发6次
{
for(x=0;x<1000;x++)
{//检查CR寄存器的txp位是否为低,为1说明正在发送,为0说明发完或出错放弃
if((Reg00&0x04)==0)
{ break; }
}
if((Reg04&0x01)!=0)//表示发送成功,判断发送状态寄存器TSR,决定是否出错
{break;};
Reg00=0x3e;
}
Reg07=0xff;
delay(1);
Reg04=0x40; //txd packet start;
delay(1);
Reg06= h; //high byte counter
delay(1);
Reg05= l; //low byte counter
delay(1);
Reg07=0xff;
delay(1);
Reg00=0x3e; //to sendpacket;
delay(1);
}
unsigned short checksum(unsigned short *buffer, short size)
{
unsigned long cksum;
unsigned short sum;
cksum=0;
while(size >0)
{
sum=(*buffer<<8)+(*buffer>>8);
buffer++;
cksum+=sum;
size --;
}
cksum = (cksum >> 16) + (cksum & 0xffff);
cksum += (cksum >>16); //cksum maybe +1
sum=(unsigned short)(~cksum);
sum=(sum<<8)+(sum>>8);
return (sum);
}
void send_udp(unsigned short *buf,unsigned short length)
{
unsigned short temp;
unsigned short tempbuf[1240/2];
for(temp=0;temp<length;temp++)
buf[temp]=change_byte(buf[temp]);
load_udp(buf,&length);
t_iphdr.protocal_ttl =128; //usally 32 or 64
t_iphdr.protocal_ttl +=(unsigned short)17<<8; //17=UDP
t_iphdr.saddr =nod_ipaddr;
t_iphdr.tol_len =change_byte((length+10)<<1);
t_iphdr.chksum=0; //it is important
memcpy(tempbuf,&t_iphdr,sizeof(t_iphdr));
t_iphdr.chksum=checksum(tempbuf,10);
load_ip(sendbuf,&length);
if((t_iphdr.daddr.addr4_3&0xff01)==0xff01) //是广播地址
temp=BROADCAST;
else
temp=0;
send_frame(sendbuf,temp,UDP, length);
}
void send_arp(struct ipaddr *ip,unsigned short arp_type)
{
unsigned short temp;
arp1.hard_type =(unsigned short)1<<8;
arp1.proto_type =(unsigned short)((2048<<8)+(2048>>8));
arp1.proto_hard_length =6;
arp1.proto_hard_length +=(unsigned short)4<<8;
arp1.op_code =arp_type<<8;
arp1.send_macaddr =MAC_self;
arp1.send_ipaddr =nod_ipaddr;
if(arp_type==1) //请示对方 fill MAC
{
arp1.rec_macaddr.addr2_1 =0;
arp1.rec_macaddr.addr4_3 =0;
arp1.rec_macaddr.addr6_5 =0;
temp=BROADCAST;
}
else //应答对方 fill MAC
{
arp1.rec_macaddr=MAC_rec;
temp=REC_ARP;
}
arp1.rec_ipaddr =*ip;
memcpy(sendbuf,&arp1,sizeof(arp1));
send_frame(sendbuf,temp,ARP,sizeof(arp1));
}
/**********************************************************************
**函数原型: 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<25;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 = 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<length+2;ii++)
{
RxEthnetFrameBuffer[ii]=Reg10;
}
//================终止DMA操作
Reg0b=0x00; //read count high
delay(1);
Reg0a=0x00; //read count low;
delay(1);
Reg00=0x22; //结束或放弃DMA
delay(1);
//============================
}
//=========================================
d.total = RxEthnetFrameBuffer[0];
bnry = d.e.high - 1;
if(bnry<0x4c) bnry=0x7f;
page(0);
delay(10);
Reg03=bnry; //write to bnry
delay(1);
Reg07=0xff;
return(1); //have new packet
}
}
else
return(0);
}
void nic_recieve()
{
unsigned int x,length ;
unsigned int temp ;
unsigned int flag;
do{
flag = RecFrame();
temp=RxEthnetFrameBuffer[8];
if(temp==Frame_IP)
{
if(RxEthnetFrameBuffer[20]==DATAPORT) //有四个字节的头,1000字节的数据
{
header1=RxEthnetFrameBuffer[23]&0x00ff; //low byte
header2=RxEthnetFrameBuffer[23]>>8;
header3=RxEthnetFrameBuffer[24]&0x00ff;
header4=RxEthnetFrameBuffer[24]>>8;
getorder();
if(header2==MPEG1)
{
for(x=25;x<(25+FRAMESIZE);x++)
{
if(header1==PROGRAM)
{
DA_wptr++;
if(DA_wptr>=(unsigned int)PCMSIZE)
DA_wptr=0;
videobuf[DA_wptr]=change_byte(RxEthnetFrameBuffer[x]);
}
}
if(header1==PROGRAM) //video
request_pack++;
}
else if(header2==MPEG1)
{
*(IMR)|=0x0800; //开接收1中断
}
}
}
else if(temp==Frame_ARP) //ARP
{
for(x=9;x<length;x++)
RxEthnetFrameBuffer[x-9]=RxEthnetFrameBuffer[x];
memcpy(&r_ipaddr,RxEthnetFrameBuffer+12,2);
if(nod_ipaddr.addr2_1==r_ipaddr.addr2_1)
if(nod_ipaddr.addr4_3==r_ipaddr.addr4_3)
{
if(RxEthnetFrameBuffer[3]==0x01<<8) //自已请求,对方ARP应答
{
memcpy(&MAC_rec,RxEthnetFrameBuffer+4,3); //复制对方的MAC
memcpy(&r_ipaddr,RxEthnetFrameBuffer+7,2); //复制对方的IP
send_arp(&r_ipaddr,2);
}
if(RxEthnetFrameBuffer[3]==0x02<<8) //自已请求,对方ARP应答
{
memcpy(&MAC_server,RxEthnetFrameBuffer+4,3);
arp_ack=1;
}
}
}
}while(flag);
}
unsigned short change_byte(unsigned short value)
{
unsigned short temp;
temp=(value<<8)|(value>>8);
return(temp);
}
void getorder( )
{
if(header1==PROGRAM)
{
dat_type=MP3_DAT;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -