📄 drv_8019.c
字号:
/*****************************************************************************/
/* RTL8019AS DRIVER FUNCTIONS */
/*****************************************************************************/
#include <stdio.h>
#include <aduc812.h>
#include "reg_8019.h"
#include "depend.h"
#define WARNING
/* H/W and IP Address */
extern ETHADDR sed_lclEthAddr;
//extern ETHADDR sed_ethBcastAddr;
void ethernet_register_test(void);
//void ethernet_get_8390_hdr(word StartAddr, word Count);
void ethernet_get_8390_hdr(word StartAddr, word Count) reentrant;
void ei_rx_overrun(void);
void ethernet_init(void);
void ethernet_test(void);
//void DMA_write(byte *buffer, word StartAddr, word Count);
void ei_receive(void) reentrant;
//void ei_input(byte *buf, word StartAddr, word Count);
void ei_input(byte *buf, word StartAddr, word Count) reentrant;
void ei_output( BYTE *buf, WORD StartAddr, WORD Count );
BYTE sed_Receive( BYTE *buf );
BYTE *sed_IsPacket(void);
BYTE *sed_FormatPacket( BYTE *destEAddr, WORD ethType );
BYTE sed_CheckPacket( BYTE *BufLocation, WORD expectedType );
BYTE sed_Send( WORD pkLengthInOctets );
extern void delay(word d);
extern void delay_1ms(int times);
extern void putb_ser(byte byte_data);
extern void print(byte *ch);
extern void print_int(const byte *ch);
extern word address_ascii_to_hex_echo(void);
extern byte two_ascii_to_hex(void);
extern void Move( BYTE *src, BYTE *dest, WORD numbytes );
extern byte current_page;
extern byte next_pkt;
extern byte rx_frame_errors;
extern byte rx_crc_errors;
extern byte rx_missed_errors;
extern byte EthRxBufRdPtr;
extern byte EthRxBufWrPtr;
extern byte ethernet_8390_hdr[3];
extern byte EthRxBuf[NBUF][SBUFSIZ];
extern byte EthTxBuf[BUFSIZ];
extern longword pkt_cnt;
extern struct e8390_pkt_hdr {
byte status; /* status of receiver */
byte next; /* pointer to next packet. */
byte countl; /* header + packet length in bytes */
byte counth;
};
BYTE sed_Receive( BYTE *buf )
{
return 0;
}
BYTE *sed_IsPacket(void)
{
BYTE *buf;
//BYTE *buf;
EthRxBufRdPtr++;
if ( EthRxBufRdPtr == NBUF )
EthRxBufRdPtr = 0;
if( EthRxBufRdPtr == EthRxBufWrPtr ) {
if ( EthRxBufRdPtr ) EthRxBufRdPtr--;
else EthRxBufRdPtr = NBUF-1;
return (BYTE *)NULL;
}
buf = &EthRxBuf[EthRxBufRdPtr][14]; /* ? size of array ? start of IP header */
if( EthRxBufRdPtr == NBUF )
EthRxBufRdPtr = 0;
return buf;
}
/* Make a MAC header */
BYTE *sed_FormatPacket( BYTE *destEAddr, WORD ethType )
{
Move( destEAddr, EthTxBuf, 6 ); /* Make a destination address */
Move( sed_lclEthAddr, EthTxBuf+6, 6 ); /* Make a source address */
*(WORD *)(EthTxBuf+12) = ethType; /* Make a Ethertype */
return ( EthTxBuf+14 );
}
BYTE sed_CheckPacket( BYTE *BufLocation, WORD expectedType )
{
if ( *(WORD *)(BufLocation-2) != expectedType ) {
return ( 0 );
}
return (1);
}
BYTE sed_Send( WORD pkLengthInOctets )
{
//WORD i;
if (EthTxBuf == NULL)
return 0;
if (pkLengthInOctets <= 0)
return 0;
pkLengthInOctets += 14; /* Ethernet Header */
if ( pkLengthInOctets < MIN_PACKET_SIZE )
pkLengthInOctets = MIN_PACKET_SIZE+4; /* CRC is 4Byte */
/* Mask interrupts from the ethercard. */
EN0_IMR = 0x00; /* ? */
/* Wait for other transmit */
while ( EN0_ISR & E8390_TRANS );
/* We should already be in page 0, but to be safe... */
EN_CMD = E8390_PAGE0 + E8390_START + E8390_NODMA;
#ifndef NE8390_RW_BUGFIX
EN0_RCNTLO = 0x42;
EN0_RCNTHI = 0x00;
EN0_RSARLO = 0x42;
EN0_RSARHI = 0x00;
EN_CMD = E8390_RREAD + E8390_START;
delay_1ms(10);
#endif
/* copy RAM data to RTL8019AS iRAM with (from MAC to end of data ) */
ei_output( EthTxBuf, TX_START_PG << 8, pkLengthInOctets );
/* Just send it, and does not check */
EN0_TCNTLO = pkLengthInOctets& 0xff;
EN0_TCNTHI = pkLengthInOctets>> 8;
EN0_TPSR = TX_START_PG;
EN_CMD = E8390_NODMA + E8390_TRANS + E8390_START;
/* Turn 8390 interrupts back on. */
EN0_IMR = ENISR_ALL;
return 1;
}
/* copy RAM data to RTL8019AS Internal RAM */
void ei_output( BYTE *buf, WORD StartAddr, WORD Count )
{
word loop;
EN0_ISR = ENISR_RDC;
/* Now the normal output. */
EN0_RCNTLO = Count & 0xff;
EN0_RCNTHI = Count >> 8;
EN0_RSARLO = StartAddr & 0xFF;
EN0_RSARHI = StartAddr >> 8;
EN_CMD = E8390_RWRITE + E8390_START + E8390_PAGE0;
for(loop=0;loop < Count;loop++){
EN_DATA = *buf++;
}
EN0_ISR = ENISR_RDC; /* Ack intr. to Remote DMA */
}
void ei_receive(void) reentrant /* maybe reentrant... */
{
word pkt_len, current_offset;
byte rx_pkt=0;
byte rxing_page, this_frame, next_frame;
while ( ++rx_pkt < 10) {
/* Get the Receive Page, CURR */
EN_CMD = EN_NODMA + EN_PAGE1 + EN_START;
rxing_page = EN1_CURPAG;
EN_CMD = EN_NODMA + EN_PAGE0 + EN_START;
/* Remove one frame from the ring. Boundary is always a page behind. */
this_frame = EN0_BOUNDARY + 1;
if (this_frame >= RX_STOP_PG)
this_frame = RX_START_PG;
if (this_frame == rxing_page) /* Read all the frames? */
break; /* Done for now */
current_offset = (word)(this_frame << 8);
/* Get the header of this packet */
ethernet_get_8390_hdr( current_offset, 4);
pkt_len = (word)(ethernet_8390_hdr[3]<<8) + ethernet_8390_hdr[2] - 4;
next_frame = this_frame + 1 + ((pkt_len+4)>>8);
//print(" | this : ") ; putb_ser( this_frame ) ;
//print(" | next : ") ; putb_ser( next_frame ) ;
//print(" | 8390_hdr[1] : ") ; putb_ser( ethernet_8390_hdr[1] ) ;
//print("\r\n");
if ( ethernet_8390_hdr[1] != next_frame
&& ethernet_8390_hdr[1] != next_frame + 1
&& ethernet_8390_hdr[1] != next_frame - (RX_STOP_PG-RX_START_PG)
&& ethernet_8390_hdr[1] != next_frame + 1 - (RX_STOP_PG-RX_START_PG) ) {
current_page = rxing_page;
EN0_BOUNDARY = current_page-1;
continue;
}
if ( pkt_len > MAX_PACKET_SIZE || pkt_len < MIN_PACKET_SIZE ) {
//print("\n\rBogus packet size..");
}
else if ((ethernet_8390_hdr[0] & 0x0f) == ENRSR_RXOK) {
//print("\r\nhdr len =");
//putb_ser(ethernet_8390_hdr[3]);
//putb_ser(ethernet_8390_hdr[2]);
/* If RxBuffer is full, then break */
if ( EthRxBufWrPtr == EthRxBufRdPtr )
break;
ei_input( EthRxBuf[EthRxBufWrPtr], current_offset + 4, pkt_len );
EthRxBufWrPtr++;
if ( EthRxBufWrPtr == NBUF ) EthRxBufWrPtr = 0;
}
next_frame = ethernet_8390_hdr[1];
/* This _should_ never happen: it's here for avoiding bad clones. */
if (next_frame >= RX_STOP_PG) { /* next frame inconsistency */
next_frame = RX_START_PG;
}
current_page = next_frame;
EN0_BOUNDARY = next_frame-1;
}
/* We used to also ack ENISR_OVER here, but that would sometimes mask
a real overrun, leaving the 8390 in a stopped state with rec'vr off. */
EN0_ISR = ENISR_RX+ENISR_RX_ERR;
}
//void ei_input(byte *buf, word StartAddr, word Count)
void ei_input(byte *buf, word StartAddr, word Count) reentrant
{
word loop;
EN_CMD = EN_PAGE0 + EN_RREAD + EN_START;
/* Set Remote byte count */
EN0_RCNTLO = (byte)(Count & 0xff); /* Low byte of tx byte count */
EN0_RCNTHI = (byte)(Count >> 8); /* High byte of tx byte count Transmit byte count register */
/* Set Remote Start Address */
EN0_RSARLO = (byte)(StartAddr & 0xff); /*LSB Remote start address reg */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -