?? rtl8019.c
字號:
#include "cpu_reg.h"
#include "RTL8019.h"
struct ipaddr server_ipaddr,nod_ipaddr,r_ipaddr;
struct mac MAC_server,MAC_broad,MAC_rec;
struct mac MAC_self,MAC_nod;
struct iphdr t_iphdr;
struct igmphdr t_igmphdr;
struct udphdr t_udphdr;
struct pre_udphdr pre_udphdr1;
Uint16 TxNetBuf[1518/2];
Uint16 RxNetBuf[1518/2];
Uint16 TxBufFlag;
Uint16 bnry,curr;
extern Uint16 ms;
void InitProtocal(void);
/**********************************************************************
**函數原型: void delay_ms(uint ms_number)
**入口參數: ms_number: 延時的毫秒數
**出口參數: 無
**返 回 值: 無
**說 明: 延時預定的時間,延時時間與特定的處理器有關
************************************************************************/
void Delay_MS(Uint16 ms_number)
{
Uint16 i,j;
for (i=0;i<ms_number;i++)
{
for(j = 0;j < ms_number;j++) { ; }
}
}
//==============================================================================
/**********************************************************************
**函數原型: 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()
{
Delay_MS(10);
/**********************************************************************
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; //使芯片處于停止模式,這時進行寄存器設置
InitProtocal();
Delay_MS(10); //延時10毫秒,確保芯片進入停止模式
page(0);
Reg0a= 0x00; //清rbcr0
Reg0b= 0x00; //清rbcr1
Reg0c= 0xe0; //RCR,監視模式,不接收數據包
Reg0d= 0xe2; //TCR,loop back模式
Reg01= 0x4c; //pstart = 0x4c
Reg02= 0x80; //pstop = 0x80
Reg03= 0x4c; //bnry = 4c
Reg04= 0x40; //TPSR,發送起始頁寄存器
Reg07= 0xff; //清除所有中斷標志位,中斷狀態寄存器
Reg0f= 0x00; //中斷屏蔽寄存器清0,禁止中斷
Reg0e= 0xc9; // 數據配置寄存器,16位dma方式
page(1);
Reg07= 0x4d;
Reg08= 0x00;
Reg09= 0x00;
Reg0a= 0x00;
Reg0b= 0x00;
Reg0c= 0x00;
Reg0d= 0x00;
Reg0e= 0x00;
Reg0f= 0x00;
Reg01= MAC_self.addr2_1;
Reg02= MAC_self.addr2_1>>8;
Reg03= MAC_self.addr4_3;
Reg04= MAC_self.addr4_3>>8;
Reg05= MAC_self.addr6_5;
Reg06= MAC_self.addr6_5>>8;
page(0);
Reg0c= 0xce; //將芯片設置成正常模式,跟外部網絡連接
Reg0d= 0xe0;
Reg00= 0x22; //啟動芯片開始工作
//-----------------------------------
Reg07= 0xff; //清除所有中斷標志位
}
void InitProtocal(void)
{
/* server_ip=192.168.1.40 */
server_ipaddr.addr2_1 =192;
server_ipaddr.addr2_1 +=(Uint16)168<<8;
server_ipaddr.addr4_3 =1;
server_ipaddr.addr4_3 +=(Uint16)40<<8;
//192.168.1.1
nod_ipaddr.addr2_1 =192;
nod_ipaddr.addr2_1 +=(Uint16)168<<8;
nod_ipaddr.addr4_3 =1;
nod_ipaddr.addr4_3 +=(1<<8);
t_iphdr.tos_version =69;
t_iphdr.tos_version +=(Uint16)0<<8; //usally not use
t_iphdr.id =20; //++IP_id;
t_iphdr.id +=(Uint16)52<<8;
t_iphdr.frag_off =0;
t_iphdr.protocal_ttl =128; //usally 32 or 64
t_iphdr.protocal_ttl +=(Uint16)17<<8;
t_iphdr.saddr =nod_ipaddr;
t_iphdr.daddr =server_ipaddr;
//UDP PORT
t_udphdr.sport =1024; //1*256+0x08,9901
t_udphdr.dport =1025; //1*256+0x07,9901
pre_udphdr1.saddr=t_iphdr.saddr;
pre_udphdr1.daddr=t_iphdr.daddr;
pre_udphdr1.protocal_value =0;
pre_udphdr1.protocal_value +=17<<8; //UDP
// FF-FF-FF-FF-FF-FF
MAC_broad.addr2_1 =255;
MAC_broad.addr2_1 +=(Uint16)255<<8;
MAC_broad.addr4_3 =255;
MAC_broad.addr4_3 +=(Uint16)255<<8;
MAC_broad.addr6_5 =255;
MAC_broad.addr6_5 +=(Uint16)255<<8;
// 02-E0-4C-A0-7E-7A
MAC_self.addr2_1 =1<<1;
MAC_self.addr2_1 +=(Uint16)224<<8;
MAC_self.addr4_3 =76;
MAC_self.addr4_3 +=(Uint16)160<<8;
MAC_self.addr6_5 =126;
MAC_self.addr6_5 +=(Uint16)122<<8;
// 00-E0-4C-A0-7E-7A
MAC_nod.addr2_1 =0;
MAC_nod.addr2_1 +=(Uint16)224<<8;
MAC_nod.addr4_3 =76;
MAC_nod.addr4_3 +=(Uint16)160<<8;
MAC_nod.addr6_5 =126;
MAC_nod.addr6_5 +=(Uint16)122<<8;
}
//=============================================================================
/**********************************************************************
**函數原型: 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++) TxNetBuf[i]=0;
length=60/2;
}
page(0); //切換至第0頁
length = length <<1;
TxBufFlag=!TxBufFlag; //設置兩個發緩區,提高發送效率
if(TxBufFlag)
{Reg09=0x40 ;} //設置發送頁地址
else
{Reg09=0x46 ;} //設置發送頁地址
Reg08=0x00; //read page address low
Reg0b = length >>8; //寫發送長度高位
Reg0a = length & 0x00ff; //寫發送長度低位
Reg00=0x12; //write dma, page0
for(i=0;i<length/2;i++)
{
Reg10 = TxNetBuf[i];
}
/***************************************/
//以下為終止DMA操作
Reg0b=0x00;
Reg0a=0x00;
Reg00=0x22; //結束或放棄DMA操作
/***************************************/
for(i=0;i<6;i++) //最多重發6次
{
for(ii=0;ii<1000;ii++)
{//檢查CR寄存器的txp位是否為低,為1說明正在發送,為0說明發完或出錯放棄
if((Reg00&0x04)==0)
{ break; }
}
if((Reg04&0x01)!=0)//表示發送成功,判斷發送狀態寄存器TSR,決定是否出錯
{break;};
Reg00=0x3e;
}
Reg07=0xff;
if(TxBufFlag)
{
Reg04=0x40; //txd packet start;
}
else
{
Reg04=0x46; //txd packet start;
}
Reg06=length>>8; //high byte counter
Reg05=length&0xff;//low byte counter
Reg07=0xff;
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;
page(0);
bnry = Reg03; //bnry page have read 讀頁指針
bnry = bnry & 0x00FF;
page(1);
curr = Reg07; //curr writepoint 8019寫頁指針
curr = curr & 0x00FF;
page(0);
if((curr==0))return(0); //讀的過程出錯
bnry++;
if(bnry>0x7f) bnry=0x4c;
if(bnry!=curr) //此時表示有新的數據包在緩沖區里
{ //在任何操作都最好返回page0
page(0);
//=======================================
Reg09=bnry; //讀頁地址的高字節
Reg08=0x00; //讀頁地址的低字節
Reg0b=0x00; //讀取字節計數高字節
Reg0a=18; //讀取字節計數高字節
Reg00=0x0a; //啟動Remote DMA讀操作
for(i=0;i<9;i++) //讀取一包的前18個字節:4字節的8019頭部,6字節目的地址,6字節原地址,2字節協議
{
RxNetBuf[i]=Reg10;
}
//=======================================中止DMA操作
Reg0b=0x00; //
Reg0a=0x00; //
Reg00=0x22; //結束或放棄DMA操作
//=======================================
d.total = RxNetBuf[0];
length = RxNetBuf[1];
if(((d.e.high & 0x01)==0)||(d.e.low > 0x7f) || (d.e.low < 0x4c)||( length > 1517))
{//接收狀態錯誤或下一數據包的起始頁地址錯誤或接收的數據包長度>1500字節
page(1);
curr=Reg07; //page1
page(0); //切換回page0
bnry = curr -1;
if(bnry < 0x4c) bnry =0x7f;
Reg03=bnry; //write to bnry
Reg07=0xff;
return(0);
}
//=============================================
else//表示數據包是完好的.讀取剩下的數據
{
Temp = SwapByte(RxNetBuf[8]);
if((Temp == IP_FRAME)||(Temp == ARP_FRAME))
{ //協議為IP或ARP才接收
Reg09 = bnry; //read page address high
Reg08 = 4; //read page address low
Reg0b = length>>8; //read count high
Reg0a = length & 0xff;//read count low;
Reg00=0x0a; //read dma
length=(length+1)/2;
for(ii=2;ii<length+2;ii++)
{
RxNetBuf[ii]=Reg10;
}
//================終止DMA操作
Reg0b=0x00; //read count high
Reg0a=0x00; //read count low;
Reg00=0x22; //結束或放棄DMA
//============================
}
//=========================================
d.total = RxNetBuf[0];
bnry = d.e.low - 1;
if(bnry<0x4c) bnry=0x7f;
page(0);
Reg03=bnry; //write to bnry
Reg07=0xff;
return(1); //have new packet
}
}
else
return(0);
}
//============================================================
void LoadEnetHrd(Uint16 MAC_type,Uint16 PROTO_type)
{
if(MAC_type==0) //添加目的MAC地址
memcpy(TxNetBuf,&MAC_server,3);
else if(MAC_type==BroadCast)
memcpy(TxNetBuf,&MAC_broad,3);
else if(MAC_type==RequestArp)
memcpy(TxNetBuf,&MAC_broad,3);
else if(MAC_type==AnswerArp)
memcpy(TxNetBuf,&MAC_rec,3);
else if(MAC_type==Nod)
memcpy(TxNetBuf,&MAC_nod,3);
memcpy(TxNetBuf+3,&MAC_self,3); //添加源MAC地址
if(PROTO_type==UDP) //協議類型
*(TxNetBuf+6)=8+(0<<8);
else if(PROTO_type==ARP)
*(TxNetBuf+6)=8+(6<<8);
else if(PROTO_type==LSS) //協議類型
*(TxNetBuf+6)=8+(8<<8);
}
void LoadArp(struct ipaddr *ip,Uint16 type)
{
struct arp arp1;
arp1.hard_type = (Uint16)1<<8;
arp1.proto_type = (Uint16)((2048<<8)+(2048>>8));
arp1.proto_hard_length = 6;
arp1.proto_hard_length += (Uint16)4<<8;
arp1.send_macaddr =MAC_self;
arp1.send_ipaddr =nod_ipaddr;
if (type==RequestArp)
{
arp1.op_code = 0x01<<8;
arp1.rec_macaddr.addr2_1 =0;
arp1.rec_macaddr.addr4_3 =0;
arp1.rec_macaddr.addr6_5 =0;
}
else{
arp1.op_code = 0x02<<8;
arp1.rec_macaddr =MAC_rec;
}
arp1.rec_ipaddr =*ip;
memcpy(TxNetBuf+7,&arp1,sizeof(arp1));
}
void LoadIp(struct ipaddr *ip,Uint16 protocal)
{
struct iphdr tip;
tip.tos_version = 0x45;
tip.tos_version += (Uint16)0<<8; //usally not use
tip.id =20; //++IP_id;
tip.id +=(Uint16)52<<8;
tip.frag_off =0;
tip.protocal_ttl =128; //usally 32 or 64
tip.saddr =nod_ipaddr;
tip.daddr = *ip;
if (protocal==TCP)
t_iphdr.protocal_ttl +=(Uint16)6<<8;
else if (protocal==UDP)
t_iphdr.protocal_ttl +=(Uint16)17<<8;
else if (protocal==ICMP)
t_iphdr.protocal_ttl +=(Uint16)1<<8;
else if (protocal==IGMP)
t_iphdr.protocal_ttl +=(Uint16)2<<8;
memcpy(TxNetBuf+7,&tip,sizeof(tip));
}
void ArpRequest(struct ipaddr *ip)
{
LoadEnetHrd(RequestArp,ARP);
LoadArp(ip,RequestArp);
SendFrame(TxNetBuf,30);
}
void ArpAnswer(struct ipaddr *ip)
{
LoadEnetHrd(AnswerArp,ARP);
LoadArp(ip,AnswerArp);
SendFrame(TxNetBuf,30);
}
Uint16 SwapByte(Uint16 value)
{
Uint16 temp;
temp=(value<<8)|(value>>8);
return(temp);
}
//======================= END ===============================
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -