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

📄 am79c970.c

📁 可在VMWare workstation中的运行的wince 5 bsp
💻 C
📖 第 1 页 / 共 3 页
字号:
	//
	pCurrentTxDesc = (PTX_DESCRIPTOR_FORMAT) dwTRANSMIT_DESCRIPTORS_HEAD;		
	pLastTxDesc    = (PTX_DESCRIPTOR_FORMAT) (pCurrentTxDesc + dwTRANSMIT_RING_SIZE - 1);

	for (i = 0 ; i < dwTRANSMIT_RING_SIZE ; i++)
	{
		InitTxDescriptor ((PTX_DESCRIPTOR_FORMAT) (pCurrentTxDesc + i), 
						  (DWORD) (dwTRANSMIT_BUFFER_START + i * MAX_BUFFER_SIZE));
	}
	//DumpTxDescriptors();


	/////////////////////////////////////////////////////////////////////////////
	//	Initialize RX Descriptors...
	//
	pCurrentRxDesc = (PRX_DESCRIPTOR_FORMAT) dwRECEIVE_DESCRIPTORS_HEAD;
	pLastRxDesc    = (PRX_DESCRIPTOR_FORMAT) (pCurrentRxDesc + dwRECEIVE_RING_SIZE - 1) ;

	for (i = 0 ; i < dwRECEIVE_RING_SIZE ; i++)
	{
		InitRxDescriptor ((PRX_DESCRIPTOR_FORMAT) (pCurrentRxDesc + i), 
						  (DWORD) (dwRECEIVE_BUFFER_START + i * MAX_BUFFER_SIZE));
	}
	//DumpRxDescriptors();


	/////////////////////////////////////////////////////////////////////////////
	//	All aboard... Let the engine roar...	
	//
	
	WriteCSR (0, (ReadCSR(0) | 0x02) & ~0x04);	// Turn on START bit...and turn off STOP bit.

/*
	DumpOneRxDescriptor (pCurrentRxDesc);
	while (pCurrentRxDesc->RMD1.OWN)
		;
	localDEBUGMSG ("Data received...%d bytes\r\n", pCurrentRxDesc->RMD2.MCNT);
	DumpOneRxDescriptor (pCurrentRxDesc);
	DumpOneRxDescriptor (pCurrentRxDesc + 1);
	DumpMemory ((PUCHAR) (TO_VIRT(pCurrentRxDesc->RBADR)), pCurrentRxDesc->RMD2.MCNT);		
	for (;;)
		;
*/

	SleepLoop(5000);
	localDEBUGMSG ("CSR0 == 0x%x \r\n", ReadCSR(0));		

	return TRUE;
}	// AM79C970Init()


/////////////////////////////////////////////////////////////////////////////////
//	AM79C970EnableInts()
//	For Ether Debug, we only need Receive Interrupt.
//	Hence, turn on IENA and mask all other interrupts except Receive Interrupt.
//
void	AM79C970EnableInts (void)
{
	/////////////////////////////////////////////////////////////////////////////
	//	First, make sure all interrupts are mask, except the receive interrupt...
	//

	WriteCSR (3, ReadCSR(3) | CSR3_MASK_ALL_INTS);
	WriteCSR (4, ReadCSR(4) | CSR4_MASK_ALL_INTS);
	WriteCSR (5, ReadCSR(5) | CSR5_MASK_ALL_INTS);	
	WriteCSR (3, ReadCSR(3) & ~CSR3_RINTM);

	
	/////////////////////////////////////////////////////////////////////////////
	//	Then enable IENA in CSR0, the father of all interrupts !!!
	//

	WriteCSR (0, ReadCSR(0) | CSR0_IENA);		

		
	{
		//RETAILMSG (1, (TEXT("CSR0 = 0x%x \r\n"), ReadCSR(0)));		
		//RETAILMSG (1, (TEXT("CSR3 = 0x%x \r\n"), ReadCSR(3)));				
		//RETAILMSG (1, (TEXT("CSR4 = 0x%x \r\n"), ReadCSR(4)));
		//RETAILMSG (1, (TEXT("CSR5 = 0x%x \r\n"), ReadCSR(5)));
		//RETAILMSG (1, (TEXT("BCR2 = 0x%x \r\n\r\n\r\n"), ReadBCR(2)));
		
	}
		


}	// AM79C970EnableInts()


/////////////////////////////////////////////////////////////////////////////////
//	AM79C970DisableInts()
//	Simply turn off CSR0_IOENA...
//
void	AM79C970DisableInts(void)
{
	WriteCSR (0, (ReadCSR(0) & ~CSR0_IENA));

}	// AM79C970DisableInts()


/////////////////////////////////////////////////////////////////////////////////
//	
//
DWORD	AM79C970GetPendingInts(void)
{	
	//RETAILMSG (1, (TEXT("GetPending: CSR0 = 0x%x \r\n"), ReadCSR(0)));

	WriteCSR (0, ReadCSR(0) | CSR0_RINT);
	return INTR_TYPE_RX;

}	// AM79C970EnableInts()




/////////////////////////////////////////////////////////////////////////////////
//	AM79C970GetFrame()
//
//	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 is a frame that was received correctly, it will be stored in pwData, 
//	otherwise it will be discarded.  
//

void SkipAllErrorDescriptors(void)
{
	/////////////////////////////////////////////////////////////////////////
	//	FM-FM-FM Should investigate properly what causes this, instead of
	//	just blowing them away...
	//	ASSUMING that OWN will be set even for ERRORNEOUS packets...
	//	
	while (pCurrentRxDesc->RMD1.OWN && pCurrentRxDesc->RMD1.ERR)
	{
		localDEBUGMSG ("Error Descriptor: %d\r\n", 
			pCurrentRxDesc - (PRX_DESCRIPTOR_FORMAT) dwRECEIVE_DESCRIPTORS_HEAD);
		InitRxDescriptor (pCurrentRxDesc, 0);
		pCurrentRxDesc = GetNextRxDesc (pCurrentRxDesc);
	}
}	// SkipAllErrorDescriptors()



BOOL Broadcast(PBYTE pHeader)
{
	int	i = 0;
	while (1)
	{
		if (pHeader[i++] != 0xff)
			break;
		if (i == 6)
			return TRUE;		
	}
	
	return FALSE;
}	// Broadcast()



UINT16	AM79C970GetFrame(BYTE *pbData, UINT16 *pwLength, BOOL	bBootLoaderCall)
{
	
	BOOL	bDone			= FALSE;		//	When we loop for ENP.
	UINT16	dwOffset		= 0;			//	Offset to User's pbData...
	UINT16	dwBytesToCopy	= 0;
	BOOL	bTossedPacket   = FALSE;
	PBYTE	pHeader;
	

	*pwLength = 0;

	/////////////////////////////////////////////////////////////////////////////
	//	Bail out immediately if there is no data avail...
	//
	if (pCurrentRxDesc->RMD1.OWN)
		return 0;

	/////////////////////////////////////////////////////////////////////////////
	//	Okay, at least we must have all or part of data available...
	//	ASSUMING AMD is doing the right thing, I won't detect STP but just the
	//	ENP.   If error happens in between packets, whatever received will be 
	//	tossed away.
	//	[stjong 11/14/98]
	//	Alright, it is a WRONG assumption, if STP is set without ENP, it means
	//	the whole buffer is filled, eventhough MCNT reports zero !!!
	//	What's more, the last packet contains the exact total number of packets
	//	received... (what a bummer !!!)
	//
	while (!bDone)
	{
		//localDEBUGMSG ("Using RX Descriptor Number: %d \r\n", 
		//	(pCurrentRxDesc - (PRX_DESCRIPTOR_FORMAT) dwRECEIVE_DESCRIPTORS_HEAD));

		/////////////////////////////////////////////////////////////////////////
		//	If it is error packets, throw away until we get to descriptor not 
		//	yet used.   And return zero to user...
		//
		if (pCurrentRxDesc->RMD1.ERR)
		{				
			SkipAllErrorDescriptors();
			return 0;
		}		


		/////////////////////////////////////////////////////////////////////////
		//	So here is the logic,
		//	If it is ENP (End Of Packet) and STP (Start Of Packet), 
		//	number of bytes to copy is the number of bytes pointed to by MCNT.
		//	If it is NOT end of packet, then MAX_BUFFER_SIZE takes effect.
		//	For multi buffer packet (ONLY ENP set and NOT STP), we just need to 
		//	copy whatever less to make up MCNT.
		//

		if (!bBootLoaderCall && pCurrentRxDesc->RMD1.STP)		
		{
			/////////////////////////////////////////////////////////////////////
			//	Determine if we need to toss this packet away...
			//	Toss this away if it is non ARP broadcast...
			//
			pHeader = (PVOID)TO_VIRT(pCurrentRxDesc->RBADR);
			if (Broadcast(pHeader))
			{
				if (pHeader[12] != 0x08 && pHeader[13] != 0x06)
				{
					/////////////////////////////////////////////////////////////
					//	This packet is tossed...
					//					
					bTossedPacket = TRUE;				
				}
			}
		}


		if (pCurrentRxDesc->RMD1.ENP)
		{
			bDone = TRUE;
			if (pCurrentRxDesc->RMD1.STP)
				dwBytesToCopy = (UINT16) pCurrentRxDesc->RMD2.MCNT;
			else
				dwBytesToCopy = (UINT16) (pCurrentRxDesc->RMD2.MCNT - dwOffset);
		}
		else
			dwBytesToCopy = MAX_BUFFER_SIZE;

		if (bTossedPacket)
			dwBytesToCopy = 0x00;

		// localDEBUGMSG ("BYTES COPIED : %d\r\n", dwBytesToCopy);

		memcpy (pbData + dwOffset, 
				(PVOID) TO_VIRT(pCurrentRxDesc->RBADR),
				dwBytesToCopy);

		dwOffset += dwBytesToCopy;								//	Increase what we have copied so far.
		
		InitRxDescriptor(pCurrentRxDesc, 0);					//	Initialize the used RX Descriptor.	
		pCurrentRxDesc = GetNextRxDesc (pCurrentRxDesc);		//	Forward to next descriptor...
		

		/////////////////////////////////////////////////////////////////////////
		//	Now, if I am not done yet and the next packet is now owned by me,
		//	just loop till it is owned by me...
		//	In interrupt mode, it should be Okay, because by the time RX interrupt
		//	received, I am guaranteed to have received the entirety of the packet.
		//	For Bootloader download, I don't care, it is single task and I will
		//	have nothing else to do except waiting for the data...
		//	But becareful not to poll too fast, as it affects the DMA transfer
		//	that must be going on...
		//
		
		if (!bDone)
		{
			while (pCurrentRxDesc->RMD1.OWN)
			{
				localDEBUGMSG (">>> Waiting for descriptor %d to complete packet.\r\n",
					pCurrentRxDesc - (PRX_DESCRIPTOR_FORMAT) dwRECEIVE_DESCRIPTORS_HEAD);
				SleepLoop(10000000);
			}					
		}
	}

	// DumpSenderAddr (pbData);

	if (dwOffset >= 4) 
		dwOffset -=4; // Takeout CRC.
	*pwLength = (UINT16)dwOffset;
	return (UINT16)dwOffset;
}	// AM79C970GetFrame()



/////////////////////////////////////////////////////////////////////////////////
//	AM79C970SendFrame()
//
//	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.
//	

UINT16	AM79C970SendFrame(BYTE *pbData, DWORD dwLength)
{
	UINT		dwTotalCopied = 0;
	UINT		dwBytesToCopy = 0;
	
	volatile	PTX_DESCRIPTOR_FORMAT	pFirstTxDesc = pCurrentTxDesc;
	volatile	PTX_DESCRIPTOR_FORMAT	pNextTxDesc;


	// localDEBUGMSG ("\r\n*** Sending: %d bytes.\r\n", dwLength);	

	/////////////////////////////////////////////////////////////////////////////
	//	Loop until all data has been copied to the descriptor's buffer.
	//	Depending on buffer size, all data may fit into one buffer or span 
	//	through multiple descriptors' buffers.
	//	

	while (dwTotalCopied < dwLength)
	{	
		localDEBUGMSG ("Using TX Descriptor Number: %d \r\n", 
			(pCurrentTxDesc - (PTX_DESCRIPTOR_FORMAT) dwTRANSMIT_DESCRIPTORS_HEAD));	


		/////////////////////////////////////////////////////////////////////////
		//	Figure out how many bytes to copy to descriptor's buffer...
		//	
		if ((dwLength - dwTotalCopied) < MAX_BUFFER_SIZE)			
			dwBytesToCopy = (dwLength - dwTotalCopied);
		else
			dwBytesToCopy = MAX_BUFFER_SIZE;

		memcpy ((PVOID)TO_VIRT(pCurrentTxDesc->TBADR),			
				 pbData + dwTotalCopied, 
				 dwBytesToCopy);		

⌨️ 快捷键说明

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