📄 rtl8019.c
字号:
//***********************************************************************
//**
//** Project: Hush
//** Module: RTL8019.C
//**
//** Description: This module contains the code needed to test
//** the RealTek Ethernet Controller
//**
//** Date Rev Eng Description
//** -------- ---- --- ------------
//** 12/28/00 ERS Chip Specific Functions
//**
//***********************************************************************
//**
//** (c) Copyright Inari Inc. All rights reserved.
//**
//***********************************************************************
//======================================================================
// Include Files
//======================================================================
#ifdef _IPL0201_
#include <Reg0201.h> // special function register declarations
#else //(_IPL0202_)
#include <Reg0202.h> // special function register declarations
#endif //(_IPL0201_/_IPL0202_)
#include <STDIO.h>
#include "PLX020X.h" // PLX Library defines & memory
#include "Global.h" // PC Interface project defines & memory
#include "RTL8019.h" // RealTek 8019AS chip defines
//Memory
xdata volatile chipctrl ChipCtrl _at_ CONTROL_BASE; // GLOBAL Chip Control Registers
//xdata volatile unsigned char DataPort _at_ (CONTROL_BASE+0x10); // GLOBAL DMA Read/Write port
xdata volatile unsigned char ResetPort _at_ (CONTROL_BASE+0x18); // GLOBAL ChipReset Port
//*********************************
//* Global Variables
//*********************************
static unsigned char bWait;
bit NICTxInProgress; // transmit currently operating?
bit bEthOverflow = 0;
data unsigned char NextRxPage; // Hold the RxPage untilthe next DMARead operation
//define Macro
#define INSERT_WAIT_STATE() \
bWait = CKCON;\
CKCON |= 0x02; //Add 2 wait state to Movx Commands
#define REMOVE_WAIT_STATE() CKCON = bWait;
#define MIN_ETH_SIZE 60 //PAD packets smaller than this #
#define XBYTEDUMP ((unsigned char volatile xdata*) 0)
#if (HARDWARE == HDKREV12)
#if (JAM_BOTH == ON)
#define INIT_HOLDOFF (DDR2=DDR2|0x03)
#define START_HOLDOFF (P2=(P2&0xFC))
#define STOP_HOLDOFF (P2=(P2|0x03))
#else //(JAM_BOTH == OFF)
#define INIT_HOLDOFF (DDR2=DDR2|0x02)
#define START_HOLDOFF (P2=(P2&0xFD))
#define STOP_HOLDOFF (P2=(P2|0x02))
#endif //(JAM_BOTH == OFF)
#else //(HARDWARE == HDKREV20)
#define INIT_HOLDOFF (DDR2=DDR2|0x01)
#define START_HOLDOFF (P2=(P2&0xFE))
#define STOP_HOLDOFF (P2=(P2|0x01))
#endif //(HARDWARE == HDKREV12/HDKREV20)
//bit bStartHoldOff;
extern void ProgramEprom ();
void delay (unsigned int i)
{
while(i !=0)
i --;
}
void EthInit (void)
{
unsigned char temp;
NICTxInProgress = 0; // Not transmit currently operating
//Use the Totem PeripheralChipSelect0 to Drive the AEN line on the RTL8019
PCSMIN0L = LSB(CONTROL_BASE); //Select IO Space
PCSMIN0H = MSB(CONTROL_BASE); // from 0x0300
PCSMAX0L = LSB((CONTROL_BASE+0x1F)); // to 0x031F
PCSMAX0H = MSB((CONTROL_BASE+0x1F));
// NICTxPendingLen = 0; // No transmit currently waiting
IT0 = 1; // External0 on Falling Edge
// IT0 = 0; // External0 on LowLevel
IE0 = 0; // clear External0 ISR Flag
EX0 = 0; // Disable While Configuring External0 Interrupt
// ChipCtrl.page0_wr.cr = USE_PAGE0; // move to page 0
// ChipCtrl.page0_wr.imr = 0x0F;//INTERRUPT_MASK;
// ChipCtrl.page0_wr.cr = USE_PAGE2;
// if (0x0F != (ChipCtrl.page2_rd.imr&0x7F))
// EdtLog ('I');
INSERT_WAIT_STATE(); //save current CKCON & add wait states for Chip access.
//Reset the Chip & Wait 2ms(min)
temp = ResetPort; // Read the port
ResetPort = temp; // write it back again
//Delay for some time!!!!!!
delay(0x1000); //Stall after Reset
//Double check the jumpered values for I/O, IRQ, etc
ChipCtrl.page0_wr.cr = STOP_CHIP; // Make sure the chip is stopped
ChipCtrl.page0_wr.cr = USE_PAGE3; // move to page 3
//This should have been done by jumpers upon bootup, but just to make sure... do it again!!!!
// ChipCtrl.page3_wr.config1 = 0x00 ; // Enable Interrupts (INT0 =IRQ2/09)
ChipCtrl.page3_wr.n9346cr = 0xC0; // Enable writes to configuration
#if (SEND_HEARTBEAT == ON)
ChipCtrl.page3_wr.config2 = 0x20; // 10baseT with LinkTest Enabled (Auto-Select), No BootROM
#else //(SEND_HEARTBEAT == OFF)
ChipCtrl.page3_wr.config2 = 0x60; // 10baseT with LinkTest Disabled, No BootROM
#endif //(SEND_HEARTBEAT == ON/OFF)
ChipCtrl.page3_wr.config3 = 0x00; //
ChipCtrl.page3_wr.n9346cr = 0x00; // Back to normal
//Setup Ethernet Device Address (Shouldn't matter because we need to run in Promiscuous mode anyway)
ChipCtrl.page3_wr.cr = USE_PAGE1; // move to page 1
ChipCtrl.page1.par0 = 0xBA ; // Address = BA DD EA DD 0C 11
ChipCtrl.page1.par1 = 0xDD ; //
ChipCtrl.page1.par2 = 0xEA ; //
ChipCtrl.page1.par3 = 0xDD ; //
ChipCtrl.page1.par4 = 0x0C ; //
ChipCtrl.page1.par5 = 0x11 ; //
ChipCtrl.page1.mar0 = 0xFF ; // MultiCast Hash = ffffffffffffffff= all
ChipCtrl.page1.mar1 = 0xFF ; //
ChipCtrl.page1.mar2 = 0xFF ; //
ChipCtrl.page1.mar3 = 0xFF ; //
ChipCtrl.page1.mar4 = 0xFF ; //
ChipCtrl.page1.mar5 = 0xFF ; //
ChipCtrl.page1.mar6 = 0xFF ; //
ChipCtrl.page1.mar7 = 0xFF ; //
// One Time Setup
ChipCtrl.page1.curr = RECEIVE_PAGE_START; // current Receive buffer to fill (Tail pointer)
ChipCtrl.page1.cr = USE_PAGE0; // move to page 0
ChipCtrl.page0_wr.bnry = RECEIVE_PAGE_START; // current Receive buffer full upto (Head pointer)
ChipCtrl.page0_wr.pstart= RECEIVE_PAGE_START; // Start of receive Buffer Space
NextRxPage = RECEIVE_PAGE_START; // This is where we start to read
ChipCtrl.page0_wr.pstop = RECEIVE_PAGE_STOP; // End of Circular RxBuffer
ChipCtrl.page0_wr.tpsr = TX0_PAGE_START; // Start of Transmit Buffer Space
ChipCtrl.page0_wr.dcr = FIFO_THRESHOLD; // Data Config Register (Fifo Threshold)
ChipCtrl.page0_wr.tcr = INTERNAL_LOOPBACK; // Transmit control (Temporarily in Loopback)
// ChipCtrl.page0_wr.rcr = RECEIVE_ADDRESS; // Receive Packet types (Direct & Broadcast)
ChipCtrl.page0_wr.rcr = RECEIVE_ALL; // Receive Packet types (Direct,Broadcast, Promiscuous)
// ChipCtrl.page0_wr.rcr = RECEIVE_ANYTHING; // Receive Packet types (Direct,Broadcast, Promiscuous)
//DMA Setup
ChipCtrl.page0_wr.rbcr0 = 0x00; // Remote DMA Byte Count = 00
ChipCtrl.page0_wr.rbcr1 = 0x00; // Remote DMA Byte Count = 00
ChipCtrl.page0_wr.tbcr0 = 0x00; // Transmit Byte Count = 00
ChipCtrl.page0_wr.tbcr1 = 0x00; // Transmit Byte Count = 00
//Delay for some time!!!!!!
delay(0xFF00); //Wait around after Reset
ChipCtrl.page0_wr.cr = USE_PAGE0; // move to page 0
ChipCtrl.page0_wr.isr = 0xFF; // Clear any pending ISR Flags that we may have produced
ChipCtrl.page0_wr.imr = INTERRUPT_MASK; // Enable these Interrupts to fire
ChipCtrl.page0_wr.tcr = NORMAL_TRANSMIT; // Transmit control ready!
ChipCtrl.page1.cr = PAGE0_START; // move to page 0 and start Chip!!!
REMOVE_WAIT_STATE(); //Restore Saved CKCON
#if (USE_HOLDOFF == ON) // ON = Use Force Collision Circuit
INIT_HOLDOFF;
STOP_HOLDOFF;
#endif //(USE_HOLDOFF == ON)
EX0 = 1; // Enable External0 Interrupt
}
//bit EthSelfTest (void)
//{
// /* Check the chips functionality... */
//
// return TRUE;
//}
/*
void RingOverflow(void);
void RingOverflow(void)
{
int nInc = 0;
bEthOverflow = 1;
#if (WAIT_STATE_BOUNCE == ON)
CKCON &= 0xFB; //No Wait States for Chip Writes
#endif
//Double check the jumpered values for I/O, IRQ, etc
ChipCtrl.page0_wr.cr = STOP_CHIP; // Put Chip in STOP mode
//reset DMA info
ChipCtrl.page0_wr.rbcr0 = 0x00; // Remote DMA Byte Count = 00
ChipCtrl.page0_wr.rbcr1 = 0x00; // Remote DMA Byte Count = 00
//Do nothing, just wait!!
#define BREAK_AMOUNT_FOR_THE_REALLY_CRAPPY_TIMEOUT_WE_IMPLEMENTED 0x0A0
//the 60 was determined to be around 2.6ms (must be an int for the 16 bit math)
while (BREAK_AMOUNT_FOR_THE_REALLY_CRAPPY_TIMEOUT_WE_IMPLEMENTED != nInc++)
{
}
ChipCtrl.page0_wr.tcr = INTERNAL_LOOPBACK; // Transmit control in Internal Loopback mode
ChipCtrl.page0_wr.cr = STOP_CHIP; // Put Chip in STOP mode
ChipCtrl.page0_wr.isr = OVW; // Clear the Overflow Flag (by writing a 1 to it)
ChipCtrl.page0_wr.tcr = NORMAL_TRANSMIT; // Transmit control in Internal Loopback mode
//Clear out the Transmit Status, We caused the Chip to Reset, no more transmits pending!!!!
// if we were nice we would try and recover the prepared packet
NICTxInProgress = 0; // Clear the bit that says were busy
#if (WAIT_STATE_BOUNCE == ON)
CKCON |= 0x02; //Add 2 wait states to Movx Commands for Chip Reads
#endif
}
*/
//****************************************************************
//**
//** Subroutine: RTL_ISR
//**
//** Description: The function called when the RTL0819AS chip
//** creates an interrupt
//**
//** On Entry:
//** ============================
//**
//** On Exit:
//** ============================
//** ISR Flag(s) = Cleared manually
//**
//****************************************************************
/*
void RTL_ISR(void)
{
unsigned char ISR_Value;
//New version
INSERT_WAIT_STATE();
ISR_Value = ChipCtrl.page0_rd.isr;
REMOVE_WAIT_STATE();
if (ISR_Value & (PTX|TXE))
{
NICTxInProgress = 0;
START_HOLDOFF;
}
if(ISR_Value & OVW) // if receive overflow
{
START_HOLDOFF;
RingOverflow();
}
ChipCtrl.page0_wr.isr = ISR_Value;
return;
INSERT_WAIT_STATE();//Save current CKCON value then force it to 2 wait states
ISR_Value = ChipCtrl.page0_rd.isr;
#if (WAIT_STATE_BOUNCE == ON)
CKCON &= 0xFB; //No Wait States for Chip Writes
#endif
while (((~RST & ~CNT) & ISR_Value) != 0)
{
if (ISR_Value & PTX) // if Transmit Packet interrupt
{
ChipCtrl.page0_wr.isr = PTX; // Write TxBit to clear Interrupt
NICTxInProgress = 0;
START_HOLDOFF;
}
if (ISR_Value & TXE) // if Transmit Error interrupt
{
ChipCtrl.page0_wr.isr = TXE; // Write TxErrorBit to clear Interrupt
NICTxInProgress = 0;
START_HOLDOFF;
}
if(ISR_Value & PRX) // if receive complete interrupt
{
ChipCtrl.page0_wr.isr = PRX; // Write RxPacket Bit to clear Interrupt
}
if (ISR_Value & RXE) // if ReceivePacket with Errors
{
ChipCtrl.page0_wr.isr = RXE; // Write ReceivePacket w/Errors Bit to clear Interrupt
}
if (ISR_Value & RDC) // if RemoteDMA complete
{
ChipCtrl.page0_wr.isr = RDC; // Write RemoteDMAComplete Bit to clear Interrupt
}
if(ISR_Value & OVW) // if receive overflow
{
//Do the Overflow Special Code path!!!!
START_HOLDOFF;
RingOverflow();
}
#if (WAIT_STATE_BOUNCE == ON)
CKCON |= 0x02;
#endif
ISR_Value = ChipCtrl.page0_rd.isr;
#if (WAIT_STATE_BOUNCE == ON)
CKCON &= 0xFB; //No Wait States for Chip Writes
#endif
}
REMOVE_WAIT_STATE();//Restore Saved CKCON
}
*/
WORD EthSend (EDT_RX_LIST* assm)
{
BYTE i=0;
WORD len;
//DEBUG
if (!assm)
{
EdtLog (ROUTER_ASSM_BAD); /* NOTE:: We shouldn't do this at "SEND" time!!! */
return 0xFFFF;
}
//END DEBUG
// if (!EthSendSetup(0)) /* Check if we can TX yet... */
// return 0; /* Try again later... */
for (len=0; i < (assm->eth.frag[MAX_ETH_FRAGS-1]->frag.plx.seq.num); i++)
len += assm->eth.frag[i]->frag.plx.len - (sizeof (PLX_HEADER)-1);
len += assm->eth.frag[MAX_ETH_FRAGS-1]->frag.plx.len - (sizeof (PLX_HEADER)-1);
if (len > 0x600)
{
EdtLog (ROUTER_ASSM_LARGE);
EdtReset(PLXRESET_CHIP); //Full reset!
}
if (!EthSendSetup( max (len,MIN_ETH_SIZE) ))
return 0; /* We don't have a TX buffer avaiable right now.. Try again from the Poll loop. */
#if ((PRINTF_DEBUG == ON) && (LOG_ETH_RX == ON))
for (i = 18; i < 22; i++)
{
printf("%02BX,",(assm->eth.frag[0])->frag.payload[i]);
}
// printf("\n");
#endif //((PRINTF_DEBUG == ON) & (LOG_ETH_RX == ON))
for (i=0; i < (assm->eth.frag[MAX_ETH_FRAGS-1]->frag.plx.seq.num); i++)
{
EthSendCopy ((assm->eth.frag[i])->frag.plx.len - (sizeof (PLX_HEADER)-1),
((BYTE*)&assm->eth.frag[i]->frag)+sizeof(PLX_HEADER) );
_PUT_FRAG (assm->eth.frag[i], &pFragBuff);
}
EthSendCopy ((assm->eth.frag[MAX_ETH_FRAGS-1])->frag.plx.len - (sizeof (PLX_HEADER)-1),
((BYTE*)&assm->eth.frag[MAX_ETH_FRAGS-1]->frag)+sizeof(PLX_HEADER) );
_PUT_FRAG (assm->eth.frag[MAX_ETH_FRAGS-1], &pFragBuff);
_PUT_FRAG ((PLX_FRAG_LIST*)assm, &pFragBuff);
EthSendFinish( max (len,MIN_ETH_SIZE) ); //Transmit the packet!!
return 0xFFFF;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -