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

📄 ethernet.c

📁 开发三星s3c44b0引导程序
💻 C
字号:
#include <zooboot.h>
#include <command.h>
#include <hardware.h>
#include <net.h>


#ifdef CFG_DRIVER_ETHER

#if (CFG_COMMANDS & CFG_CMD_NET)


#define LITTLE

int pad0[10];
sFrameDescriptor RxFDBaseAddr[MaxRxFrameDescriptors*2];   //Ethernet0 Rx Frame Descriptor
int pad1[10];
sMACFrame RxFBABaseAddr[MaxRxFrameData*2];		//Ethernet0 Rx Frame Buffer

sFrameDescriptor TxFDBaseAddr0[MaxTxFrameDescriptors*2];   //Ethernet0 Tx Frame Descriptor
sMACFrame TxFBABaseAddr0[MaxTxFrameData*2];		//Ethernet0 Tx Frame Buffer

// Global variables  used for MAC driver

#if WITH_CRC
	volatile U32 gMacRxCon = RxEn ;
#else
	volatile U32 gMacRxCon = RxEn | StripCRC ;
#endif

volatile U32 gBdmaTxCon = BTxBRST | BTxMSL111 | BTxSTSKO ;


#ifdef LITTLE
	volatile U32 gBdmaRxCon = BRxDIE | BRxEn | BRxLittle | BRxMAINC | BRxBRST | \
    	                      BRxNLIE | BRxNOIE | BRxSTSKO ;
#else
	volatile U32 gBdmaRxCon = BRxDIE | BRxEn | BRxBig | BRxMAINC | BRxBRST | \
    	                      BRxNLIE | BRxNOIE | BRxSTSKO |BRxWA00;
#endif


volatile U32 gCamCon = StationAcc | BroadAcc | GroupAcc;  // promiscuous mode
//volatile U32 gCamCon = BroadAcc | CompEn;

volatile U32 gCTxFDPtr0, gWTxFDPtr0 ;
volatile U32 gCRxFDPtr0, gPreviousFdp=0 ;
volatile U32 gCam0_Addr0 = 0 , gCam0_Addr1 = 0  ;
volatile int gErrorPacketCnt =0 ;

// Global variable structure for store status
//Ethernet0
pMACTxStatus gsMacTxStatus = {0,0,0,0,0,0,0,0,0,0,0} ;
pMACRxStatus gsMacRxStatus = {0,0,0,0,0,0,0,0,0} ;
pBDMATxStatus gsBdmaTxStatus = {0,0,0} ;
pBDMARxStatus gsBdmaRxStatus = {0,0,0,0,0} ;


/* Initialize Tx frame descriptor area-buffers */
static
void TxFDInitialize(void)
{
	sFrameDescriptor *pFrameDescriptor;
	sFrameDescriptor *pStartFrameDescriptor;
	sFrameDescriptor *pLastFrameDescriptor = NULL;
	U32 FrameDataAddr;
	U32 i;
	
	// Get Frame descriptor's base address.   
	// +0x400_0000 is for setting this area to non-cacheable area. 
	BDMATXPTR0 = (U32)TxFDBaseAddr0 + 0x4000000;
	gWTxFDPtr0 = gCTxFDPtr0 = BDMATXPTR0;

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

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

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

		pFrameDescriptor->FrameDataPtr = 
			(U32)(FrameDataAddr & fOwnership_CPU);
		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;
}

/* Initialize Rx frame descriptor area-buffers */
static
void RxFDInitialize(void)
{
	sFrameDescriptor *pFrameDescriptor;
	sFrameDescriptor *pStartFrameDescriptor;
	sFrameDescriptor *pLastFrameDescriptor = NULL;
	U32 FrameDataAddr;
	U32 i;
	
	// Get Frame descriptor's base address.  
	// +0x4000000 is for setting this area to non-cacheable area. 
	BDMARXPTR0 = (U32)RxFDBaseAddr + 0x4000000;
	gCRxFDPtr0 = BDMARXPTR0;
	
	// Get Transmit buffer base address.  
	FrameDataAddr = (U32)RxFBABaseAddr + 0x4000000;

	// Generate linked list. 
	pFrameDescriptor = (sFrameDescriptor *) gCRxFDPtr0;
	pStartFrameDescriptor = pFrameDescriptor;
	
	for(i=0; i < MaxRxFrameDescriptors; i++)  {
		if(pLastFrameDescriptor == NULL)
			pLastFrameDescriptor = pFrameDescriptor;
		else  	
			pLastFrameDescriptor->NextFrameDescriptor = (U32)pFrameDescriptor;

		pFrameDescriptor->FrameDataPtr =
			(U32)(FrameDataAddr | fOwnership_BDMA | 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;
}

/* set Tx Registers related with BDMA & MAC to transmit packet */
static
void ReadyMacTx(void)
{	
	BDMATXCON0 = gBdmaTxCon ;
	MACTXCON0 =  EnComp ;
}

/* set Rx Registers related with BDMA & MAC to Receive packet */
static
void ReadyMacRx(void)
{	
	BDMARXCON0 = gBdmaRxCon ;
	MACRXCON0 = gMacRxCon ;
}

/* MAC Transfer Start for interactive mode */
static
void MacTxGo(int mac_n)
{		
	// Enable MAC and BDMA Transfer
	if (!(MACTXCON0 & TxEn))  MACTXCON0 |= TxEn ;
	if (!(BDMATXCON0 & BTxEn))  BDMATXCON0 |= BTxEn ;
}

/* Get MAC Address From IIC EEPROM */
static
void GetMyMacAddr(void)
{
	U8 MacAddr[MAC_ADDR_SIZE];
	U8 TempAddr[MAC_ADDR_SIZE];
	int i;
	
	gCam0_Addr0 = gCam0_Addr1 = 0 ;
				
	/* samsung's mac */
	MacAddr[0] = 0x00 ;
	MacAddr[1] = 0x00 ;
	MacAddr[2] = 0xf0 ;
	MacAddr[3] = 0x90 ;
	MacAddr[4] = 0x11 ;
	MacAddr[5] = 0x11 ;
		
	/* Get MAC Address */
	for (i=0;i<(int)MAC_ADDR_SIZE;i++)  TempAddr[i] = MacAddr[i];

	/* Copy MAC Address to global variable */
	/* big endian */
	for (i=0;i<(int)MAC_ADDR_SIZE-2;i++)
		gCam0_Addr0 = (gCam0_Addr0 << 8) | TempAddr[i] ;

	for (i=(int)(MAC_ADDR_SIZE-2);i<(int)MAC_ADDR_SIZE;i++)
		gCam0_Addr1 = (gCam0_Addr1 << 8) | TempAddr[i] ;
	gCam0_Addr1 = (gCam0_Addr1 << 16) ;
}

/* Initialize MAC and BDMA Controller */
static
void MacInitialize(void)
{		
	int cam_n=0;
	
	/* 1. Disable MAC and BDMA interrupts */
	//Disable_Intr(nMAC0_TX_INT) ;     // Disable MAC0 Tx Interrupt
	//Disable_Intr(nBDMA0_RX_INT) ;    // Disable BDMA0 Rx Interrupt
	
	/* 2. BDMA and MAC interrupt vector setup */
	//SysSetInterrupt(nMAC0_TX_INT, MAC0_Tx_isr) ;
	//SysSetInterrupt(nBDMA0_RX_INT, BDMA0_Rx_isr) ; 

	/* 3. Set the initial condition of the BDMA, and MAC */
 	//Ethernet0 
	BDMARXCON0 = BRxRS ;				// Reset BDMAC Receiver
	BDMARXCON0 = 0x0;				// Reset signal Rise.
		
	BDMATXCON0 = BTxRS ;             // Reset BDMA0 Transceiver
	MACCON0 = SwReset ;
	BDMARXLSZ0 = MaxRxFrameSize+20 ;    // 1517=0x05EC; 1520
	MACCON0 = FullDup ;
		
	/* 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
	cam_n= Cam_index+(Cam_index/2);
	CAM_Reg0(cam_n) =  gCam0_Addr0;
	cam_n++;
	CAM_Reg0(cam_n) =  gCam0_Addr1;

	// CAM Enable Register(CAM_index)
	CAMEN0 = (1<<Cam_index);
	CAMCON0 = gCamCon ;

	/* 6. Enable interrupt BDMA Rx and MAC Tx interrupt */
	//Enable_Intr(nBDMA0_RX_INT); 
	//Enable_Intr(nMAC0_TX_INT);

 	/* 7. Configure the BDMA and MAC control registers */
	ReadyMacTx() ;
	ReadyMacRx() ;
}

static
void delay_physet(void) 
{
	int i=1000 ;
	while(i--) ;
}

/* MII Interface Station Management Register Read or Write */
static
void MiiStationWrite(U32 PhyInAddr, U32 PhyAddr, U32 PhyWrData)
{
	STADATA0 = PhyWrData ;
	STACON0 = PhyInAddr | PhyAddr |  MiiBusy | PHYREGWRITE ;
	while( (STACON0 & MiiBusy) )  ;
	delay_physet() ;
}


/* Reset The Phychip, Auto-Negotiation Enable */
static
void ResetPhyChip(void)
{
	// For MII I/F
	//MiiStationWrite(PHY_CNTL_REG,PHYHWADDR, ENABLE_AN | RESTART_AN);  // Auto-negotiation	
	MiiStationWrite(PHY_CNTL_REG,PHYHWADDR,0x0) ; // 10M Half duplex
}


/* Initialize Phy and Mac */
static
void EthInitialize(void)
{
	// Reset the PHY chip and start Auto-negotiat
	ResetPhyChip() ;

	// Read MAC address from IIC EEPROM
	GetMyMacAddr() ;
	
	// Initialize MAC and BDMA controller
	MacInitialize() ;
}

/* Interrupt Service Routine for MAC0 Tx 
   Only check status */
void MAC0_Tx_isr(void)
{   
	sFrameDescriptor *pTxFDptr;
	U32 *pFrameDataPtr ;
	U32 Status ;
	U32 CTxPtr ;

	CTxPtr = BDMATXPTR0 ;

	while ( gCTxFDPtr0 != CTxPtr )  { 
		pTxFDptr = (sFrameDescriptor *) gCTxFDPtr0;

		// Check CPU ownership
		// if Owner is BDMA then break
		pFrameDataPtr = (U32 *)&pTxFDptr->FrameDataPtr;
		if ( (*pFrameDataPtr & fOwnership_BDMA) ) break ;
	
		Status = (pTxFDptr->StatusAndFrameLength >> 16) & 0xffff;
	
		if (Status & Comp)
			gsMacTxStatus.MacTxGood++ ;
		
		// Save Error status
		// Check each status, because, error can duplicated
		if (Status & Under) gsMacTxStatus.UnderErr++ ;
		if (Status & ExColl) gsMacTxStatus.ExCollErr++ ;
		if (Status & TxDeffer) 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.
		if (Status != 0x4080)
		{
			//MacDebugStatus() ; 
			if(!(Status & Comp))	
				ReadyMacTx() ;
		}

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

		gCTxFDPtr0 = (U32)pTxFDptr->NextFrameDescriptor ;
	} // end while loop			
}

/* Interrupt Service Routine for BDMA0 Rx
   Ethenet Frame is received in BDMA0_Rx_isr */
void BDMA0_Rx_isr(void)
{
	sFrameDescriptor *pRxFDptr ;
	U32 RxStatus, FrameLength ;
	U32 CRxPtr;
	U32 sBdmaStat, CheckOwnerShip ;
	U8 *pFrameData ;

	// Step 1. Get current frame descriptor and status
	CRxPtr = BDMARXPTR0 ;
	sBdmaStat = BDMASTAT0 ;
	
	BDMASTAT0 = sBdmaStat;

	// Step 2. Clear BDMA status register bit by write 1
	//BDMASTAT0 |= S_BRxRDF ;
	gsBdmaRxStatus.BdmaRxCnt++ ;
	do {
		// Step 3. Check Null List Interrupt
		//if ( BDMASTAT0 & S_BRxNL ) {
		//	BDMASTAT0 |= S_BRxNL ;
		if ( sBdmaStat & S_BRxNL ) {
			gsBdmaRxStatus.BRxNLErr++ ;
			MacInitialize() ;
			break ;
		}
		
		// Step 4. Get Rx Frame Descriptor
		pRxFDptr = (sFrameDescriptor *)gCRxFDPtr0 ;
		RxStatus = (pRxFDptr->StatusAndFrameLength >> 16) & 0xffff;
		
		//pFrameData = (U8 *)pRxFDptr->FrameDataPtr ;
		/* Check BDMA Receive Ownership     */
		//CheckOwnerShip = *pFrameData & fOwnership_BDMA;
		//if(!CheckOwnerShip)
		//{

		// Step 5. If Rx frame is good, then process received frame
		if((RxStatus & RxGood)&&!(RxStatus & OvMax)) {
			FrameLength = pRxFDptr->StatusAndFrameLength & 0xffff ; 
			pFrameData = (U8 *)pRxFDptr->FrameDataPtr ;
			gsBdmaRxStatus.BdmaRxGood++ ;
			
			//// Step 6. Get received frame to memory buffer
			NetReceive(pFrameData, FrameLength);	
		} 
		else {
				// Step 7. If Rx frame has error, then process error frame
				gErrorPacketCnt++ ;

				// Save Error status
				// Check each status, because, error can duplicated
				if (RxStatus & OvMax) {
					gsMacRxStatus.OvMaxSize++ ;	
				}
				if (RxStatus & CtlRecd) 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++ ;
		}
		//}
		//else
		//{
		//break;
		//}

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

		// Save Current Status and Frame Length field, and clear

		// Step 9. Get Next Frame Descriptor pointer to process
		gCRxFDPtr0 = (U32)(pRxFDptr->NextFrameDescriptor) ;
	} while (CRxPtr != gCRxFDPtr0);

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

		ReadyMacRx() ;
	}
}

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

	// 1. Get Tx frame descriptor & data pointer
	psTxFD = (sFrameDescriptor *)gWTxFDPtr0 ;

	pFrameData = (U8 *)psTxFD->FrameDataPtr ;
	pFrameDataPtr = (U32 *)&psTxFD->FrameDataPtr;
	FrameLength = Size + sizeof(etheader) ;

	// 2. Check BDMA ownership
	if ( (*pFrameDataPtr & fOwnership_BDMA) ) return 0 ;   // 1 : BDMA

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

	// 4. Set TX Frame flag & Length Field
#ifdef LITTLE
	psTxFD->Reserved = (PaddingMode | CRCMode | SourceAddrIncrement | \
			LittleEndian | WidgetAlign00 | MACTxIntEn);
#else
	psTxFD->Reserved = (PaddingMode | CRCMode | SourceAddrIncrement | \
			BigEndian | WidgetAlign00 | MACTxIntEn);
#endif
	psTxFD->StatusAndFrameLength = (U32)(FrameLength & 0xffff);

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

	// 6. Enable MAC and BDMA Tx control register
	MacTxGo(0);

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

	return 1 ;
}


int eth_init( bd_t *bd ) {
  EthInitialize() ;
  return 0;
}

/* send the packet and wait for its complete */
int eth_send(volatile void *packet, int length) {
  uint status;
 
  SendPacket(packet, length);
		
  while(1) {
	status = MACTXSTAT0;
	if (status & Comp) break; 
  }

  /* check status */
  MAC0_Tx_isr() ;

  return 0;
}

int eth_rx(void) {
  int size;

  if(!(BDMASTAT0 & S_BRxRDF)) return 0;
  
  /* handle received packets by calling NetReceive */
  BDMA0_Rx_isr();

  return size;
}


void eth_halt( void ) 
{
}


#endif

#endif

⌨️ 快捷键说明

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