📄 rtl8019as.c
字号:
#include <string.h>
#include <stdio.h>
#include "rtl8019as.h"
#include "..\inc\44b.h"
#include "..\inc\44blib.h"
#include "..\inc\def.h"
#include "..\inc\MyType.h"
#include "..\inc\NetProtocol.h"
extern BYTE g_SrcIP_Addr[];
extern BYTE g_SrcMAC_Addr[];
void DelayMs(unsigned short MSecond);
void RTL8019AS_Rreset();
void Page(unsigned char PageNo);
void __irq rtl8019INT(void)
{
unsigned char HSYNC;
HSYNC = rEXTINTPND; //read the interrup condition
rEXTINTPND=0xf; //clear ExINTPEND reg
rI_ISPC |= BIT_EINT4567; //clear pending bit
OUT_B(P0_ISR, 0xFF);
}
void InitRTL8019AS()
{
unsigned char val;
short i;
RTL8019AS_Rreset(); // 网卡复位
OUT_B(P_CR, 0x21); // 置CR:选择页0的寄存器,网卡停止运行,因为还没有初始化;
DelayMs(10); // 延时10毫秒,确保芯片进入停止模式;
OUT_B(P0_PSTART, 0x4C); // 设接收缓冲区起始地址为0x4c;
OUT_B(P0_PSTOP, 0x80); // 设接收缓冲区结束地址为0x80(第0x7f页有效);
OUT_B(P0_BNRY, 0x4C); // 设接收缓冲区读页指针为0x4c;
OUT_B(P0_TPSR, 0x40); // 设发送缓冲区起始地址为0x40。
OUT_B(P0_TCR, 0xE0);
OUT_B(P0_ISR, 0xFF); // 清除中断状态寄存器所有中断标志位;
OUT_B(P0_IMR, 0x00); // 设中断屏蔽寄存器,屏蔽所有中断。
OUT_B(P0_DCR, 0xC8); // 置数据配置寄存器:FIFO开始;高字节MD15-8,低字节MD7-0;8位DMA方式。
// OUT_B(P0_RCR, 0xDF);
OUT_B(P0_RCR, 0xDC);
OUT_B(P0_RBCR0, 0x00); // 给远程DMA字节计数器低字节清0;
OUT_B(P0_RBCR1, 0x00); // 给远程DMA字节计数器高字节清0;
OUT_B(P_CR, 0x61);
DelayMs(10);
OUT_B(P1_CURR, 0x4D); // 置当前页寄存器:指向当前正在写的页的下一页,
// 初始化时指向0x4c+1=0x4d。
for(i = 0; i < MAC_ADDR_LEN; i++)
{
OUT_B(P1_PAR0+i, g_SrcMAC_Addr[i]); // 设物理地址寄存器i值
}
for(i = 0; i < 8; i++)
{
OUT_B(P1_MAR0+i, 0x00); // 设组播地址寄存器i值
}
OUT_B(P_CR, 0x22); // 设命令寄存器:选择页0的寄存器,让8019芯片开始工作;
}
void S3c44b0x_init_for_RTL8019(void)
{
U32 i = 0;
//PCONB PB7 = 1 select nGCS3
rPCONB |= (0x01<<8);
//PCONG PG3->7:6 = 11 select EINT4
rPCONG |= (0x03<<8);
//rPUPG PG3->3 = 1 pull up enable
rPUPG |= (0x01<<4);
//rEXTINT EINT3->14:12 = 000 low
// rEXTINT |= (0x01<<14);
//rEXTINT &= ~(0x01<<13);
//rEXTINT &= ~(0x01<<12);
rEXTINT &= ~(0x01<<18);
rEXTINT &= ~(0x01<<17);
rEXTINT &= ~(0x01<<16);
//nGCS2 16BIT no nWBE no wait
//11:ST2 =0 , 10: WS2 =0 , 9.8: DW2 = 01
// rBWSCON |= (0x01<<11);
// rBWSCON &= ~(0x01<<10);
// rBWSCON &= ~(0x01<<9);
// rBWSCON |= (0x01<<8);
rBWSCON |= (0x01<<15);
rBWSCON &= ~(0x01<<14);
rBWSCON &= ~(0x01<<13);
rBWSCON &= ~(0x01<<12);
//B2_Tacs EQU 0x3 ;4clk
//B2_Tcos EQU 0x3 ;4clk
//B2_Tacc EQU 0x7 ;14clk
//B2_Tcoh EQU 0x3 ;4clk
//B2_Tah EQU 0x3 ;4clk
//B2_Tacp EQU 0x3 ;6clk
//B2_PMC EQU 0x0 ;normal(1data)
rBANKCON3 = 0x0700;
//rPCONE PE3->7:6 = 01 output
rPCONE &= ~(0x01<<7);
rPCONE |= (0x01<<6);
//rPUPE PE3->3 = 1 pull up enable
rPUPE |= (0x01<<3);
//rPDATE PE3 = 1 -> 0 => rst 8019
rPDATE |= (0x01<<3);
for(i=0;i<200000;i++);
rPDATE &= ~(0x01<<3);
for(i=0;i<200000;i++);
rNCACHBE0 = (((((0x8000000)>>12)+1)<<16)|((0x6000000)>>12));
rSYSCFG= SYSCFG_8KBn;
}
void DelayMs(unsigned short MSecond)
{
int i,j;
for(i=0; i<MSecond;i++)
{
for(j=0; j< 5000;j++)
;
}
}
void Page(unsigned char PageNo) // 设置寄存器页数
{
unsigned char ByteVal;
//Uart_Printf("PageNo=[%d].\n",PageNo);
ByteVal=IN_B(P_CR);
//Uart_Printf("ByteVal.in=[%x].\n",ByteVal);
ByteVal=(ByteVal&0x3f)|(PageNo<<6)|0x20;
//Uart_Printf("ByteVal.out=[%x].\n",ByteVal);
OUT_B(P_CR, ByteVal);
}
void RTL8019AS_Rreset() // 网卡复位
{
unsigned char val;
val = IN_B(P_RESET);
OUT_B(P_RESET, val);
DelayMs(100);
}
/*
RTL8019AS接收帧格式:
接收状态(1),下一页指针(1),以太网帧长度(2),目的IP地址DA(6),源IP地址SA(6),类型TYPE/长度LEN(2),数据域DATA(<=1500),
填充PAD(可选),校验FCS(4)
*/
BYTE RTL8019AS_RcvPacket(Frame8019 *Packet)
{
static int currCount = 0;
BYTE i;
BYTE reProtocol = PROTOCOL_NULL;
short j;
WORD frameLen = 0;
WORD packetLen = 0;
#define PACK_HEAD_LEN 18
unsigned char Bnry, Curr;
Page(0); // 选择页0的寄存器
Bnry=IN_B(P0_BNRY); // 读接收缓冲区读页指针
Page(1); // 选择第1页的寄存器
Curr=IN_B(P1_CURR); // 读接收缓冲区写页指针
Page(0);
if (Curr==0 || Curr > 0x7f || Curr < 0x4c)
return PROTOCOL_NULL; // 读的过程出错返回0
Bnry++;
//Uart_Printf("Bnry = %x, Curr = %x\n", Bnry, Curr);
if (Bnry>0x7F || Bnry < 0x4c)
Bnry=0x4C;
if (Bnry!=Curr)
{ // 此时表示有新的数据包在缓冲区里;
// 读取一包的前18个字节:4字节的8019头部,
// 6字节目的地址,6字节源地址,2字节协议
Page(0); // 返回到页0
OUT_B(P0_RSAR1, Bnry); // 设远程(DMA)起始地址寄存器1(高字节)为Bnry
OUT_B(P0_RSAR0, 0x00); // 设远程(DMA)起始地址寄存器0(低字节)为0
OUT_B(P0_RBCR1, 0x00); // 设远程字节计数寄存器1(高字节)为0
OUT_B(P0_RBCR0, PACK_HEAD_LEN); // 设远程字节计数寄存器0(低字节)[准备读包头18字节]
OUT_B(P_CR, 0x0A); // 设命令寄存器:选择页0, 远程DMA读, 开始执行。
Uart_Printf("\nRTL8019AS_RcvPacket %d\n", ++currCount);
//Uart_Printf("EtherPacket Header :\n");
for (i=0; i<PACK_HEAD_LEN; i++) // 读18个字节
{
*((BYTE *)Packet + i) = IN_B(P_DMA_PORT);
//Uart_Printf(" %x,", *((BYTE *)Packet + i));
}
//Uart_Printf("\n");
frameLen = (Packet->Length[1]<<8) + Packet->Length[0];
frameLen -= 4; // 去掉4个字节的CRC,表示读入的数据包有效
// if(((Packet->Status & 0x01) == 0)||(Packet->NextPage > 0x7F)||
if((Packet->NextPage > 0x7F)||
(Packet->NextPage < 0x4C)||(frameLen > 1514))
{ // 接收状态错误, 或者NextPageStart错误,或者长度错误, 将丢弃所有数据包
Uart_Printf(" RTL8019AS_RcvPacket WRONG \n");
//Uart_Printf("Status 0x%.2x NextPage 0x%.2x 0x%.2x%.2x %d\n",
// Packet->Status, Packet->NextPage, Packet->Length[1],Packet->Length[0], frameLen);
Page(1); // 选页1的寄存器
Curr=IN_B(P1_CURR); // 读接收缓冲区写页指针
Page(0); // 选页0的寄存器
Bnry=Curr-1;
if (Bnry<0x4C)
Bnry=0x7F;
OUT_B(P0_BNRY, Bnry); // 写接收缓冲区读页指针
//Uart_Printf("WRONG Bnry = %x, Curr = %x\n", Bnry, Curr);
return PROTOCOL_NULL;
}
else
{ // 表示数据包是完好的.读取剩下的数据
if (((Packet->Status & 0x01) == 1) && (Packet->Protocol[0] == 0x08) && (Packet->Protocol[1] ==0x00 || Packet->Protocol[1] ==0x06)) // ARP包0x0806
{
// 协议为IP或ARP才接收
OUT_B(P0_RSAR1, Bnry); // 设远程起始地址寄存器1(高字节)
OUT_B(P0_RSAR0, PACK_HEAD_LEN); // 设远程起始地址寄存器0(低字节)
packetLen = frameLen - 14;
OUT_B(P0_RBCR1, packetLen >>8); // 设远程字节计数寄存器1(高字节)
OUT_B(P0_RBCR0, packetLen & 0xff); // 设远程字节计数寄存器0(高字节)
OUT_B(P_CR, 0x0A); // 设命令寄存器:选择页0, 远程读, 开始执行。
for (j = 0; j < packetLen; j++)
Packet->Packet[j]=IN_B(P_DMA_PORT); // 读远程DMA口
reProtocol = (Packet->Protocol[1] ==0x06) ? PROTOCOL_ARP : PROTOCOL_IP;
}
else
{
reProtocol = PROTOCOL_NULL;
}
Bnry=Packet->NextPage-1; // 下一页指针减1
if (Bnry<0x4C)
Bnry=0x7F;
OUT_B(P0_BNRY, Bnry); // 设接收缓冲区读页指针
return reProtocol; // 读包成功,返回1
}
}
return PROTOCOL_NULL; // 不成功,返回0
}
// ne2000 发包子程序
// 发送一个数据包的命令, 长度最小为60 字节,
// 最大1514 字节需要发送的数据包要先存放在 txdnet 缓冲区
void RTL8019AS_SndPacket(Frame8019 *Packet, short Length)
{
static unsigned char TransBufSwitch=0;
unsigned char i;
short j;
Page(0); // 选择页0的寄存器
if (Length<60)
Length=60;
TransBufSwitch=!TransBufSwitch;
if (TransBufSwitch)
OUT_B(P0_RSAR1, 0x40); // 设远程(DMA)起始地址寄存器1=前缓冲区首页
else
OUT_B(P0_RSAR1, 0x46); // 设远程(DMA)起始地址寄存器1=后缓冲区首页
OUT_B(P0_RSAR0, 0x00); // 设远程(DMA)起始地址寄存器0(低字节)值
OUT_B(P0_RBCR1, (BYTE)(Length>>8)); // 设远程字节计数器寄存器1(高字节)
OUT_B(P0_RBCR0, (BYTE)(Length&0xFF)); // 设远程字节计数器寄存器0(低字节)
OUT_B(P_CR, 0x12); // 设命令寄存器:选择0页寄存器, 远程写DMA, 起始命令。
for (j=4; j<Length+4; j++)
OUT_B(P_DMA_PORT, *((BYTE *)Packet + j)); // 写远程DMA口
for (i=0; i<6; i++) // 最多重发6 次
{
for (j=0; j<1000; j++)
if ((IN_B(P_CR)&0x04)==0) // 读命令寄存器,检查TXP:为是否为低(传送结束或中止)
break;
if ((IN_B(P0_TSR)&0x01)!=0) // 读发送状态寄存器,检查PTX:发送成功为1时,退出;
break;
OUT_B(P_CR, 0x3E); // 设命令寄存器:选择页0,中止DMA,执行发送。
}
// 发送新的数据帧
if (TransBufSwitch)
OUT_B(P0_TPSR, 0x40); // 设发送页起始寄存器=前缓冲区首页;
else
OUT_B(P0_TPSR, 0x46); // 设发送页起始寄存器=后缓冲区首页;
OUT_B(P0_TBCR1, (BYTE)(Length>>8)); // 设发送字节计数器1(高字节)
OUT_B(P0_TBCR0, (BYTE)(Length&0xFF)); // 设发送字节计数器0(低字节)
OUT_B(P_CR, 0x3E); // 设命令寄存器:选择页0,中止DMA,执行发送。
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -