📄 rtl8019.c
字号:
#include <reg51.h>
#include <RTL8019.h>
#include <gnet.h>
void delay_ms(uchar ms_number)
{
uchar i,j;
for(j=0;j<ms_number;j++)
for(i=0;i<90;i++);
}
/******************选择8019寄存器页面子程序************************/
void page(uchar pagenumber)
{
uchar data temp;
temp=reg00;
temp=temp&0x3B ; //注意txp位不能要
pagenumber=pagenumber <<6;
temp=temp | pagenumber;
reg00=temp;
}
/****************************复位网卡子程序************************/
void rtl8019as_rst()
{
uchar temp;
// RST8019=1;
delay_ms(200);
// RST8019=0;
temp=reg1f;//读网卡的复位端口
reg1f=temp; //写网卡的复位端口
}
/******************读出网卡的物理地址子程序************************/
//存到my_ethernet_address.bytes[6]里
void ReadRtl8019NodeID(void)
{
unsigned char data i;
page(0);
reg09=0;//RSAR1 网卡上的RAM的起始地址高8位
reg08=0;//RSAR0 网卡上的RAM的起始地址低8位
reg0b=0;//RBCR1 要读取的字节数的计数(高8位)
reg0a=12;//RBCR0 要读取的字节数的计数(低8位) 读取12个字节
reg00=0x0a; //读ram
for (i=0;i<6;i++)
{
//my_hwaddr[i]=reg10;
//my_hwaddr[i]=reg10;////读取一个重复的字节,这个字节被丢弃
}
}
void initNIC()
{
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 rtl8019as_init()//RTL8019AS网卡初始化
{
rtl8019as_rst();//重启网卡
reg00=0x21; //选择页0的寄存器,网卡停止运行,因为还没有初始化。
delay_ms(10); //延时10毫秒,确保芯片进入停止模式
//使芯片处于mon和loopback模式,跟外部网络断开
page(0); //选择第0页寄存器
reg0a=0x00; //RBCR0
reg0b=0x00; //RBCR1
reg0c=0xE0; //RCR,不接受任何数据包
reg0d=0xE2; //loop back mode
//使用0x40-0x4B为网卡的发送缓冲区,共12页,刚好可以存储2个最大的以太网包。
//使用0x4c-0x7f为网卡的接收缓冲区,共52页。
reg01=0x4C; //PSTART 接收缓冲区范围
reg02=0x80; //PSTOP
reg03=0x4C; //BNRY
reg04=0x40; //TPSR 发送缓冲区范围
reg07=0xFF; //ISR 清除所有中断标志位
reg0f=0x05; //IMR开放数据包错误接收中断和数据包无错误接收中断
reg0e=0xC8; //DCR使用FIFO缓存,普通模式,8位数据DMA
page(1); //选择页1的寄存器
reg07=0x4D; //CURR
reg08=0x00; //MAR0
reg09=0x41; //MAR1
reg0a=0x00; //MAR2
reg0b=0x80; //MAR3
reg0c=0x00; //MAR4
reg0d=0x00; //MAR5
reg0e=0x00; //MAR6
reg0f=0x00; //MAR7
initNIC(); //初始化MAC地址
//将网卡设置成正常的模式,跟外部网络连接
page(0);
reg0c=0xCC; //RCR接收到的帧存入缓冲环
reg0d=0xE0; //TCR启用CRC自动生成和自动校验,工作在正常模式
reg00=0x22; //这时让芯片开始工作?
reg07=0xFF; //清除所有中断标志位
}
bit recv_packet(union netcard *rxdnet)//RTL8019AS收包子程序
{
unsigned char i;
unsigned int ii;
unsigned char bnry,curr,isr;
page(0); //选择第0页寄存器
isr=reg07; //读取ISR寄存器
if((isr&0x04)==4) //判断PXE是否为1
return 0; //数据包接收错误
if((isr&0x01)==1) //判断PRX是否为1
{ //数据包接收正确
reg07=0xFF; //清除中断标志位
bnry=reg03; //读取BNRY寄存器
page(1); //选择页面1
curr=reg07; //读取CURR寄存器
page(0); //选择页面0
if(curr==0)
return 0; //读的过程出错
bnry=bnry++;
if(bnry>0x7F)
bnry=0x4C;
if(bnry!=curr) //此时表示有新的数据包在缓冲区里
{
//读取一包的前18个字节:4字节的8019头部,6字节目的地址,6字节原地址,2字节协议
page(0); //在任何操作都最好返回page0
reg09=bnry-1; // BNRY寄存器的值写入RSAR1
reg08=0x00; // 00写入RSAR0
reg0b=0x00; // 00H写入远程DMA字节计数寄存器RBCR1
reg0a=0x12; // #12H写入远程DMA字节计数寄存器RBCR0
reg00=0x0A; // 启动远程DMA读
for(i=0;i<18;i++) //读取18个字节的数据
rxdnet->bytes.bytebuf[i]=reg10;
i=rxdnet->bytes.bytebuf[3]; //将长度字段的高低字节掉转
rxdnet->bytes.bytebuf[3]=rxdnet->bytes.bytebuf[2];
rxdnet->bytes.bytebuf[2]=i;
rxdnet->etherframe.length=rxdnet->etherframe.length-4;//去掉4个字节的CRC
//读入的数据包有效
if(((rxdnet->bytes.bytebuf[0]&0x01)==0)
||(rxdnet->bytes.bytebuf[1]>0x7F)
||(rxdnet->bytes.bytebuf[1]<0x4C)
||(rxdnet->bytes.bytebuf[2]>0x06))
{
//接收状态错误,或者next_page_start错误或者长度错误,将丢弃所有数据包
page(1);
curr=reg07; //page1
page(0); //切换回page0
bnry=curr-1;
if(bnry<0x4C)
bnry=0x7F;
reg03=bnry; //write to bnry
return 0;
}
else
//数据包是完好的.读取剩下的数据
{
//协议为IP或ARP才接收
if((rxdnet->etherframe.protocal==0x0800)
||(rxdnet->etherframe.protocal==0x0806))
{
reg09=bnry; // BNRY寄存器的值写入RSAR1
reg08=4; // 04写入RSAR0
reg0b=rxdnet->etherframe.length>>8; //写入远程DMA字节计数寄存器RBCR1
reg0a=rxdnet->etherframe.length&0xFF;//写入远程DMA字节计数寄存器RBCR0
reg00=0x0A; //启动远程DMA读
for(ii=4;ii<rxdnet->etherframe.length+4;ii++)
rxdnet->bytes.bytebuf[ii]=reg10; //从端口10读数据
}
bnry=rxdnet->bytes.bytebuf[1]-1;//
if(bnry<0x4C)
bnry=0x7F;
reg03=bnry;
return 1;
}
}
return 0;
}
return 0;
}
//发送一个数据包的命令,长度最小为60字节,最大1514字节需要发送的数据包要先存放在txdnet缓冲区
void send_packet(union netcard *txdnet, unsigned int length)
{
unsigned char i;
unsigned int ii;
page(0); //选择第0页寄存器
if (length<60) length=60;
reg00=0x12; // 开始远程DMA操作
for (ii=4;ii<length+4;ii++) //数据通过10H端口写入RTL8019AS
reg10=txdnet->bytes.bytebuf[ii];
reg09=0x40; //RSAR1 写入远程DMA的起始地址高八位
reg08=0x00; //RSAR0 写入远程DMA的起始地址高八位
reg0b=length>>8; //RBCR1 数据包字节长度高八位
reg0a=length&0xFF; //RBCR0 数据包长度字节低八位
for(i=0;i<6;i++){ //最多重发6次
for(ii=0;ii<1000;ii++)
if((reg00&0x04)==0) //检查TXP为是否为0
break;
if((reg04&0x01)!=0) //判断RTX是否为1
break; //表示发送成功
reg00=0x1E;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -