📄 rtl8019.c
字号:
#include "debug.h"
#include "true_false.h"
#include "typedef.h"
#include "stdlib.h"
#include "rtl8019.h"
#include "mem_man.h"
#include "utilities.h"
/* to prevent call RTLSendPacket() when RTLSendPackt() is already is called, InSending
is used. example when process run in RTLSendPacket() and a interrupt ocurr then call
RTLSendPacket again, then the Register would have changed when interrupt return. */
static BYTE InSending;
static BYTE StartPageOfPacket;
/* receive head information */
/*struct RTLReceiveHeader
{
BYTE ReceiveStatus;
BYTE NextPacketStartPage;
BYTE PacketSizeLow;
BYTE PacketSizeHigh;
}Head;for some unknown resean Head must be a gloal value. */
static BYTE Head[4];
/* last trasmit start page */
static BYTE LastSendStartPage;
/* read rtl8019 register. port is reg address */
/*BYTE ReadReg(WORD port)
{
return *((BYTE xdata *)port);
}*/
#define ReadReg(port) (*((volatile BYTE *)port))
#define ReadReg_WORD(port) (*((volatile WORD *)port))
/* write value to register */
/*void WriteReg(WORD port,BYTE value)
{
*((BYTE xdata *)port) = value;
}*/
#define WriteReg(port,value) (*((volatile BYTE *)port) =(BYTE )value)
#define WriteReg_WORD(port,value) (*((volatile WORD *)port) =(WORD) value)
/* select which page of register to use*/
/* TO DO:set bit 7-6 in CR, CR_TXP must be 0(if 1 the packet is retrasmit) */
#define RTLPage(Index) WriteReg(CR,(ReadReg(CR) & 0x3B)|(BYTE)(Index << 6))
/* reset rtl8019 and init registers, LocalMacAddr is MAC address */
void RTLInit(BYTE LocalMACAddr[])
{
BYTE temp;
u32_t i ;
/* after hardware reset a longdelay is necessary for rtl to self-initial */
for(i=0; i < RTL_DELAY_AFTER_HARDWARE_RESET; i++);
/* reset: write to reset prot */
temp = ReadReg(RESET_PORT);
WriteReg(RESET_PORT,temp);
/* init RTL registers*/
WriteReg(CR,(CR_PAGE0 | CR_ABORT_COMPLETE_DMA | CR_STOP_COMMAND)); /* set page0, stop command. command is stop after power up. */
WriteReg(PSTART_WPAGE0, RECEIVE_START_PAGE); /* Pstart */
WriteReg(PSTOP_WPAGE0, RECEIVE_STOP_PAGE); /* Pstop */
WriteReg(BNRY_WPAGE0, RECEIVE_START_PAGE); /* BNRY */
WriteReg(TPSR_WPAGE0, SEND_START_PAGE0); /* TPSR */
WriteReg(RCR_WPAGE0, 0xCE); /* RCR: refer to define of RCR in Rtl8019as.h */
WriteReg(TCR_WPAGE0, 0xE0); /* TCR: refer to define of TCR in Rtl8019as.h */
WriteReg(DCR_WPAGE0, 0xC9); /* DCR: refer to define of DCR in Rtl8019as.h */
WriteReg(IMR_WPAGE0,0); /* RTL recieve interrupt enabled */
WriteReg(ISR_WPAGE0, 0xFF); /* write FF to clear up all interrupt status */
RTLPage(1);
WriteReg(CURR_WPAGE1,RECEIVE_START_PAGE + 1);
WriteReg(PRA0_WPAGE1,LocalMACAddr[0]);
WriteReg(PRA1_WPAGE1,LocalMACAddr[1]);
WriteReg(PRA2_WPAGE1,LocalMACAddr[2]);
WriteReg(PRA3_WPAGE1,LocalMACAddr[3]);
WriteReg(PRA4_WPAGE1,LocalMACAddr[4]);
WriteReg(PRA5_WPAGE1,LocalMACAddr[5]);
/* transimit start page */
LastSendStartPage = SEND_START_PAGE0;
StartPageOfPacket = RECEIVE_START_PAGE + 1;
/* in the beginning, no packet is in sending */
InSending = FALSE;
/* initial over, start command and receive */
WriteReg(CR,(CR_PAGE0 | CR_ABORT_COMPLETE_DMA | CR_START_COMMAND));
}
/* write buffer to rlt ram */
void RTLWriteRam(WORD address, WORD size, BYTE * buff)
{
//BYTE *Endp;
BYTE PrePage; /* store page */
BYTE t1,t2;
WORD Temp;
PrePage = ReadReg(CR);
RTLPage(0);
WriteReg(RSARH_WPAGE0,(BYTE)((address>>8)&0x00ff));
WriteReg(RSARL_WPAGE0,(BYTE)address);
WriteReg(RBCRH_WPAGE0,(BYTE)((size>>8)&0x00ff));
WriteReg(RBCRL_WPAGE0,(BYTE)size);
WriteReg(CR,(0x00 | CR_REMOTE_WRITE | CR_START_COMMAND));
/*
for(Endp = buff + size; buff < Endp;)
{
WriteReg(REMOTE_DMA_PORT,*(buff++));
}
*/
for(size=(1+size)>>1;size;--size)
{
t1=*buff++;//LOW
t2=*buff++;//HIGH
Temp=((t2<<8)&0xff00)|(t1&0x00ff);
WriteReg_WORD(REMOTE_DMA_PORT,Temp);
}
/* complete dma */
WriteReg(RBCRH_WPAGE0,0);
WriteReg(RBCRL_WPAGE0,0);
WriteReg(CR,((PrePage&0xC0) | CR_ABORT_COMPLETE_DMA | CR_START_COMMAND));
}
/* read rlt ram data to buffer */
void RTLReadRam(WORD address,WORD size,BYTE * buff)
{
//BYTE * Endp;
BYTE PrePage; /* store page */
BYTE flag=0,t1,t2;
WORD Temp;
PrePage = ReadReg(CR);
RTLPage(0);
WriteReg(RSARH_WPAGE0,(BYTE)((address>>8)&0x00ff));
WriteReg(RSARL_WPAGE0,(BYTE)address);
WriteReg(RBCRH_WPAGE0,(BYTE)((size>>8)&0x00ff));
WriteReg(RBCRL_WPAGE0,(BYTE)size);
WriteReg(CR,(0x00 | CR_REMOTE_READ | CR_START_COMMAND));
/*
for(Endp = buff + size; buff < Endp;)
{
*(buff++) = ReadReg(REMOTE_DMA_PORT);
}
*/
for(;size>1;size-=2)
{
Temp = ReadReg_WORD(REMOTE_DMA_PORT);
*(buff++)=Temp&0x00ff;//low
*(buff++)=(Temp>>8)&0x00ff;//high
//*(buff++)=(Temp>>8)&0x00ff;//low
//*(buff++)=Temp&0x00ff;//high
}
if (size)
{
Temp = ReadReg_WORD(REMOTE_DMA_PORT);
*(buff++)=Temp&0x00ff;//low
//*(buff++)=(Temp>>8)&0x00ff;//high
}
/* complete dma */
WriteReg(RBCRH_WPAGE0,0);
WriteReg(RBCRL_WPAGE0,0);
WriteReg(CR,((PrePage&0xC0) | CR_ABORT_COMPLETE_DMA | CR_START_COMMAND));
}
/* call this function to send a packet by RTL8019. packet store in ram
starts at 'buffer' and its size is 'size'. 'size' should not large than
MAX_PACKET_SIZE or the excess data will be discard. */
BOOL RTLSendPacket(BYTE * buffer,WORD size)
{
BYTE StartPage;
BYTE PrePage;
/* if send is already running */
if(InSending == TRUE)
return FALSE;
else
InSending = TRUE;
/* store page */
PrePage = ReadReg(CR);
/* check pakcet size */
if(size < MIN_PACKET_SIZE)
{
size = MIN_PACKET_SIZE;
}
else
{
if(size > MAX_PACKET_SIZE)
size = MAX_PACKET_SIZE;
}
/* write packet to ram */
if(LastSendStartPage == SEND_START_PAGE0)
{
StartPage = SEND_START_PAGE1;
LastSendStartPage = SEND_START_PAGE1;
}
else
{
StartPage = SEND_START_PAGE0;
LastSendStartPage = SEND_START_PAGE0;
}
RTLWriteRam((WORD)(((WORD)StartPage)<<8),size,buffer);
/* wait for last time trasmition to complete */
while((ReadReg(CR) & CR_TXP) == CR_TXP);
/* write trasmit start page and size */
RTLPage(0);
WriteReg(TPSR_WPAGE0,StartPage); /* TPSR */
WriteReg(TBCRL_WPAGE0,(BYTE)size);/*low */
WriteReg(TBCRH_WPAGE0,(BYTE)((size>>8)&0x00ff)); /*high*/
WriteReg(CR,((PrePage&0xC0) | CR_ABORT_COMPLETE_DMA | CR_TXP | CR_START_COMMAND));
InSending = FALSE;
return TRUE;
}
/* call this function to receive a ethernet packet from RTL8019.
return value:
NULL: no packet can receive yet.
not NULL:
a address point to MemHead. This Head contain merory
Imformation(memory start address, memory end address ...) of
received packet. Memory is allocated by function 'MemAllocate(WORD size)'.
a example of struct SMemHead is:
struct SMemHead
{
BOOL used; // if in using
BYTE *pStart; // the start address of memory
BYTE *pEnd;
};
You can use your own struct SMemHead and MemAllocat function in your project.
*/
struct SMemHead * RTLReceivePacket()
{
BYTE curr,bnry;
WORD address;
WORD PacketSize;
struct SMemHead *MemHead;
/* if send is running don't crrupt RTL register*/
if(InSending == TRUE)
return NULL;
MemHead = NULL;
RTLPage(1);
curr = ReadReg(CURR_RPAGE1);
RTLPage(0);
/* check if startpage exceed range becasue of unknow error */
if(StartPageOfPacket >= RECEIVE_STOP_PAGE || StartPageOfPacket < RECEIVE_START_PAGE)
{
/* use curr as the StartPageOfPacket in this case */
StartPageOfPacket = curr;
return NULL;
}
/* check if there is packets to read */
if(StartPageOfPacket == curr)
return NULL;
/*
* read a packet
*/
/* read packet head imformation */
address = ((WORD)StartPageOfPacket)<<8;
RTLReadRam(address,4,Head);
/* check rsr, if isn't a good packet no read */
if(Head[0] & RSR_RECEIVE_NO_ERROR)
{
/* this is a good packet */
/* packet size, sub 4 bytes, this 4 byte is MAC checksum */
PacketSize = ((WORD)Head[3])*256 + Head[2] - 4;
/* allocate buffer and read packet into buffer */
if((MemHead = MemAllocate(PacketSize)) != NULL)
{
/* if packet is put from bnry+1 to receive_stop_page and receive
start page to next packet startpage, that is if bnry+1 > next
packet start page and next start page != receive_start_page,
we need read by two times. the first time from bnry+1 to receive
_stop_page, the second time from receive start page to next packet
startpage.
*/
address += 4;
if(StartPageOfPacket > Head[1] && Head[1] != RECEIVE_START_PAGE)
{
RTLReadRam(address,(WORD)((((WORD)RECEIVE_STOP_PAGE)<<8) - address),MemHead->pStart); /* read from rtl */
RTLReadRam((WORD)(((WORD)RECEIVE_START_PAGE)<<8),(WORD)(PacketSize - ((((WORD)RECEIVE_STOP_PAGE)<<8) - address)),
MemHead->pStart + ((((WORD)RECEIVE_STOP_PAGE)<<8) - address)); /* read from rtl */
}
else
{
RTLReadRam(address,PacketSize,MemHead->pStart); /* read from rtl */
}
}
}
/* get next packet start page */
StartPageOfPacket = Head[1];
/* reset bnry */
bnry = StartPageOfPacket-1;
if(bnry<RECEIVE_START_PAGE)
bnry = RECEIVE_STOP_PAGE - 1;
WriteReg(BNRY_WPAGE0,bnry);
#ifdef debug_rtl
Uart_Printf( " \nRTL8019::RCV A FRAME\n" ) ;
#endif
return MemHead;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -