⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 8019drv.c

📁 rt8019的驱动程序源代码和驱动测试程序源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
// 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 + -