dec21140.c

来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· C语言 代码 · 共 1,694 行 · 第 1/4 页

C
1,694
字号
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Copyright (c) 1998  Microsoft Corporation

Module Name:  

Abstract:  
	Routines for DEC21140 NIC used by bootloader download and 
	ether debug.
    
Functions:


Notes: 

    
--*/

#include <windows.h>
#include <halether.h>
#include <wdm.h>
#include "dec21140.h"


#define MIN_DMA_SIZE    0x20000		// Minimum DMA buffer possible.

//	Forward declaration...
void	DEC21140ModeSetByAutoNegotiation(void);
BOOL    EEPROMReadMAC(WORD *wMAC);


/////////////////////////////////////////////////////////////////////////////////
//
//

#define	__DEC21140_DUMP_TX_DESCRIPTOR__	1
#ifdef  __DEC21140_DUMP_TX_DESCRIPTOR__
	static void	DumpTxDescriptor (PTX_DESCRIPTOR_FORMAT pTxHead);
#endif


#define	__DEC21140_DUMP_RX_DESCRIPTOR__	1
#ifdef  __DEC21140_DUMP_RX_DESCRIPTOR__
	static void	DumpRxDescriptor (PRX_DESCRIPTOR_FORMAT pRxHead);
#endif


#define	__DEC21140_DUMP_MEMORY__	1
#ifdef  __DEC21140_DUMP_MEMORY__
	static void	DumpMemory (PBYTE	pSource, DWORD	dwLength);
#endif


/////////////////////////////////////////////////////////////////////////////////
//	External Functions that must be there...
//

//extern void	localDEBUGMSG(const unsigned char *sz, ...);
#define localDEBUGMSG EdbgOutputDebugString

extern	DWORD	OEMEthGetMSecs (void);



/////////////////////////////////////////////////////////////////////////////////
//	Misc defines
//
#define  CSR0_OFFSET  	 0x00
#define  CSR1_OFFSET  	 0x08
#define  CSR2_OFFSET  	 0x10
#define  CSR3_OFFSET  	 0x18
#define  CSR4_OFFSET  	 0x20
#define  CSR5_OFFSET  	 0x28
#define  CSR6_OFFSET  	 0x30
#define  CSR7_OFFSET  	 0x38
#define  CSR8_OFFSET  	 0x40
#define  CSR9_OFFSET  	 0x48
#define  CSR10_OFFSET 	 0x50
#define  CSR11_OFFSET 	 0x58
#define  CSR12_OFFSET 	 0x60
#define  CSR13_OFFSET 	 0x68
#define  CSR14_OFFSET	 0x70
#define  CSR15_OFFSET	 0x78

#define  CSR0_REG		(PULONG)(g_pIOBase + CSR0_OFFSET)
#define  CSR1_REG		(PULONG)(g_pIOBase + CSR1_OFFSET)
#define  CSR2_REG		(PULONG)(g_pIOBase + CSR2_OFFSET)
#define  CSR3_REG		(PULONG)(g_pIOBase + CSR3_OFFSET)
#define  CSR4_REG		(PULONG)(g_pIOBase + CSR4_OFFSET)
#define  CSR5_REG		(PULONG)(g_pIOBase + CSR5_OFFSET)
#define  CSR6_REG		(PULONG)(g_pIOBase + CSR6_OFFSET)
#define  CSR7_REG		(PULONG)(g_pIOBase + CSR7_OFFSET)
#define  CSR8_REG		(PULONG)(g_pIOBase + CSR8_OFFSET)
#define  CSR9_REG		(PULONG)(g_pIOBase + CSR9_OFFSET)
#define  CSR10_REG		(PULONG)(g_pIOBase + CSR10_OFFSET)
#define  CSR11_REG		(PULONG)(g_pIOBase + CSR11_OFFSET)
#define  CSR12_REG		(PULONG)(g_pIOBase + CSR12_OFFSET)
#define  CSR13_REG		(PULONG)(g_pIOBase + CSR13_OFFSET)
#define  CSR14_REG		(PULONG)(g_pIOBase + CSR14_OFFSET)
#define  CSR15_REG		(PULONG)(g_pIOBase + CSR15_OFFSET)

#ifdef MIPS
#define	TO_REAL(Addr)	((Addr & 0x1fffffff) + dwMEM_OFFSET)
#define	TO_VIRT(Addr)	((Addr | 0xA0000000) - dwMEM_OFFSET)
#else
#define	TO_REAL(Addr)	(Addr)
#define	TO_VIRT(Addr)	(Addr)
#endif


/////////////////////////////////////////////////////////////////////////////////
//	Local Variables...
//
static		BYTE					pbEthernetAddr[6];		//	Local copy of MAC address
volatile	PCSR					pCSR;					//	pointer to 21140 Control and Status Register
PUCHAR g_pIOBase = NULL;

volatile	PRX_DESCRIPTOR_FORMAT	pRxDesc;				//	pointer to RX Descriptor head.
volatile	PRX_DESCRIPTOR_FORMAT	pCurrentRxDesc;			//	pointer to current RX Descriptor that Rx may use.

volatile	PTX_DESCRIPTOR_FORMAT	pTxDesc;				//	pointer to TX Descriptor head.
volatile	PTX_DESCRIPTOR_FORMAT	pCurrentTxDesc;			//	pointer to current TX Descriptor that Tx may use.

static		DWORD					dwMEM_OFFSET;


//	These used to be constants.
//	To make this a true hardware independent library, user needs to provide these addresses...

volatile	DWORD	dwTRANSMIT_DESCRIPTORS_HEAD;		
volatile	DWORD	dwRECEIVE_DESCRIPTORS_HEAD;		
volatile	DWORD	dwTRANSMIT_BUFFER_START;
volatile	DWORD	dwRECEIVE_BUFFER_START;			

//	Then we will calculate the following...

static	DWORD	dwTRANSMIT_RING_SIZE;							
static	DWORD	dwRECEIVE_RING_SIZE;		


//	Forward declaration...
BOOL	DEC21140SetupPerfectFilter(void);


/////////////////////////////////////////////////////////////////////////////////
//	Delay - Spin for the asked amount of time in MilliSecond.
//	Input: dwMilliSecond === Delay required in MilliSecond.
//	Oh well, simply spin...
//
void	Delay (DWORD dwMilliSecond)
{	
	//	Need to find a better way...
	//	But should be okay for ether debug purposes...
	while (dwMilliSecond--)
        {
            READ_PORT_ULONG(CSR9_REG);
        }

}	// Delay()



/////////////////////////////////////////////////////////////////////////////////
//	MIIRead() - 
//	On ICS1890, it's written:
//	Management Interface uses a serial bit stream with a specified frame 
//	structure and protocol as defined:
//	-	Preamble	[32 ones]
//	-	SOF			[01]
//	-	OpCode		[10(read) ; 01(write)]
//	-	Address		[5 bits]
//	-	Register	[5 bits]
//	-	TA			[2 bits]
//	-	Data		[16 bits]
//	-	Idle		[at least 1 bit]
//
//
//	CSR9 controls:
//	+-----------------+-----------------+-----------------+-----------------+
//	| MII Management  | MII Management  | MII Management  | MII Management  |
//	| Data In         | Operation Mode  | Write Data      | Clock           |
//	+-----------------+-----------------+-----------------+-----------------+
//	        19                 18                17               16
//	

WORD MIIRead (BYTE bRegAddr) 
{
	WORD	wValue;
	DWORD	wData;	
	int		i;	

	// Start with clock low and MDIO high	
        WRITE_PORT_ULONG(CSR9_REG, 0x00020000);

	// 32 cycles with MDIO = '1'
	for( i = 0; i < 32; i++ ) 
	{
		WRITE_PORT_ULONG(CSR9_REG, 0x00030000);			
		WRITE_PORT_ULONG(CSR9_REG, 0x00020000);		
	}

	// Start of frame 01
	WRITE_PORT_ULONG(CSR9_REG, 0x00000000);	
	WRITE_PORT_ULONG(CSR9_REG, 0x00010000);		
	WRITE_PORT_ULONG(CSR9_REG, 0x00020000);		
	WRITE_PORT_ULONG(CSR9_REG, 0x00030000);		


	// Read cycle 10
	WRITE_PORT_ULONG(CSR9_REG, 0x00020000);		
	WRITE_PORT_ULONG(CSR9_REG, 0x00030000);		
	WRITE_PORT_ULONG(CSR9_REG, 0x00000000);		
	WRITE_PORT_ULONG(CSR9_REG, 0x00010000);		
    

	// Physical address of 00001.
	WRITE_PORT_ULONG(CSR9_REG, 0x00000000);	
	WRITE_PORT_ULONG(CSR9_REG, 0x00010000);	
	WRITE_PORT_ULONG(CSR9_REG, 0x00000000);	
	WRITE_PORT_ULONG(CSR9_REG, 0x00010000);	
	WRITE_PORT_ULONG(CSR9_REG, 0x00000000);	
	WRITE_PORT_ULONG(CSR9_REG, 0x00010000);	
	WRITE_PORT_ULONG(CSR9_REG, 0x00000000);	
	WRITE_PORT_ULONG(CSR9_REG, 0x00010000);	
	WRITE_PORT_ULONG(CSR9_REG, 0x00020000);	
	WRITE_PORT_ULONG(CSR9_REG, 0x00030000);
    

	// Register address
	for( i = 4; i >= 0; i-- ) 
	{
		if (bRegAddr & (1 << i)) 
		{
			WRITE_PORT_ULONG(CSR9_REG, 0x00020000);	
			WRITE_PORT_ULONG(CSR9_REG, 0x00030000);						
		}
		else 
		{
			WRITE_PORT_ULONG(CSR9_REG, 0x00000000);						
			WRITE_PORT_ULONG(CSR9_REG, 0x00010000);						
		}
	}

	// Two cycle turnaround time
	WRITE_PORT_ULONG(CSR9_REG, 0x00040000);		
	WRITE_PORT_ULONG(CSR9_REG, 0x00050000);		
	WRITE_PORT_ULONG(CSR9_REG, 0x00040000);		
	WRITE_PORT_ULONG(CSR9_REG, 0x00050000);

    
	// Read out the data bits
	wValue = 0;

	for( i = 0; i < 16; i++ ) 	
	{
		wValue <<= 1;

		WRITE_PORT_ULONG(CSR9_REG, 0x00040000);        				
		wData = READ_PORT_ULONG(CSR9_REG);
		WRITE_PORT_ULONG(CSR9_REG, 0x00050000);		

		wData = (wData >> 19);
		wValue |= (WORD) (wData & 1);		
	}

	// Two cycle at the end to make sure it's now Idle
	WRITE_PORT_ULONG(CSR9_REG, 0x00040000);	
	WRITE_PORT_ULONG(CSR9_REG, 0x00050000);		
	WRITE_PORT_ULONG(CSR9_REG, 0x00040000);		
	WRITE_PORT_ULONG(CSR9_REG, 0x00050000);    		
	
	return wValue;
}




/////////////////////////////////////////////////////////////////////////////////
//	HWStopAdapter -   Stop the adapter by resetting the chip through CSR0[0]
//					
static void
HWStopAdapter(void)
{
    CSR6_21140 CSR6;
    CSR0_21140 CSR0;

    CSR6.dwReg = READ_PORT_ULONG(CSR6_REG);
    CSR6.PortSelect = 1;					//	Select MII/SYM port.
    WRITE_PORT_ULONG(CSR6_REG, CSR6.dwReg);

    CSR0.dwReg = READ_PORT_ULONG(CSR0_REG); 
    CSR0.dwReg |= SOFTWARE_RESET;
    WRITE_PORT_ULONG(CSR0_REG, CSR0.dwReg);

    Delay (12000);

    CSR6.dwReg = READ_PORT_ULONG(CSR6_REG);
    CSR6.TransmitThresholdMode = 1;
    WRITE_PORT_ULONG(CSR6_REG, CSR6.dwReg);

}   // HWStopAdapter()



/////////////////////////////////////////////////////////////////////////////////
//	HWInit	-	completely initialize the hardware and leave it in a state that is ready to transmit and receive
//				packets.
//	

static BOOL 
HWInit(void)
{	
	int		i;
	int		dwTxRingSize;
	int		dwRxRingSize;
	int		dwTxBufferStart;
	int		dwRxBufferStart;
	volatile	PTX_DESCRIPTOR_FORMAT	pTxHead;
	volatile	PRX_DESCRIPTOR_FORMAT	pRxHead;
	CSR0_21140	localCSR0;
	CSR6_21140	localCSR6;

	dwTxRingSize = dwTRANSMIT_RING_SIZE;
	dwRxRingSize = dwRECEIVE_RING_SIZE;
	dwTxBufferStart = TO_REAL(dwTRANSMIT_BUFFER_START);
	dwRxBufferStart = TO_REAL(dwRECEIVE_BUFFER_START);

	HWStopAdapter();				

	// ==========================================================================
	//	The descriptors are linked by circular linked list	
	//	They are basically one after another, and we use buffer address 2 as pointer to
	//	next descriptor.
	//	The last descriptor will link back to first descriptor.

	//	First stop, TX descriptors...
	//	Note: Initializing pTxDesc and pCurrentTxDesc for future global use...

	pTxHead = pTxDesc = pCurrentTxDesc = (PTX_DESCRIPTOR_FORMAT) dwTRANSMIT_DESCRIPTORS_HEAD;;
	memset (pTxHead, 0, (sizeof(TX_DESCRIPTOR_FORMAT) * dwTxRingSize));		

	for (i = 0 ; i < dwTxRingSize ; i++)
	{
		//	For each descriptor, this is what we need to set:
		//	-	The descriptor is now owned by Host TDES0[31]
		//	-	TDES1[24] set indicating second address is a chained address
		//	-	TDES1[25] set for last descriptor indicating a loop back.
		//	-	TDES2 will point to the buffer this descriptor points to.
		//	-	The next descriptor address in TDES3		
		
		pTxHead->TDES0.dwReg = pTxHead->TDES0.dwReg & DESC_OWNED_BY_HOST;		
		pTxHead->TDES1.dwReg = pTxHead->TDES1.dwReg | SECOND_ADDRESS_CHAINED;			
		

		pTxHead->TDES2 = dwTxBufferStart;
		dwTxBufferStart += MAX_BUFFER_SIZE;
	
		if (i == dwTxRingSize - 1)		
		{
			//	Last descriptor points to first descriptor...
			//	And indicates that this is the end of the ring...
			pTxHead->TDES1.TransmitEndOfRing = 1;
			pTxHead->TDES3 = TO_REAL((DWORD) pTxDesc);		
		}
		else
		{
			pTxHead->TDES3 = TO_REAL((DWORD) ((DWORD)pTxHead + sizeof(TX_DESCRIPTOR_FORMAT)));
			pTxHead = (PTX_DESCRIPTOR_FORMAT) TO_VIRT(pTxHead->TDES3);
		}		

	}    	
	//DumpTxDescriptor (pTxDesc);


	// ==========================================================================
	//	Then, Rx descriptors...
	//	Note: Initializing pRxDesc for future global use...
	//
	
	pRxHead = pRxDesc = pCurrentRxDesc = (PRX_DESCRIPTOR_FORMAT) dwRECEIVE_DESCRIPTORS_HEAD;;
	memset (pRxHead, 0, (sizeof(RX_DESCRIPTOR_FORMAT) * dwRxRingSize));	
	memset ((PBYTE)TO_VIRT(dwRxBufferStart), 0, dwRxRingSize * 1536);

	for (i = 0 ; i < dwRxRingSize ; i++)
	{
		//	For each descriptor, this is what we need to set:
		//	-	The descriptor is now owned by DEC21140 RDES0[31] = 1
		//	-	RDES1[24] set indicating second address is a chained address,		
		//	-	RDES1[25] set for last descriptor indicating a loop back.
		//	-	RDES2 will point to the buffer this descriptor points to.
		//	-	The next descriptor address in TDES3		
		
		pRxHead->RDES0.dwReg = pRxHead->RDES0.dwReg | DESC_OWNED_BY_DEC21140;
		pRxHead->RDES1.dwReg = pRxHead->RDES1.dwReg | SECOND_ADDRESS_CHAINED;
		pRxHead->RDES1.Buffer1Size = MAX_BUFFER_SIZE;
		
		pRxHead->RDES2 = dwRxBufferStart;

		dwRxBufferStart += MAX_BUFFER_SIZE;
	
		if (i == dwRxRingSize - 1)		
		{
			//	Last descriptor points to first descriptor...
			//	And indicates that this is the end of the ring...
			pRxHead->RDES1.ReceiveEndOfRing = 1;
			pRxHead->RDES3 = TO_REAL((DWORD) pRxDesc);		
		}
		else
		{
			pRxHead->RDES3 = TO_REAL((DWORD) ((DWORD)pRxHead + sizeof(RX_DESCRIPTOR_FORMAT)));
			pRxHead = (PRX_DESCRIPTOR_FORMAT) TO_VIRT(pRxHead->RDES3);
		}		
	}	
	// DumpRxDescriptor (pRxDesc);	


	// ==========================================================================	
	//	Set CSRs:
	//
	
	// enable the 21143 chip

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?