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

📄 drv_eth.c

📁 一个比较好的三星s3c4510的启动代码
💻 C
字号:
/***********************************************************************
 *  MODULE:        drv_eth.c     
 *  Description:   Ethernet Driver
 *  Runtime Env:   ARM7TDMI - KS32C50100
 *  Company:       
 *  Change History:
 *     03-28-02   Create (Yadong Wang)
 ***********************************************************************/
#include <string.h>
#include "snds.h"
#include "isr.h"
#include "mac.h"
//#include"drv_eth.h"
// Ethernet address, move to EEPRM later
U8 dev_addr[] = {0x00, 0x40, 0x95, 0x36, 0x35, 0x34};


/*****************************************************************
 * Local routines
 ****************************************************************/
void MAC_Tx_isr(void);
void MAC_Rx_isr(void);
void BDMA_Tx_isr(void);
void BDMA_Rx_isr(void);
void RxFDInitialize(void);
void TxFDInitialize(void);
void ReceivePackets(U8 *buf, U16 size);

/*****************************************************************
 * Local variables
 ****************************************************************/
// Rx Frame Descriptor, data buffer, and pointers
static sFrameDescriptor TxFDBaseAddr[MaxTxFrameDescriptors];
static sMACFrame TxFBABaseAddr[MaxTxFrameData];		
static volatile U32 gCTxFDPtr, gWTxFDPtr;

// Tx Frame Descriptor, data buffer, and pointers
static sFrameDescriptor RxFDBaseAddr[MaxRxFrameDescriptors];   
static sMACFrame RxFBABaseAddr[MaxRxFrameData];		
static volatile U32 gCRxFDPtr;

// Rx Status and error count
static U32 EthStatusAddr;		// anchor address
static pBDMARxStatus gsBdmaRxStatus;
static pMACRxStatus gsMacRxStatus;
static pMACTxStatus gsMacTxStatus;
//static pBDMATxStatus gsBdmaTxStatus;


/*****************************************************************
 * Init
 ****************************************************************/
void MIIWrite(unsigned long PhyInAddr, unsigned long PhyAddr, unsigned long PhyData)
{
	CSR_WRITE(STADATA, PhyData);
	CSR_WRITE(STACON, PhyInAddr | PhyAddr | MiiBusy | PHYREGWRITE);
	while(CSR_READ(STACON) & MiiBusy);
}

unsigned long MIIRead(unsigned long PhyInAddr, unsigned long PhyAddr)
{
	CSR_WRITE(STACON, PhyInAddr | PhyAddr | MiiBusy);
	while(CSR_READ(STACON) & MiiBusy);
	return CSR_READ(STADATA);
}

U16 DrvEthInit()
{
	U8 i;
	unsigned long status;

	/*-----------------------------------------------------------------*
	 *  1. Disable MAC and BDMA interrupts.                            *
	 *-----------------------------------------------------------------*/
	Disable_Int(nMAC_RX_INT) ;     // Disable MAC Rx Interrupt
	Disable_Int(nMAC_TX_INT) ;     // Disable MAC Tx Interrupt
	Disable_Int(nBDMA_RX_INT) ;    // Disable BDMA Rx Interrupt
	Disable_Int(nBDMA_TX_INT) ;    // Disable BDMA Tx Interrupt

	/*-----------------------------------------------------------------*
	 * 2. BDMA and MAC interrupt vector setup.                         * 
	 *-----------------------------------------------------------------*/
	SysSetInterrupt(nMAC_RX_INT, MAC_Rx_isr);
	SysSetInterrupt(nMAC_TX_INT, MAC_Tx_isr);		// needed
	SysSetInterrupt(nBDMA_RX_INT, BDMA_Rx_isr);		// needed
	SysSetInterrupt(nBDMA_TX_INT, BDMA_Tx_isr);

	/*-----------------------------------------------------------------*
 	 * 3. Set the initial condition of the BDMA, and MAC               * 
 	 *-----------------------------------------------------------------*/
	BDMARXCON = BRxRS ;             // Reset BDMAC Receiver
	BDMATXCON = BTxRS ;             // Reset BDMAC Transceiver
	MACCON = Reset ;
	BDMARXLSZ = sizeof(sMACFrame); //MaxRxFrameSize+40 ;    // 1520
	MACCON = 0; //CompEn | BroadAcc;

	/*-----------------------------------------------------------------*
 	 * 4. Set the BDMA Tx/Rx Frame Descriptor                          *
 	 *-----------------------------------------------------------------*/
	TxFDInitialize();
	RxFDInitialize();

	/*-----------------------------------------------------------------*
 	 * 5. Set the CAM Control register and the MAC address value       *
 	 *-----------------------------------------------------------------*/
 	// CAM0 register of CAM registers : 0x9100~0x9103, 0x9104, 0x9105
	for(i = 0; i < 4; i++)
		CAM_Reg(0) = (CAM_Reg(0) << 8) | dev_addr[i];
	for(i = 4; i < 6; i++)
		CAM_Reg(1) = (CAM_Reg(1) << 8) | dev_addr[i];
	CAM_Reg(1) = (CAM_Reg(1) << 16);

	// CAM Enable Register(CAMEN)
	CAMEN = 0x0001 ;
	CAMCON = CompEn | BroadAcc;

	/*-----------------------------------------------------------------*
	 * 6. Enable interrupt BDMA Rx and MAC Tx interrupt.               *
	 *-----------------------------------------------------------------*/
	Enable_Int(nBDMA_RX_INT); 
	//Enable_Int(nMAC_TX_INT);
	//Enable_Int(nMAC_RX_INT);

	/*-----------------------------------------------------------------*
 	 * 7. Configure the BDMA and MAC control registers.                *
 	 *-----------------------------------------------------------------*/
	BDMATXCON = BTxBRST | BTxMSL110 | BTxSTSKO | BTxEn;  //11000000101111//302F
	//MACTXCON  = EnComp | TxEn;
	BDMARXCON = BRxDIE | BRxEn | BRxLittle | BRxMAINC | BRxBRST | BRxNOIE | BRxSTSKO | BRxNLIE |BRxWA10; //
	MACRXCON = RxEn;

	/*-----------------------------------------------------------------*
 	 * 8. PHY init                                                     *
 	 *-----------------------------------------------------------------*/
#if 1
	i_printf("Reseting PHY\n\r");
	MIIWrite(0x0, 0x0, 1<<15);
	while((MIIRead(0x0, 0x0) & (1<<15)));
	
	
	i_printf("Perform AN again\n\r");
	MIIWrite(0x0, 0x0, MIIRead(0x0, 0x0) & ~(1<<12));
//	while(!(MIIRead(0x11, 0x0) & (1<<4)));

	MIIWrite(0x0, 0x2, 1<<13|1<<8);
	
	status = MIIRead(0x1, 0x0);
	if(status & 1<<15)
		i_printf("10M/b  \r");
	else
		i_printf("100M/b  ");
	if(status & 1<<14)
		i_printf("Full duplex\n\r");
	else	i_printf("Half duplex\n\r");
#endif	

	// Start the transmit queue
	//netif_start_queue(dev);
	//EthData[ETH_STS_ADDR] = (U32)(&EthStatusAddr);

	return 0;
}


/*****************************************************************
 * Write
 * Description : Send ethernet frame function
 * Input : frame data pointer, frame length
 * Output : transmit ok(1) or error(0)
 ****************************************************************/
int DrvEthWrite(U8 *Data,int Size)
{
	sFrameDescriptor	*psTxFD;
	U32 *pFrameDataPtr ;
	U8  *pFrameData ;
	int	 FrameLength ;

	// 1. Get Tx frame descriptor & data pointer
	psTxFD = (sFrameDescriptor *)gWTxFDPtr ;
	pFrameData = (U8 *)psTxFD->FrameDataPtr ;
	pFrameDataPtr = (U32 *)&psTxFD->FrameDataPtr;
	FrameLength = Size + sizeof(etheader) ;

	// 2. Check BDMA ownership
	if ( (*pFrameDataPtr & BDMA_owner) ) 
		return 0 ;

	// 3. Prepare Tx Frame data to Frame buffer
	memcpy ((U8 *)pFrameData,(U8 *)Data,FrameLength);

	// 4. Set TX Frame flag & Length Field
	psTxFD->Reserved = (Padding | CRCMode | FrameDataPtrInc | \
			LittleEndian | WA00 | MACTxIntEn);
	psTxFD->StatusAndFrameLength = (U32)(FrameLength & 0xffff);

	// 5. Cheange ownership to BDMA
	psTxFD->FrameDataPtr |= BDMA_owner;

	// 6. Enable MAC and BDMA Tx control register
	if (!(BDMATXCON & BTxEn))  
		BDMATXCON |= BTxEn ;
	MACTXCON |= TxEn  ;

	// 7. Change the Tx frame descriptor for next use
	gWTxFDPtr = (U32)(psTxFD->NextFrameDescriptor);

	return 1 ;
}


/*****************************************************************
 * Read, through ISR and call back
 ****************************************************************/


/*****************************************************************
 * Local routines
 ****************************************************************/

// init Tx Frame Descriptor 
void TxFDInitialize(void)
{
	sFrameDescriptor *pFrameDescriptor;
	sFrameDescriptor *pStartFrameDescriptor;
	sFrameDescriptor *pLastFrameDescriptor = NULL;
	U32 FrameDataAddr, i;

	// Get Frame descriptor's base address.   
	// +0x4000000 is for setting this area to non-cacheable area. 
	BDMATXPTR = (U32)TxFDBaseAddr + 0x4000000;
	gWTxFDPtr = gCTxFDPtr = BDMATXPTR;

	// Get Transmit buffer base address.
	FrameDataAddr = (U32)TxFBABaseAddr + 0x4000000;

	// Generate linked list.
	pFrameDescriptor = (sFrameDescriptor *) gCTxFDPtr;
	pStartFrameDescriptor = pFrameDescriptor;

	for(i=0; i < MaxTxFrameDescriptors; i++)  
	{
		if(pLastFrameDescriptor == NULL)
			pLastFrameDescriptor = pFrameDescriptor;
		else  	
			pLastFrameDescriptor->NextFrameDescriptor = (U32)pFrameDescriptor;

		pFrameDescriptor->FrameDataPtr = (U32)(FrameDataAddr & CPU_owner);
		pFrameDescriptor->Reserved = (U32)0x0;
		pFrameDescriptor->StatusAndFrameLength = (U32)0x0;
		pFrameDescriptor->NextFrameDescriptor = NULL;
		pLastFrameDescriptor = pFrameDescriptor;
		pFrameDescriptor++;
		FrameDataAddr += sizeof(sMACFrame);
	} // end for loop

	// Make Frame descriptor to ring buffer type.     
	pFrameDescriptor--; 
	pFrameDescriptor->NextFrameDescriptor = (U32)pStartFrameDescriptor;
}


// init Rx Frame Descriptor 
void RxFDInitialize(void)
{
	sFrameDescriptor *pFrameDescriptor;
	sFrameDescriptor *pStartFrameDescriptor;
	sFrameDescriptor *pLastFrameDescriptor = NULL;
	U32 FrameDataAddr, i;

	// Get Frame descriptor's base address.  
	// +0x4000000 is for setting this area to non-cacheable area. 
	BDMARXPTR = (U32)RxFDBaseAddr + 0x4000000;
	gCRxFDPtr = BDMARXPTR;
	
	// Get Transmit buffer base address.  
	FrameDataAddr = (U32)RxFBABaseAddr + 0x4000000;

	// Generate linked list. 
	pFrameDescriptor = (sFrameDescriptor *) gCRxFDPtr;
	pStartFrameDescriptor = pFrameDescriptor;
	
	for(i=0; i < MaxRxFrameDescriptors; i++)  
	{
		if(pLastFrameDescriptor == NULL)
			pLastFrameDescriptor = pFrameDescriptor;
		else  	
			pLastFrameDescriptor->NextFrameDescriptor = (U32)pFrameDescriptor;
		
		pFrameDescriptor->FrameDataPtr =
			(U32)(FrameDataAddr | BDMA_owner | 0x4000000 );
		pFrameDescriptor->Reserved = (U32)0x0;
		pFrameDescriptor->StatusAndFrameLength = (U32)0x0;
		pFrameDescriptor->NextFrameDescriptor = NULL;
		pLastFrameDescriptor = pFrameDescriptor;
		pFrameDescriptor++;
		FrameDataAddr += sizeof(sMACFrame); 
	} // end for loop
      
	// Make Frame descriptor to ring buffer type.     
	pFrameDescriptor--; 
	pFrameDescriptor->NextFrameDescriptor = (U32)pStartFrameDescriptor;
}


void MAC_Rx_isr()
{ 
}

void BDMA_Tx_isr() 
{ 
}


// ISR for BDMA Rx (Ethenet Frame is received)
void BDMA_Rx_isr(void)
{
	sFrameDescriptor *pRxFDptr ;
	U16 error = 0;
	U32 RxStatus, FrameLength ;
	U32 CRxPtr;
	U32 sBdmaStat ;
	U8 *pFrameData ;

	// Step 1. Get current frame descriptor and status
	CRxPtr = BDMARXPTR ;
	sBdmaStat = BDMASTAT ;

	// Step 2. Clear BDMA status register bit by write 1
	BDMASTAT |= sBdmaStat & 0x17001D;
	gsBdmaRxStatus.BdmaRxCnt++ ;

	do 
	{
		// Step 3. Check Null List Interrupt
		if ( BDMASTAT & S_BRxNL ) 
		{
			BDMASTAT |= S_BRxNL ;
			gsBdmaRxStatus.BRxNLErr++ ;
			// MacInitialize() ;
			error = 1;
			break ;
		}

		// Step 4. Get Rx Frame Descriptor
		pRxFDptr = (sFrameDescriptor *)gCRxFDPtr ;
		RxStatus = (pRxFDptr->StatusAndFrameLength >> 16) & 0xffff;

		// Step 5. If Rx frame is good, then process received frame
		if((RxStatus & Good)&&!(RxStatus & OvMax)) 
		{
			FrameLength = pRxFDptr->StatusAndFrameLength & 0xffff - 4; 
			pFrameData = (U8 *)pRxFDptr->FrameDataPtr + 2;
			gsBdmaRxStatus.BdmaRxGood++ ;
	
			//Step 6. Get received frame to memory buffer
			ReceivePackets(pFrameData, FrameLength);
		} 
		else 
		{
			error = 1;
			// Step 7. If Rx frame has error, then process error frame
			gsMacRxStatus.gErrorPacketCnt++ ;
			if (RxStatus & OvMax)		gsMacRxStatus.OvMaxSize++;
			if (RxStatus & CtlRcv)		gsMacRxStatus.sCtlRecd++;
			if (RxStatus & Rx10Stat)	gsMacRxStatus.sRx10Stat++;
			if (RxStatus & AlignErr)	gsMacRxStatus.AllgnErr++;
			if (RxStatus & CRCErr)		gsMacRxStatus.sCRCErr++;
			if (RxStatus & Overflow)	gsMacRxStatus.OverflowErr++;
			if (RxStatus & LongErr)		gsMacRxStatus.sLongErr++;
			if (RxStatus & RxPar)		gsMacRxStatus.RxParErr++;
			if (RxStatus & RxHalted)	gsMacRxStatus.sRxHalted++;
		}

		// Step 8. Change ownership to BDMA for next use
		(pRxFDptr->FrameDataPtr) |= BDMA_owner;

		// Save Current Status and Frame Length field, and clear
		pRxFDptr->StatusAndFrameLength = (U32)0x0;

		// Step 9. Get Next Frame Descriptor pointer to process
		gCRxFDPtr = (U32)(pRxFDptr->NextFrameDescriptor) ;

	} while (CRxPtr != gCRxFDPtr);

	// Step 10. Check Notowner status
	if ( sBdmaStat & S_BRxNO ) 
	{
		BDMASTAT |= S_BRxNO ;
		gsBdmaRxStatus.BRxNOErr++ ;
		// ReadyMacRx() ;
	}
}



// ISR for MAC Tx
void MAC_Tx_isr(void)
{   
	sFrameDescriptor *pTxFDptr;
	U32 *pFrameDataPtr ;
	U32 Status ;
	U32 CTxPtr ;
	
	CTxPtr = BDMATXPTR ;
	while ( gCTxFDPtr != CTxPtr )  
	{ 
		pTxFDptr = (sFrameDescriptor *) gCTxFDPtr;

		// Check CPU ownership, if Owner is BDMA then break
		pFrameDataPtr = (U32 *)&pTxFDptr->FrameDataPtr;
		if ( (*pFrameDataPtr & BDMA_owner) ) 
			break ;
	
		Status = (pTxFDptr->StatusAndFrameLength >> 16) & 0xffff;
		if (Status & Comp) 
		{
			gsMacTxStatus.MacTxGood++ ;
		}
		else
		{
			// Save Error status
			// Check each status, because, error can duplicated
			if (Status & Under) gsMacTxStatus.UnderErr++ ;
			if (Status & ExColl) gsMacTxStatus.ExCollErr++ ;
			if (Status & TxDefer) gsMacTxStatus.TxDefferedErr++ ;
			if (Status & Paused) gsMacTxStatus.sPaused++ ;
			if (Status & Defer) gsMacTxStatus.DeferErr++ ;
			if (Status & NCarr) gsMacTxStatus.NCarrErr++ ;
			if (Status & SQErr) gsMacTxStatus.sSQE++ ;
			if (Status & LateColl) gsMacTxStatus.LateCollErr++ ;
			if (Status & TxPar) gsMacTxStatus.TxParErr++ ;
			if (Status & TxHalted) gsMacTxStatus.sTxHalted++ ;

			// Set MAC/BDMA Tx control register for next use.
			// MacDebugStatus() ; 
			//	ReadyMacTx() ;
		} 

		// Clear Framedata pointer already used.
		pTxFDptr->StatusAndFrameLength = (U32)0x0;
		gCTxFDPtr = (U32)pTxFDptr->NextFrameDescriptor ;
	} 
}

/*********************************************************************** *  Call Back by Ethernet Rx Interrupt ***********************************************************************/

⌨️ 快捷键说明

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