dec21140.c

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

C
1,694
字号
	

	WRITE_PORT_ULONG(CSR13_REG, 0);        //pull it out of sleep  sudhakar
	WRITE_PORT_ULONG(CSR14_REG, 0xffff);
	WRITE_PORT_ULONG(CSR15_REG, 0x1000);
	WRITE_PORT_ULONG(CSR13_REG, 0xef01);

     Delay (1200);
	 
     //	CSR0

	
	localCSR0.dwReg = READ_PORT_ULONG(CSR0_REG);
	localCSR0.ProgrammableBurstLength = 0;		//	16 DWORD transfer in one DMA transaction.
	WRITE_PORT_ULONG(CSR0_REG, localCSR0.dwReg);
	localCSR0.CacheAlignment          = 1;		//	8 DWORD boundary alignment.	
	WRITE_PORT_ULONG(CSR0_REG, localCSR0.dwReg);

	//	CSR 3 & CSR4
	WRITE_PORT_ULONG(CSR3_REG, TO_REAL ((DWORD)pRxDesc));
	WRITE_PORT_ULONG(CSR4_REG, TO_REAL ((DWORD)pTxDesc));
	
	
	//	CSR6
	localCSR6.dwReg = READ_PORT_ULONG(CSR6_REG);
	localCSR6.ReceiveAll = 1;					//	Start off seeing everything...
	localCSR6.PromiscuousMode  = 1;				
	localCSR6.PassAllMulticast = 0;				//	No multicast...
	localCSR6.FullDuplexMode   = 0;				//	Use half duplex.
	localCSR6.dwReg &= CSR6_MUST_AND;
	localCSR6.dwReg |= CSR6_MUST_OR;
	WRITE_PORT_ULONG(CSR6_REG, localCSR6.dwReg);	
	
	DEC21140ModeSetByAutoNegotiation();//change for 5474
	
	DEC21140SetupPerfectFilter();
     
	//	Turn on Receiver...
        localCSR6.dwReg = READ_PORT_ULONG(CSR6_REG);
	localCSR6.StartReceive = 1;		
        WRITE_PORT_ULONG(CSR6_REG, localCSR6.dwReg);
	return TRUE;
}	// HWInit()



/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
//	Interfaces exported to caller starts here:
//	DEC21140Init()
//	DEC21140InitDMABuffer()
//	DEC21140EnableInts()
//	DEC21140DisableInts()
//	DEC21140ISR()	
//	DEC21140GetPendingInts()
//	DEC21140GetFrame()
//	DEC21140SendFrame()
//
//

/////////////////////////////////////////////////////////////////////////////////
//	DEC21140Detect - Detect whether there is 21140 compatible chip.
//	Input:	
//	-	pbBaseAddress... Caller can pass in either physical or virtual address here.
//						 But have to make sure that it's non cached (if it is virtual).
//
BOOL
DEC21140Detect(BYTE *pbBaseAddress)
{	
	//	Need to do proper detection here...

	g_pIOBase = (PUCHAR)pbBaseAddress;
	
	localDEBUGMSG ("DEC21140Detect()::: returning TRUE\r\n");
	return	TRUE;
}	// DEC21140Detect()



/////////////////////////////////////////////////////////////////////////////////
//	DEC21140Init -	This is called to initialze the ethernet low level driver.  
//					The base address of the ethernet hardware is passed into 
//					the routine.  The routine will return TRUE for a successful 
//					initialization.
//	Initialization:
//	1.	Perform 21140 hardware initialization.
//	2.	Create transmit and receive descriptor lists.
//	3.	Start transmit and receive process on 21140.
//	
BOOL
DEC21140Init( BYTE *pbBaseAddress, ULONG dwMemOffset, USHORT MacAddr[3])
{
    int	        n = 0;
    PBYTE       pDst = NULL;
    PBYTE       pSrc = NULL;

   
    localDEBUGMSG ("DEC21140::: Init using i/o address : 0x%x - mem offset = 0x%x\r\n", pbBaseAddress, dwMemOffset);

    dwMEM_OFFSET = dwMemOffset;

    // ** NOTE - the method for determining the MAC address is platform
    // ** dependent in the case of built-in controllers.  For plug-in NICs, we
    // ** generally assume the MAC address can be found in a common location.
    // ** Either way, the following code needs to obtain the MAC address to
    // ** be used with the controller.
 
    if ((PUSHORT)MacAddr != NULL)
    {
        if (!EEPROMReadMAC(&MacAddr[0]))
        {
            localDEBUGMSG("ERROR: Unable to get MAC address for DEC21140.\r\n");
            return(FALSE);
        } 

        // Make a copy of the MAC address...
        pSrc = (PBYTE)MacAddr;
        pDst = pbEthernetAddr;	
        for (n = 6; n ; n--) 
        {
            *pDst++ = *pSrc++;		
        }
    	
        localDEBUGMSG ("MAC = %x-%x-%x", pbEthernetAddr[0], pbEthernetAddr[1], pbEthernetAddr[2]);
        localDEBUGMSG ("-%x-%x-%x\r\n",  pbEthernetAddr[3], pbEthernetAddr[4], pbEthernetAddr[5]);
    }
    else
    {
        //localDEBUGMSG("INFO: MAC address to be provided via call to DEC21140SetMACAddress().\r\n");
    }

	
    // HWInit will return false if hardware is not detected.
    g_pIOBase = (PUCHAR)pbBaseAddress;

    if (!HWInit())
    {
        localDEBUGMSG ("DEC21140:::HWInit() failed...\r\n");
        return FALSE;
    }
    
    localDEBUGMSG ("DEC21140Init()::: Done.\r\n");	
    return TRUE;   

}	// DEC21140Init()



////////////////////////////////////////////////////////////////////////////////
//
//	InitTxDescriptor -	
//
//  Caller tells us where the descriptors and buffers should live.  Furthermore,
//  the size of buffer is fixed at MAX_BUFFER_SIZE.  It is caller's 
//  responsibility to allocate enough memory.  Note: Caller can use 
//  DEC21140QueryBufferSize() to find out the size of buffer used for each 
//  buffer and hence calculate the Total Buffer that can be allocated...	
//  DEC21140QueryDescriptorSize() will return size of descriptor...
//
//  Input:	
//	- dwStartAddress = Location where descriptors start.
//	- dwSize         = Size of buffer allocated by caller.
//
//  WARNING: IT IS CALLER RESPONSIBILITY TO GIVE PROPER DATA.
//	     NO SANITY CHECK HERE !!!
//	     THIS IS ONLY FOR INTERNAL USAGE...
//

void InitTxDescriptor(DWORD dwStartAddress, DWORD dwSize)
{
	
    // Easy... Simply use the provided addresses and size to fit the maximum 
    // number of buffer and descriptors we can...
    // We must have been called from Bootloader or Ethdbg.

    BOOL   bDone = FALSE;
    int    i = 1;	
    DWORD  dwCostOfOneBuffer = sizeof(TX_DESCRIPTOR_FORMAT) + MAX_BUFFER_SIZE;

    // Calculate the max number of descriptor + buffer that I can have for the 
    // given size.
    while (!bDone)
    {
        if ((i * dwCostOfOneBuffer) > dwSize)
        {
            bDone = TRUE;
            i--;
        }
        else
            i++;
    }		

    dwTRANSMIT_DESCRIPTORS_HEAD = dwStartAddress;		
    dwTRANSMIT_BUFFER_START = dwStartAddress + i * sizeof(TX_DESCRIPTOR_FORMAT);
    dwTRANSMIT_RING_SIZE = i;

    localDEBUGMSG ("InitTxDescriptor::: dwTRANSMIT_DESCRIPTORS_HEAD = 0x%x...\r\n", dwTRANSMIT_DESCRIPTORS_HEAD);
    localDEBUGMSG ("InitTxDescriptor::: dwTRANSMIT_BUFFER_START     = 0x%x...\r\n", dwTRANSMIT_BUFFER_START);
    localDEBUGMSG ("InitTxDescriptor::: dwTRANSMIT_RING_SIZE        = 0x%x...\r\n", dwTRANSMIT_RING_SIZE);


} // InitTxDescriptor()



////////////////////////////////////////////////////////////////////////////////
//
//	InitRxDescriptor - See InitTxDescriptor()
//
//

void InitRxDescriptor(DWORD dwStartAddress, DWORD dwSize)
{
    // Easy... Simply use the provided addresses and size to fit the maximum 
    // number of buffer and descriptors we can...
    // We must have been called from Bootloader or Ethdbg.

    BOOL   bDone = FALSE;
    int	   i = 1;	
    DWORD  dwCostOfOneBuffer = sizeof(RX_DESCRIPTOR_FORMAT) + MAX_BUFFER_SIZE;

    // Calculate the max number of descriptor + buffer that I can have for the
    // given size.
    while (!bDone)
    {
        if ((i * dwCostOfOneBuffer) > dwSize)
        {
            bDone = TRUE;
            i--;
        }
        else
            i++;
    }

    dwRECEIVE_DESCRIPTORS_HEAD = dwStartAddress;				
    dwRECEIVE_BUFFER_START = dwStartAddress + i * sizeof(RX_DESCRIPTOR_FORMAT);
    dwRECEIVE_RING_SIZE	= i;		


    localDEBUGMSG ("InitRxDescriptor::: dwRECEIVE_DESCRIPTORS_HEAD   = 0x%x...\r\n", dwRECEIVE_DESCRIPTORS_HEAD);
    localDEBUGMSG ("InitRxDescriptor::: dwRECEIVE_BUFFER_START       = 0x%x...\r\n", dwRECEIVE_BUFFER_START);
    localDEBUGMSG ("InitRxDescriptor::: dwRECEIVE_RING_SIZE          = 0x%x...\r\n", dwRECEIVE_RING_SIZE);

}  // InitRxDescriptor()
	

BOOL DEC21140InitDMABuffer(DWORD dwStartAddress, DWORD dwSize)
{
    DWORD dwAlignedTxStart = 0;
    DWORD dwAlignedRxStart = 0;
    DWORD dwTxBufferSize   = 0;
    DWORD dwRxBufferSize   = 0;


    // Check for minimum buffer size.
    if (dwSize < MIN_DMA_SIZE)
    {
        localDEBUGMSG("ERROR: DMA buffer is too small.\r\n");
        return(FALSE);
    } 

    // Determine aligned start address for DMA buffer.
    dwAlignedTxStart = (dwStartAddress + 0x03) & 0xFFFFFFFC;
    dwSize          -= (dwAlignedTxStart - dwStartAddress);

    // Roughly split buffer in two and init Tx and Rx regions. 
    dwTxBufferSize   = dwSize / 2;
    dwSize          -= dwTxBufferSize;
    dwStartAddress  += dwTxBufferSize;

    dwAlignedRxStart = (dwStartAddress + 0x03) & 0xFFFFFFFC;
    dwSize          -= (dwAlignedRxStart - dwStartAddress);
    dwRxBufferSize   = dwSize;
    

    InitTxDescriptor(dwAlignedTxStart, dwTxBufferSize);
    InitRxDescriptor(dwAlignedRxStart, dwRxBufferSize);

    return(TRUE);
}


/////////////////////////////////////////////////////////////////////////////////
//	DEC21140EnableInts -	Interrupts left disabled at init, call this function 
//							to turn them on
//	For Ethernet debug, we only need Receive Interrupt.
//	Hence simply turn on CSR7[6] and CSR7[16]
//		
void
DEC21140EnableInts()
{
	CSR7_21140	localCSR7;
	
	localDEBUGMSG ("DEC21140EnableInts::: Interrupt Enabled...\r\n");
	localCSR7.dwReg = READ_PORT_ULONG(CSR7_REG);	
	localCSR7.ReceiveInterruptEnable	= 1;
	localCSR7.NormalIntrSummaryEnable	= 1;
	WRITE_PORT_ULONG(CSR7_REG, localCSR7.dwReg);	
}	// DEC21140EnableInts()



/////////////////////////////////////////////////////////////////////////////////
//	DEC21140DisableInts -	Disable interrupt.
//	For etherent debug, we only worry about normal interrupt...
//
void
DEC21140DisableInts()
{
    CSR7_21140  CSR7;

	localDEBUGMSG ("+/- DEC21140DisableInts::: Interrupt Enabled...\r\n");
        CSR7.dwReg = READ_PORT_ULONG(CSR7_REG);
	CSR7.NormalIntrSummaryEnable	= 0;
        WRITE_PORT_ULONG(CSR7_REG, CSR7.dwReg);
}	//	DEC21140DisableInts()



/////////////////////////////////////////////////////////////////////////////////
//	DEC21140GetPendingInts -
//					
//
DWORD
DEC21140GetPendingInts()
{
    CSR5_21140  CSR5;

	//localDEBUGMSG ("+/- DEC21140GetPendingInts::: ...\r\n");
	
	//	The only time we get here is when RX interrupt happens.
	//	Let's check it and see if it is the case...
        CSR5.dwReg = READ_PORT_ULONG(CSR5_REG);
	if (CSR5.ReceiveInterrupt)
	{
		//	Clear the interrupt...
		CSR5.ReceiveInterrupt = 1;
                WRITE_PORT_ULONG(CSR5_REG, CSR5.dwReg);
		return INTR_TYPE_RX;
	}
	else
	{		
		//	Probably need to fix other abnormal interrupts here...
		//localDEBUGMSG ("DEC21140GetPendingInts::: Suspicious... how do I get here ???\r\n");
	}	
        return(0);
}	// DEC21140GetPendngInts()



/////////////////////////////////////////////////////////////////////////////////
//	DEC21140GetFrame -	This routine is used to find out if a frame has been 
//						received.  If there are no frames in the RX FIFO, the 
//						routine will return 0.  
//						If there was a frame that was received correctly,
//						it will be stored in pwData, otherwise it will be discarded.  
//
//	Check if the address is broadcast address...
BOOL IsBroadcast(PBYTE pHeader)
{
	int	i = 0;
	while (1)
	{
		if (pHeader[i++] != 0xff)
			break;
		if (i == 6)
			return TRUE;		
	}
	
	return FALSE;
}	// IsBroadcast()


void PrintMAC (BYTE bData)
{
	if (bData < 10)
		localDEBUGMSG ("0");
	
	//localDEBUGMSG ("%x", bData);
	localDEBUGMSG ("%x", bData);
}	// PrintMAC



/////////////////////////////////////////////////////////////////////////////////
//	Not until SP1 that the problem in talking to DHCP server that does not reply 
//	discovery packet with ARP broadcast is solved.
//	For altoona, the solution is to differentiate between a kernel call and
//	bootloader call. 
//	We pass all broadcast packets up if it is bootloader.
//	Bootloader has to call this function with bBootLoaderCall == TRUE

UINT16
DEC21140GetFrame(BYTE *pbData, UINT16 *pwLength)
{	
	RX_RDES0	localRDES0;
	BOOL		bMultiBufferDetected = FALSE;	
	PBYTE		pHeader;
	BOOL bBootLoaderCall = FALSE;
        CSR5_21140  CSR5;

	//	localDEBUGMSG ("+/- DEC2114GetFrame:::...\r\n");	
	*pwLength = 0;
	
	//	Bail out immediately if the target descriptor is owned by DEC21140
	if (pCurrentRxDesc->RDES0.OwnBit == 1)
		return 0x00;	

        // KITL doesn't call GetPendingInts to disable the interrupt at the card
        // therefore we need to do it here.
        //
        CSR5.dwReg = READ_PORT_ULONG(CSR5_REG);
        if (CSR5.ReceiveInterrupt)
        {
                //      Clear the interrupt...
                CSR5.ReceiveInterrupt = 1;
                WRITE_PORT_ULONG(CSR5_REG, CSR5.dwReg);
        }



	//	A chance of getting valid packet...	

⌨️ 快捷键说明

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