📄 hardware.c
字号:
#define HARDWARE_ENTITY
/*
****************************************************************
*
*
* rtl8019 hardware driver
* file:hardware.c
* created by gm
* data 2008.8.20
*
*
*
****************************************************************
*/
#include "includes.h"
INT8U My_Mac[]=MY_MAC_ID;
INT8U My_Ip[]=MY_IP_ID;
/*
************************************************
*
* Read and Write rtl8019 chip
*
*描述:读写指定地址处数据的函数
*参数:
* addr rtl内部地址
* data 要写入的数据,16bit
*返回值:
*
************************************************
*/
static unsigned char get_reg(unsigned int address)
{
return (*(volatile unsigned char *)address);
}
//读芯片内部寄存器函数
static void put_reg(unsigned int address,unsigned char data)
{
(*(volatile unsigned char *)address)=data;
}
static void udelay(unsigned int i)
{
unsigned j;
for(;i!=0;i--)
for(j=0;j<2000;j++);
}
static void eth_reset(void)
{
unsigned char temp;
temp=get_reg(RTL8019_RESET);
put_reg(RTL8019_RESET,temp);
put_reg(RTL8019_INTERRUPTSTATUS,0xff);
udelay(200);
}
void rtl8019_get_enetaddr(unsigned char *addr)
{
unsigned int i;
unsigned char temp;
eth_reset();
put_reg (RTL8019_COMMAND, RTL8019_REMOTEDMARD);
put_reg (RTL8019_DATACONFIGURATION, 0x48);
put_reg (RTL8019_REMOTESTARTADDRESS0, 0x00);
put_reg (RTL8019_REMOTESTARTADDRESS1, 0x00);
put_reg (RTL8019_REMOTEBYTECOUNT0, 12);
put_reg (RTL8019_REMOTEBYTECOUNT1, 0x00);
put_reg (RTL8019_COMMAND, RTL8019_REMOTEDMARD);
for (i = 0; i < 6; i++)
{
temp = get_reg (RTL8019_DMA_DATA);
*addr++ = temp;
temp = get_reg (RTL8019_DMA_DATA);
// printf ("%x:", temp);
}
while ((!get_reg (RTL8019_INTERRUPTSTATUS) & 0x40));
//printf ("\b \n");
put_reg (RTL8019_REMOTEBYTECOUNT0, 0x00);
put_reg (RTL8019_REMOTEBYTECOUNT1, 0x00);
put_reg (RTL8019_COMMAND, RTL8019_PAGE0);
}
void eth_halt (void)
{
put_reg (RTL8019_COMMAND, 0x01);
}
int eth_init (void)
{
eth_reset ();
put_reg (RTL8019_COMMAND, RTL8019_PAGE0STOP);
put_reg (RTL8019_DATACONFIGURATION, 0x48);
put_reg (RTL8019_REMOTEBYTECOUNT0, 0x00);
put_reg (RTL8019_REMOTEBYTECOUNT1, 0x00);
put_reg (RTL8019_RECEIVECONFIGURATION, 0x00); /*00; */
put_reg (RTL8019_TRANSMITPAGE, RTL8019_TPSTART);
put_reg (RTL8019_TRANSMITCONFIGURATION, 0x02);
put_reg (RTL8019_PAGESTART, RTL8019_PSTART);
put_reg (RTL8019_BOUNDARY, RTL8019_PSTART);
put_reg (RTL8019_PAGESTOP, RTL8019_PSTOP);
put_reg (RTL8019_INTERRUPTSTATUS, 0xff);
put_reg (RTL8019_INTERRUPTMASK, 0x11); /*b; */
put_reg (RTL8019_COMMAND, RTL8019_PAGE1STOP);
put_reg (RTL8019_PHYSICALADDRESS0,My_Mac[0]);
put_reg (RTL8019_PHYSICALADDRESS1,My_Mac[1]);
put_reg (RTL8019_PHYSICALADDRESS2,My_Mac[2]);
put_reg (RTL8019_PHYSICALADDRESS3,My_Mac[3]);
put_reg (RTL8019_PHYSICALADDRESS4,My_Mac[4]);
put_reg (RTL8019_PHYSICALADDRESS5,My_Mac[5]);
put_reg (RTL8019_MULTIADDRESS0, 0x00);
put_reg (RTL8019_MULTIADDRESS1, 0x41);
put_reg (RTL8019_MULTIADDRESS2, 0x00);
put_reg (RTL8019_MULTIADDRESS3, 0x80);
put_reg (RTL8019_MULTIADDRESS4, 0x00);
put_reg (RTL8019_MULTIADDRESS5, 0x00);
put_reg (RTL8019_MULTIADDRESS6, 0x00);
put_reg (RTL8019_MULTIADDRESS7, 0x00);
put_reg (RTL8019_CURRENT, RTL8019_PSTART);
put_reg (RTL8019_COMMAND, RTL8019_PAGE0);
put_reg (RTL8019_TRANSMITCONFIGURATION, 0xe0); /*e0; */
return 0;
}
static unsigned char nic_to_pc (void)
{
unsigned char rec_head_status;
unsigned char next_packet_pointer;
unsigned char packet_length0;
unsigned char packet_length1;
unsigned short rxlen = 0;
unsigned int i = 4;
unsigned char current_point;
static INT8U REC_BUFF_NUM=0;
INT8U *REC_BUFF_PTR_BYTES;
/*
* The RTL8019's first 4B is packet status,page of next packet
* and packet length(2B).So we receive the fist 4B.
*/
put_reg (RTL8019_REMOTESTARTADDRESS1, get_reg (RTL8019_BOUNDARY));
put_reg (RTL8019_REMOTESTARTADDRESS0, 0x00);
put_reg (RTL8019_REMOTEBYTECOUNT1, 0x00);
put_reg (RTL8019_REMOTEBYTECOUNT0, 0x04);
put_reg (RTL8019_COMMAND, RTL8019_REMOTEDMARD);
rec_head_status = get_reg (RTL8019_DMA_DATA);
next_packet_pointer = get_reg (RTL8019_DMA_DATA);
packet_length0 = get_reg (RTL8019_DMA_DATA);
packet_length1 = get_reg (RTL8019_DMA_DATA);
put_reg (RTL8019_COMMAND, RTL8019_PAGE0);
/*Packet length is in two 8bit registers */
rxlen = packet_length1;
rxlen = (((rxlen << 8) & 0xff00) + packet_length0);
rxlen -= 4;
if (rxlen > PKTSIZE_ALIGN)
{
// printf ("hfrkpacket too big!\n");
while(1); //调试
}
//准备一个缓冲区,接收数据
if(REC_BUFF_NUM==MAX_BUFF_NUM)
{
REC_BUFF_NUM=0x00;
}
REC_BUFF_PTR_BYTES=REC_BUFF[REC_BUFF_NUM].bytes;
/*Receive the packet */
put_reg (RTL8019_REMOTESTARTADDRESS0, 0x04);
put_reg (RTL8019_REMOTESTARTADDRESS1, get_reg (RTL8019_BOUNDARY));
put_reg (RTL8019_REMOTEBYTECOUNT0, (rxlen & 0xff));
put_reg (RTL8019_REMOTEBYTECOUNT1, ((rxlen >> 8) & 0xff));
put_reg (RTL8019_COMMAND, RTL8019_REMOTEDMARD);
for (i = rxlen; i > 0; i--)
*REC_BUFF_PTR_BYTES++ = get_reg (RTL8019_DMA_DATA);
// Pass the packet up to the protocol layers.
Rec_Ethernet_Packed(REC_BUFF[REC_BUFF_NUM].bytes);
while (!(get_reg (RTL8019_INTERRUPTSTATUS)) & 0x40); // wait for the op.dma操作结束
put_reg (RTL8019_COMMAND, RTL8019_PAGE1);
current_point = get_reg (RTL8019_CURRENT);
put_reg (RTL8019_COMMAND, RTL8019_PAGE0);
put_reg (RTL8019_BOUNDARY, next_packet_pointer);
return current_point;
}
int eth_rx (void)
{
unsigned char temp, current_point;
put_reg(RTL8019_COMMAND, RTL8019_PAGE0);
while (1)
{
temp = get_reg (RTL8019_INTERRUPTSTATUS);
if (temp & 0x90) //若复位和溢出则重新初始化
{
eth_reset();
eth_init();
udelay(200);
return 0;
}
if (temp & 0x1)
{
do
{
put_reg (RTL8019_INTERRUPTSTATUS, 0x01);
current_point = nic_to_pc ();
} while (get_reg (RTL8019_BOUNDARY) != current_point);
}
if (!(temp & 0x1)) //直到接收缓冲为空为止
return 0;
}
}
/*
**************************************************
*函数:void Send_Packet(struct _pkst *TxData)
*功能:
* rtl发送数据的函数
* 由上层协议调用
*参数:
* TxData 发送数据的结构
*
*
*
**************************************************
*/
int eth_send(_pkst *TxData)
{
static INT8U Tx_Buff_Sel=0; //控制发送缓冲区的切换
_pkst *ExPtr;
INT8U *pdata; //发送时的数据指针
INT16U ii,length=0;
//计算本次发送数据的总长度
ExPtr=TxData;
while(ExPtr!=NULL)
{
length+=ExPtr->length;
ExPtr=ExPtr->next;
}
//开始远程dma将数据由cpu->arm
Tx_Buff_Sel^=1;
if(Tx_Buff_Sel) //选择一发送的起始页
{
put_reg(RTL8019_REMOTESTARTADDRESS1,0x40);
}
else
{
put_reg(RTL8019_REMOTESTARTADDRESS1,0x46);
}
while (get_reg (RTL8019_COMMAND) == RTL8019_TRANSMIT);
put_reg (RTL8019_REMOTESTARTADDRESS0,0x00); //发送起始的低地址
put_reg (RTL8019_REMOTEBYTECOUNT0, (length & 0xff));
put_reg (RTL8019_REMOTEBYTECOUNT1, ((length >> 8) & 0xff));
put_reg (RTL8019_COMMAND, RTL8019_REMOTEDMAWR); //开始远程dma传送数据
//一个一个的发送发送结构
ExPtr=TxData;
while(ExPtr!=NULL) //知道结构发送完毕
{
pdata=ExPtr->pdata;
for(ii=0;ii<ExPtr->length;ii++) // 发送一个数据缓存
{
put_reg (RTL8019_DMA_DATA,*pdata++);
}
ExPtr=ExPtr->next;
}
ii=length;
while (ii< 60) //数据不足填充
{
put_reg (RTL8019_DMA_DATA, 0);
ii++;
};
//发送完毕,结束本次dma操作
while (!(get_reg (RTL8019_INTERRUPTSTATUS)) & 0x40);
put_reg (RTL8019_INTERRUPTSTATUS, 0x40);
//传送数据到网络
if(Tx_Buff_Sel)
{
put_reg (RTL8019_TRANSMITPAGE,0x40);
}
else
{
put_reg (RTL8019_TRANSMITPAGE,0x46);
}
put_reg (RTL8019_TRANSMITBYTECOUNT0, (ii & 0xff));
put_reg (RTL8019_TRANSMITBYTECOUNT1, ((ii >> 8 & 0xff)));
put_reg (RTL8019_COMMAND, RTL8019_TRANSMIT);
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -