📄 8019drv.c
字号:
// Driver of RTL8019AS
#include <intrins.h>
#include "pubdef.h"
#include "8019.h"
#define NIC_TX_MIN_PAGE 0x40
#define NIC_TX_MAX_PAGE 0x4b
#define NIC_RX_MIN_PAGE 0x4c
#define NIC_RX_MAX_PAGE 0x7f
/* enthernet frame type field indicates the top level protocol type */
#define EFT_LOOP 0x0060 /* type: Loopback */
#define EFT_ECHO 0x0200 /* type: Echo */
#define EFT_PUP 0x0400 /* type: Xerox PUP */
#define EFT_IP 0x0800 /* type: Internet Protocol */
#define EFT_ARP 0x0806 /* type: ARP */
#define EFT_RARP 0x8035 /* type: Reverse ARP */
#define VLAN_ID 0x8100
#define VLAN_LEN 4
typedef struct tagETHF{
byte DA[6];
byte SA[6];
word frmType;
byte pdu[1];
} ETHF, SPTR PETHF;
/*-------------------------------------------------------------------------------*/
void displayNICReg(byte pageNum)
{
setNICRegPage(pageNum);
TRACE("---content of Page %d registers list ---\n\r", (int)(pageNum - '0'));
TRACE("reg00: %x\n\r", (int)reg00);
TRACE("reg01: %x\n\r", (int)reg01);
TRACE("reg02: %x\n\r", (int)reg02);
TRACE("reg03: %x\n\r", (int)reg03);
TRACE("reg04: %x\n\r", (int)reg04);
TRACE("reg05: %x\n\r", (int)reg05);
TRACE("reg06: %x\n\r", (int)reg06);
TRACE("reg07: %x\n\r", (int)reg07);
TRACE("reg08: %x\n\r", (int)reg08);
TRACE("reg09: %x\n\r", (int)reg09);
TRACE("reg0a: %x\n\r", (int)reg0a);
TRACE("reg0b: %x\n\r", (int)reg0b);
TRACE("reg0c: %x\n\r", (int)reg0c);
TRACE("reg0d: %x\n\r", (int)reg0d);
TRACE("reg0e: %x\n\r", (int)reg0e);
TRACE("reg0f: %x\n\r", (int)reg0f);
}
bit initNIC(void)
{
RESET_NIC;
/* the following initializing sequence come from doucment DP83901A.pdf
Initialization Sequence
The following initialization procedure is mandatory. */
// 1. Program Command Register for Page 0 (Command Register e 21H)
// followed by a wait state of at least 1.5 ms for the NIC to reset.
CR = 0x21;
delayMsec(5);
/* check RTL8019AS */
if (CR != 0x21)
return false;
// 2. Initialize Data Configuration Register (DCR)
PAGE0_DCR = 0xc8; /* FIFO threshold = 8 bytes, normal operation, 8-bit byte write DMA, BOS=0 */
// 3. Clear Remote Byte Count Registers (RBCR0, RBCR1)
PAGE0_RBCR0 = 0;
PAGE0_RBCR1 = 0;
// 4. Initialize Receive Configuration Register (RCR)
PAGE0_RCR = 0xc4; /* rxed packets be buffered to memory, only rx match physical address packet,
accept with broadcast destination address packet,
reject packet with length less than 64 bytes and receive error */
// 5. Place the SNIC in LOOPBACK mode 1 or 2 (Transmit Configuration Register e 02H or 04H)
setNICInLoopbackMode;
selectInternalLoopbackMode;
// 6. Initialize Receive Buffer Ring: Boundary Pointer(BNDRY), Page Start (PSTART), and Page Stop(PSTOP)
PAGE0_PSTART = NIC_RX_MIN_PAGE;
PAGE0_PSTOP = NIC_RX_MAX_PAGE + 1;
PAGE0_BNRY = NIC_RX_MIN_PAGE;
// 7. Clear Interrupt Status Register (ISR) by writing 0FFH to it.
PAGE0_ISR = 0xff;
// 8. Initialize Interrupt Mask Register (IMR)
PAGE0_IMR = 0x3f; /* 允许中断CNT, OVW, TXE, RXE, PTX, PRX */
// PAGE0_IMR = 0;
// 9. Program Command Register for page 1 (Command Register e 61H)
setNICRegPage(1);
// I) Initialize Physical Address Registers (PAR0±PAR5)
// II) Initialize Multicast Address Registers (MAR0±MAR5)
/*
PAGE1_MAR0 = 0x00;
PAGE1_MAR1 = 0x41;
PAGE1_MAR2 = 0x00;
PAGE1_MAR3 = 0x80;
PAGE1_MAR4 = 0x00;
PAGE1_MAR5 = 0x00;
*/
// III) Initialize CURRent pointer
PAGE1_CURR = NIC_RX_MIN_PAGE;
// 10. Put SNIC in START mode and for page 0 (Command Register equal to 22H).
CR = 0x22;
// 11. Initialize the Transmit Configuration for the intended val-ue.
setNICRegPage(0);
PAGE0_TCR = 0xe0;
// 9. I) Initialize Physical Address Registers (PAR0±PAR5)
// NOTE : pNIFP stores the fixed general parameters of Network Interface
setNICRegPage(1);
PAGE1_PAR0 = pNIFP->myMAC[0];
PAGE1_PAR1 = pNIFP->myMAC[1];
PAGE1_PAR2 = pNIFP->myMAC[2];
PAGE1_PAR3 = pNIFP->myMAC[3];
PAGE1_PAR4 = pNIFP->myMAC[4];
PAGE1_PAR5 = pNIFP->myMAC[5];
TRACE("--- My Mac Address : 0x%x %x %x %x %x %x\n\r",
(int)PAGE1_PAR0,
(int)PAGE1_PAR1,
(int)PAGE1_PAR2,
(int)PAGE1_PAR3,
(int)PAGE1_PAR4,
(int)PAGE1_PAR5);
setNICRegPage(0);
disableNICInLoopbackMode;
// OK! The NIC is now ready for transmission and recep-tion.
/*-------------------------------------------------------------------------------*/
/* determine RTl8019AS mode, document P29 */
setNICRegPage(3);
if (PAGE3_CONFIG0 & 0x08) /* Config0.JP(bit 3) refect the state of pin JP input, if JP = High, NIC in Jumper mode */
TRACE("--- NIC in Jumper mode\n\r");
else
/* Pin JP = Low set NIC in jumpless mode */
if (PAGE3_CONFIG2 & 0x10 || PAGE3_CONFIG3 & 0x80)
TRACE("--- NIC in PNP mode\n\r"); /* Config0.PNPJP(bit 4) refect the state of pin PNP input */
/* Config3.PNP(bit 7), if in Jumperless mode, set this bit indicates NIC in PNP mode */
else
TRACE("--- NIC in RT Jumperless mode\n\r");
PAGE3_9346CR |= 0xc0; /* before writing to the Page3 Config1-3 registers, Bit7, 6of 9346CR must be 11b */
PAGE3_CONFIG1 |= 0x80; /* IRQ enable */
PAGE3_CONFIG2 &= 0x3f; /* Medium Type os TP/CX auto-detect(10BaseT link test is enable) */
PAGE3_CONFIG2 |= 0x20; /* BSELB, This bit, when set, forces the BROM disabled */
PAGE3_CONFIG3 &= 0xf0; /* make sure that NIC is not Sleep/PWRDN/ACTIVEB mode */
PAGE3_9346CR &= 0x3f; /* prevent writing to Page3 Config1-3 registers */
delayMsec(100); /* wait for NIC detecting medium type automatically */
if (PAGE3_CONFIG3 & 0x40)
TRACE("--- NIC in full-duplex mode\n\r");
else
TRACE("--- NIC in half-duplex mode\n\r");
TRACE("--- NIC in Auto-Detect mode, ");
if (PAGE3_CONFIG0 & 0x04)
TRACE("test failure, set medium type 10Base2 by default\n\r");
else
TRACE("test success, medium type 10BaseT\n\r");
/*-------------------------------------------------------------------------------*/
return true;
}
static void waitRDMAOperationDone(void)
{
int i = 0;
// setNICRegPage(0);
while (!(PAGE0_ISR & ISR_RomteDMAComplete) && i<300)
i++; // loop until Remote DMA Reading done or force to break the loop
if (i <300)
PAGE0_ISR = ISR_RomteDMAComplete; // clear ISR.RDC bit
else {
// #ifdef debug_time
TRACE("waitRDMAOperationDone() >> force to break loop due to i is 300 at least\n\r");
// #endif
}
}
void NICRxFrame(void)
{
byte i, NICReadPtr, nextPage;
byte NICWritePtr, lenLowByte, status, lenHighByte, desTaskID;
byte SPTR p, SPTR s;
PETHF pFrm;
bit bdata isFrameLegal;
PNIDP pNIDP;
word w;
bit bdata canReadNICData;
setNICRegPage(1);
NICWritePtr = PAGE1_CURR;
setNICRegPage(0);
NICReadPtr = PAGE0_BNRY;
NICRxFrameInvokedCnt++;
/*-------------------------------------------------------------------------------*/
canReadNICData = true;
while (1) {
if (NICReadPtr == NICWritePtr)
break; // rx buffer is empty
#ifdef debug_time
internalReport(ETH_DETECT_A_FRM);
#endif
NICRxedFrameCnt++;
// read NIC rxed buffer index
PAGE0_RSAR0 = 0;
PAGE0_RSAR1 = NICReadPtr;
PAGE0_RBCR0 = 4;
PAGE0_RBCR1 = 0;
CR = 0x0a; // enable Remote DMA read
status = REMOTE_DMA_PORT;
nextPage = REMOTE_DMA_PORT;
lenLowByte = REMOTE_DMA_PORT;
lenHighByte = REMOTE_DMA_PORT;
if (nextPage > NIC_RX_MAX_PAGE || nextPage < NIC_RX_MIN_PAGE) {
// error on read NIC rxed data!!!
// #ifdef debug_time
TRACE("NICReadPtr = %x, NICWritePtr = %x\n\r", (int)NICReadPtr, (int)NICWritePtr);
TRACE("Rxed Packet header : %x %x %x %x\n\r", (int)status, (int)nextPage, (int)lenLowByte, (int)lenHighByte);
// #endif
if (canReadNICData) {
// try to read NIC rxed data again
canReadNICData = false;
continue;
} else {
// ignor all frame
PAGE0_BNRY = NICWritePtr;
// enableAllInt;
return;
}
}
#ifdef debug_time
else
TRACE("Rxed Packet header : %x %x %x %x\n\r", (int)status, (int)nextPage, (int)lenLowByte, (int)lenHighByte);
#endif
#ifdef real_runtime
waitRDMAOperationDone();
#endif
if (lenHighByte || lenLowByte > MAX_ETH_LEN) {
#ifdef debug_time
internalReport(ETH_RX_OVERLARGE);
#endif
// discard the current rxed frame
PAGE0_BNRY = nextPage;
NICReadPtr = nextPage;
continue;
}
/*-------------------------------------------------------------------------------*/
// copy the rxed Ethernet frame to Host Network Interface data buffer
pNIDP = allocNIDP(TASK_NI_DRV);
if (pNIDP == '\0') {
// Error, NIDP table is overflow!, discard the current rxed frame
// enableAllInt;
return;
}
p = pNIDP->db;
s = p;
// copy data from NIC local memory to Host memory
i = lenLowByte + 1;
i &= 0xfe; // make even
PAGE0_RSAR0 = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -