dec21140.c

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

C
1,694
字号
	//	Need to bail out if we wait too long for a frame completion...

	while (pCurrentRxDesc->RDES0.OwnBit == 0 || bMultiBufferDetected)
	{
		localRDES0 = pCurrentRxDesc->RDES0;		
		//	localDEBUGMSG ("DEC21140GetFrame::: Looking at descriptor: %d... RDES0 = 0x%x\r\n", 
		//		(pCurrentRxDesc - pRxDesc), localRDES0.dwReg);		
		
		//	Discard Error Frame for now...   Donno what to do to them.
		//	Error frame detected if RDES0[15] and RDES0[8] are set.
		//	In this case, we simply clean up the Descriptor and release it back to 21140.		
		if (localRDES0.ErrorSummary && localRDES0.LastDescriptor)
		{
			//	localDEBUGMSG ("DEC21140GetFrame::: Error Frame !!!   1 Buffer Tossed...\r\n");
			localRDES0.dwReg = 0x00 | DESC_OWNED_BY_DEC21140;
			pCurrentRxDesc->RDES0.dwReg = localRDES0.dwReg;			
			
			//	Proceed to next descriptor...
			pCurrentRxDesc = (PRX_DESCRIPTOR_FORMAT) TO_VIRT (pCurrentRxDesc->RDES3);
			continue;
		}


		//	Okay, by now we must have a valid buffer.					
		//	Copy data pointed to by this buffer to user buffer...			
		
		//	localDEBUGMSG ("DEC21140GetFrame()::: Copying %d bytes\r\n", (UINT16)localRDES0.FrameLength);	

		//	For Ethernet Debug and Bootloader, only ARP packet is accepted...
		//	Hence filter out non-ARP broadcast or Multicast packets...

		/////////////////////////////////////////////////////////////////////////
		//	Note:
		//	Some DHCP server returns broadcast packet and some return directed packets.
		//	The bBootLoaderCall will prevent filtering out "Non ARP broadcast" packets sent from DHCP server
		//	during bootloader time (i.e. Bootloader will use this function with bBootLoaderCall == TRUE).

		pHeader = (PBYTE) TO_VIRT(pCurrentRxDesc->RDES2);
		if (localRDES0.MulticastFrame || IsBroadcast(pHeader))
		{
			//	This is multicast or broadcast packet.
			//	Toss away if it is non-ARP (i.e Header[16] != 8  || Header[17] != 6)


			if (!bBootLoaderCall)
			{			
				if (pHeader[12] != 0x08 && pHeader[13] != 0x06)
				{
					//	The buffer is tossed !!!		
						//localDEBUGMSG ("DEC21140GetFrame()::: 1 non ARP broadcast/multicast buffer tossed.\r\n");
						//localDEBUGMSG ("DEC21140GetFrame()::: RDES0 = 0x%x\r\n", localRDES0);					
					goto SkipCopy;
				}
			}
			
		}

		*pwLength = *pwLength + (UINT16)localRDES0.FrameLength;
		memcpy (pbData, (PBYTE) TO_VIRT(pCurrentRxDesc->RDES2), (UINT16)localRDES0.FrameLength);
		pbData += (UINT16)localRDES0.FrameLength;		


SkipCopy:
		//	Return descriptor back to 21140...		
		pCurrentRxDesc->RDES0.dwReg = 0x00 | DESC_OWNED_BY_DEC21140;
			
		//	Proceed to next descriptor...
		pCurrentRxDesc = (PRX_DESCRIPTOR_FORMAT) TO_VIRT (pCurrentRxDesc->RDES3);		
	
		//	Check the First and Last descriptor indications and take action accordingly...
		switch ((localRDES0.dwReg & 0x300) >> 8)
		{		
			/////////////////////////////////////////////////////////////////////
			case 0x00:	// Not first and not last... 				
				//localDEBUGMSG ("DEC21140GetFrame()::: Middle buffer...\r\n");
				break;

			
			/////////////////////////////////////////////////////////////////////
			case 0x01:	// Last Descriptor...
				if (bMultiBufferDetected)
				{
					//localDEBUGMSG ("DEC21140GetFrame()::: Last Descriptor found...length = %d\r\n", *pwLength);									
					return *pwLength;															
				}
				else
				{
					//	Must be an error, toss the whole buffer..
					return 0x00;
				}		
			
			/////////////////////////////////////////////////////////////////////
			case 0x02:	//	First Descriptor...	
				if (!bMultiBufferDetected)
				{
					//localDEBUGMSG ("DEC21140GetFrame()::: First Descriptor detected...\r\n");
					bMultiBufferDetected = TRUE;						
				}
				else
				{
					//	Another First Descriptor ???
					//	Must be something wrong !!!
					//	localDEBUGMSG ("DEC21140GetFrame()::: Multiple First Descriptor...Tossing all...\r\n");
					return 0x00;
				}			
				break;
		

			/////////////////////////////////////////////////////////////////////
			case 0x03:	//	One buffer frame...					
				// localDEBUGMSG ("DEC21140GetFrame()::: One buffer frame (%d bytes)...\r\n", *pwLength);							

				//	Let's see the destination MAC...
				//	Destination MAC starts from 8th byte.
				
				{
					static	DWORD	dwTotalFrame = 0;
					//localDEBUGMSG ("Dest MAC = ");
					//PrintMAC (pHeader[0]);
					//PrintMAC (pHeader[1]);
					//PrintMAC (pHeader[2]);
					//PrintMAC (pHeader[3]);
					//PrintMAC (pHeader[4]);
					//PrintMAC (pHeader[5]);					
					//localDEBUGMSG (" ... Total = %d\r\n", dwTotalFrame++);
				}
				
				return (*pwLength);

			/////////////////////////////////////////////////////////////////////
			default:
				//	Should NEVER get here..
				//	Just bail out...
				return (0x00);
		}
	}
	return *pwLength;	    
}	// DEC21140GetFrame()



/////////////////////////////////////////////////////////////////////////////////
//	DEC21140ModeSetByAutoNegotiation() 
//	Set the DEC to the common denominator between what PHY (ICS1890) has negotiated
//	with "link partner" and capability of DEC.
//
void	DEC21140ModeSetByAutoNegotiation()
{
	WORD	wReg4;
	WORD	wReg5;
    WORD    wModes;
    DWORD   WaitCount;
    CSR6_21140  CSR6;
    CSR0_21140  CSR0;

    WaitCount = 100000;
	while ((!(MIIRead(0x01) & 0x20)) && ( 0 != WaitCount-- ))
	{
		//	Wait till Autonegotiation completed...
		//	printf ("Autonegotiation not completed...\r\n");					
    }

	//	Make sure TX and Rx are stopped.
        CSR6.dwReg = READ_PORT_ULONG(CSR6_REG);
	CSR6.StartTransmit = 0x0;
	CSR6.StartReceive  = 0x0;
        WRITE_PORT_ULONG(CSR6_REG, CSR6.dwReg);

    //  Default to 10Base-TxHD.
	CSR6.TransmitThresholdMode = 0x01;		//	FIFO threshold to 10Mbps
	CSR6.FullDuplexMode	   = 0x00;		//	Set half duplex mode.
	CSR6.StoreAndForward	   = 0x01;		//	Store/Forward...		
        WRITE_PORT_ULONG(CSR6_REG, CSR6.dwReg);
    wModes = 0;

    //  If autonegotiation was successful, get the communications
    //  that are supported by the local host and the remote host.
    if ( 0 != WaitCount )
    {
	    wReg4 = MIIRead(0x04);
	    wReg5 = MIIRead(0x05);

        //  Determine the common modes of operation.
        wModes = wReg4 & wReg5;
    }

    //	I know that ICS1890 does not support 100Base-T4
	//	Hence we start check for
	//	100Base-TxFD
	//	100Base-TxHD 
	//	10Base-TxFD
	//	10Base-TxHD

    //  Enable 100Base-Tx if supported by both sides.
    if (( wModes & 100 ) || ( wModes & 0x80 ))
    {
        CSR0.dwReg = READ_PORT_ULONG(CSR0_REG);
        CSR0.ProgrammableBurstLength	= 32;
        WRITE_PORT_ULONG(CSR0_REG, CSR0.dwReg);

        CSR6.dwReg = READ_PORT_ULONG(CSR6_REG); 
	CSR6.TransmitThresholdMode		= 0x00;		//	FIFO threshold to 100Mbps
        WRITE_PORT_ULONG(CSR6_REG, CSR6.dwReg);

        //  Set bit 0 if full duplex is enabled.
        wModes >>= 2;
    }
    wModes >>= 6;

    //  Enable full duplex if supported by both sides.
    if ( wModes & 1 )
    {
        CSR6.dwReg = READ_PORT_ULONG(CSR6_REG);
        CSR6.FullDuplexMode				= 0x01;		//	Set Full duplex mode.
        WRITE_PORT_ULONG(CSR6_REG, CSR6.dwReg);
    }
}



BOOL	DEC21140SetupPerfectFilter ()
{
    CSR6_21140                     csr;
    PTX_DESCRIPTOR_FORMAT   pTxDesc;
    PBYTE                  pbBuffer;
    int                     i;

    pTxDesc = pCurrentTxDesc;
    //
    // Advance to next descriptor...
    //
    pCurrentTxDesc = (PTX_DESCRIPTOR_FORMAT) TO_VIRT(pCurrentTxDesc->TDES3);
    //PrintTransmitState();

    csr.dwReg = READ_PORT_ULONG(CSR6_REG);
    csr.StartTransmit = 1; 
    WRITE_PORT_ULONG(CSR6_REG, csr.dwReg);

    pTxDesc->TDES1.dwReg = 0x09000000;
    pTxDesc->TDES0.OwnBit = 1;
    WRITE_PORT_ULONG(CSR1_REG, 0xFFFFFFFF);
    

    i=0;
    while((pTxDesc->TDES0.OwnBit) == 1 && (i++ < 10)) 
        ;
        
    pTxDesc->TDES1.dwReg = SECOND_ADDRESS_CHAINED;
    
    pTxDesc = pCurrentTxDesc;
    //
    // Advance to next descriptor...
    //
    pCurrentTxDesc = (PTX_DESCRIPTOR_FORMAT) TO_VIRT(pCurrentTxDesc->TDES3);
    
    pTxDesc->TDES0.dwReg = 0;
    pTxDesc->TDES1.dwReg = 0x69000000 | 192;
    pbBuffer = (PBYTE) TO_VIRT(pTxDesc->TDES2);
    
    memset(pbBuffer, 0xff, 192);
	pbBuffer[0] = pbEthernetAddr[0];
	pbBuffer[1] = pbEthernetAddr[1];
	pbBuffer[4] = pbEthernetAddr[2];		
	pbBuffer[5] = pbEthernetAddr[3];
	pbBuffer[8] = pbEthernetAddr[4];
	pbBuffer[9] = pbEthernetAddr[5];		

    pTxDesc->TDES0.OwnBit = 1;
    WRITE_PORT_ULONG(CSR1_REG, 0xffffffff);
   

    i = 0; 
    while((pTxDesc->TDES0.OwnBit) == 1 && (i++ < 10))
        ;
    
    pTxDesc->TDES1.dwReg = SECOND_ADDRESS_CHAINED;
    
    return(TRUE);

}

#if 0

/////////////////////////////////////////////////////////////////////////////////
//	DEC21140SetupPerfectFilter (BYTE *pbPermittedAddress)
//	This function creates setup frame to be used to filter all incoming frames...
//	A perfect filter, filters out everything except its own IP address and
//	broadcast address.
//
BOOL	DEC21140SetupPerfectFilter ()
{
	//	Here are the steps taken...	
	//	1.	Prepare a zero-length buffer descriptor from current tx descriptor.
	//	2.	Setup the perfect filter frame with exactly 192 bytes data length.
	//	3.	First Segment = Last Segment = 0.
	//	4.	Finally, 
	//		set TDES0[31] = 1 ... Adapter owned descriptor.
	//
	//		Zero length descriptor needs:
	//			TDES1[30] = 0 ... Last Segment Bit 0
	//			TDES1[29] = 0 ... First Segment Bit 0
	//			TDES1[21..11] = ... Transmit buffer 2 = 0
	//			TDES1[10..0]  = ... Transmit buffer 1 = 0
	//	5.	Trigger transmitter, wait for packet 'eaten' by DEC.
	//	6.	Reset descriptor to become normal descriptor.


	PTX_DESCRIPTOR_FORMAT	pSetupDescriptor;
	PTX_DESCRIPTOR_FORMAT	pZeroLengthDescriptor;
	TX_TDES1	        ZeroLengthDescriptorOriginTDES1;
	TX_TDES1	        SetupDescriptorOriginTDES1;
	PBYTE			pbBuffer;
        CSR6_21140              CSR6;
        CSR0_21140              CSR0;


	// Make sure receiver is off and transmitter is on.
    CSR6.dwReg = READ_PORT_ULONG(CSR6_REG);
    CSR6.StartReceive  = 0;		
    CSR6.StartTransmit = 1;
    WRITE_PORT_ULONG(CSR6_REG, CSR6.dwReg);

    CSR0.dwReg = READ_PORT_ULONG(CSR0_REG);
    CSR0.OnNow = 0;
    WRITE_PORT_ULONG(CSR0_REG, CSR0.dwReg);


	//	Setup zero length buffer descriptor.
	pZeroLengthDescriptor	= pCurrentTxDesc;			
	pCurrentTxDesc	        = (PTX_DESCRIPTOR_FORMAT) TO_VIRT(pCurrentTxDesc->TDES3);
	pSetupDescriptor        = pCurrentTxDesc;
	pCurrentTxDesc	        = (PTX_DESCRIPTOR_FORMAT) TO_VIRT(pCurrentTxDesc->TDES3);

	ZeroLengthDescriptorOriginTDES1.dwReg = pZeroLengthDescriptor->TDES1.dwReg;	
	pZeroLengthDescriptor->TDES1.dwReg = 0x09000000;	
	pZeroLengthDescriptor->TDES0.OwnBit = 1;	

    
    CSR6.dwReg = READ_PORT_ULONG(CSR6_REG);
    CSR6.StartTransmit = 1;
    WRITE_PORT_ULONG(CSR6_REG, CSR6.dwReg);
    WRITE_PORT_ULONG(CSR1_REG, 0xffffffff);		// Trigger transmitter...

	localDEBUGMSG ("Waiting for Zero Length Descriptor...\r\n");	
	while ((pZeroLengthDescriptor->TDES0.OwnBit) == 1)		
        {
		WRITE_PORT_ULONG(CSR1_REG, 0xffffffff);			
        }
      
	//	Restore the original TDES1 descriptor.
	pZeroLengthDescriptor->TDES1 = ZeroLengthDescriptorOriginTDES1;	


	// Now, setup the perfect filter packet...
	
	SetupDescriptorOriginTDES1.dwReg = pSetupDescriptor->TDES1.dwReg;	// Store original TDES1 value to restore later.		
	pSetupDescriptor->TDES1.dwReg = (0x69000000 | 192);					// Store this into descriptor and it is ready to go...
	pbBuffer = (PVOID)TO_VIRT(pSetupDescriptor->TDES2);
	memset (pbBuffer, 0xff, 500);		
	pbBuffer[0] = pbEthernetAddr[0];
	pbBuffer[1] = pbEthernetAddr[1];
	pbBuffer[4] = pbEthernetAddr[2];		
	pbBuffer[5] = pbEthernetAddr[3];
	pbBuffer[8] = pbEthernetAddr[4];
	pbBuffer[9] = pbEthernetAddr[5];		
	{
		PDWORD	pData = (PDWORD) pbBuffer;
		localDEBUGMSG ("pData[0] = 0x%x \r\n", *pData++);
		localDEBUGMSG ("pData[1] = 0x%x \r\n", *pData++);
		localDEBUGMSG ("pData[2] = 0x%x \r\n", *pData++);
	}
	
	
     
	// We are ready to hoo ha...
	pSetupDescriptor->TDES0.OwnBit = 1;	
	WRITE_PORT_ULONG(CSR1_REG, 0xffffffff);	

	// Now we just wait till it gobbles up the packets...
	localDEBUGMSG ("Waiting for DEC to perform perfect filtering...\r\n");		
	while ((pSetupDescriptor->TDES0.OwnBit) == 1)		
		WRITE_PORT_ULONG(CSR1_REG, 0xffffffff);			
	
		
	 	
	
	//	Finally, restore the original TDES1 for the setupdescriptor so that next packet won't be 
	//	treated as setup packet.
	pSetupDescriptor->TDES1.dwReg = SetupDescriptorOriginTDES1.dwReg;

	//	Turn off promiscuous mode from now onwards...
        CSR6.dwReg = READ_PORT_ULONG(CSR6_REG);
	CSR6.PromiscuousMode  = 0;				
	CSR6.ReceiveAll = 0;
        WRITE_PORT_ULONG(CSR6_REG, CSR6.dwReg);

	return TRUE;
}
#endif


/////////////////////////////////////////////////////////////////////////////////
//	DEC21140SendFrame -	This routine should be called with a pointer to the 
//						ethernet frame data.  It is the caller's responsibility 
//						to fill in all information including the destination and 
//						source addresses and the frame type.  
//						The length parameter gives the number of bytes in 
//						the ethernet frame.
//						The routine will return immediately regardless of 
//						whether transmission has successfully been performed by 
//						21140.
//	Error return:	Non zero.
//	No error:		Returns zero.
//

UINT16 DEC21140SendFrame( BYTE *pbData, DWORD dwLength )
{	
	DWORD					i = 0;
	DWORD					dwTotalSent = 0;
	DWORD					dwNumberOfDescriptorUsed = 0;
	DWORD					dwToSend;
    CSR6_21140  CSR6;

	volatile PTX_DESCRIPTOR_FORMAT	pFirstTxDescriptor;

⌨️ 快捷键说明

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