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

📄 dm9000a.c

📁 DM900A driver for au1200(Eboot using)
💻 C
字号:
/*************************************************************************
*
* [FILE NAME]
*	dm9000a.c
*
* [VERSION]
*   Ver 1.0
*                                                                       
* [DESCRIPTION]
*	Driver of DM9000A
*                                                                       
* [COPYRIGHT]
*       Copyright (c) AMD Beijing Technology Development Center. 
*
* PROPRIETARY RIGHTS of AMD Beijing Technology Development Center
* are involved in the subject matter of this material.  All manufacturing, 
* reproduction, use, and sales rights pertaining to this subject matter are 
* governed by the license agreement.  The recipient of this software implicitly
* accepts the terms of the license. 
*
* [HISTORY]
* NAME              DATE        REMARKS               
* 
*
*************************************************************************/

/*====== Include ======*/
#include "eboot.h"
#include "dm9000a.h"

/*====== Define ======*/
// Stop the linker complaining about empty libraries
BOOL dm9000aInit = FALSE;

// This must be defined in the board header file (eg Argon.h) if
// a dm9000a is to be used.
#ifdef DM9000A_PHYS_ADDR

#define DM9000A_CMD_ADDR 		(DM9000A_PHYS_ADDR + KSEG1_OFFSET)
#define DM9000A_DATA_ADDR 	(DM9000A_PHYS_ADDR + KSEG1_OFFSET + 4)
#define SwapByte(x)     			(((x)>>8) | ((x)<<8))

#define OutWord(addr, data)		{*(volatile WORD *)addr = (WORD)data;}
#define OutByte(addr, data)		{*(volatile BYTE *)addr = (BYTE)data;}
#define InWord(addr)				(*(volatile WORD *)addr)
#define InByte(addr)				(*(volatile BYTE *)addr)


/*====== Struct ======*/

/*====== Variable ======*/

static BOOL isByteMode = TRUE;

/*====== Static Function ======*/
static DWORD GetDM9000ID(void);
static DWORD GetPHYID(void);
static void SetPHYMode(void);
static void WriteReg(BYTE addr, BYTE data);
static BYTE ReadReg(BYTE addr);
static WORD PHYRead(BYTE reg);
static void PHYWrite(BYTE reg, WORD value);
static void delay(volatile int us);

/*====== Function Prototype ======*/

/*====== Function ======*/

/* OEMEthInit
 *
 *   Initialize ethernet for downloading image.
 *
 * Parameters:
 *
 *   pAdapter - IN - Adapter object to initialize
 *
 * Return Value:
 *    Return TRUE if init successful, FALSE if not.
 */
BOOL OEMEthInit (EDBG_ADAPTER *pAdapter)
{
	UCHAR *macPtr;
	DWORD dm9000ID = 0x0;
	volatile int i;
	BYTE addr;
	
	if (dm9000aInit)
		return TRUE;

	// Get the MAC address
	GetMacAddress(pAdapter->Addr.wMAC);
	macPtr = (PUCHAR)pAdapter->Addr.wMAC;
	EdbgOutputDebugString("DM9000A: MAC Addr");
	for (i=0; i<6; i++) {
		EdbgOutputDebugString(":%B",macPtr[i]);
	}
	EdbgOutputDebugString("\r\n");
	
	dm9000ID = GetDM9000ID();
	EdbgOutputDebugString("DM9000A: MAC id = 0x%x\r\n", dm9000ID);

	if (DM9000_ID != dm9000ID) {
		EdbgOutputDebugString("DM9000A: Unknown etherNet ID.\r\n");
		return FALSE;
	}

	dm9000ID = GetPHYID();
	EdbgOutputDebugString("DM9000A: PHY id = 0x%x\r\n", dm9000ID);
	
	isByteMode = (ReadReg(DM9000_ISR) & 0x80) ? TRUE : FALSE;		//get current bus width;
	EdbgOutputDebugString("DM9000A: BusWidth = %d\r\n", isByteMode);

	
	WriteReg(DM9000_GPR, 0x0);	//Power up PHY 
	WriteReg(DM9000_NCR, 3);		//reset MAC controller
	
	SetPHYMode();

	WriteReg(DM9000_NCR, 0);		
	WriteReg(DM9000_TCR, 0);		/* TX Polling clear */
	WriteReg(DM9000_BPTR, 0x3f);		/* Less 3kb, 600us */
	WriteReg(DM9000_SMCR, 0);		/* Special Mode */
	WriteReg(DM9000_NSR, 0x2c);		/* clear TX status */
	WriteReg(DM9000_ISR, 0x0f);		/* Clear interrupt status */

	//Wait internal PHY link ready
	i = 150;
	while(--i)
	{
		delay(1000000);
		if (ReadReg(DM9000_NSR) & 0x40)
		{
			break;
		}
	}
	if (i == 0)
		return FALSE;

	//Set mac address
	for(i=0, addr=DM9000_PAR; i<6; i++, addr++)
	{
		WriteReg(addr, macPtr[i]);
	}

	//Set multi-board address
	for(i=0, addr=DM9000_MAR; i<8; i++, addr++)
	{
		WriteReg(addr, 0);
	}

	//Enable receive 
	WriteReg(DM9000_RCR, 0x39);
	WriteReg(DM9000_IMR, DM9000_ENABLE_INT);

	dm9000aInit = TRUE;

	return TRUE;
}

/* OEMEthGetFrame
 *
 *   Check to see if a frame has been received, and if so copy to buffer. An optimization
 *   which may be performed in the Ethernet driver is to filter out all received broadcast
 *   packets except for ARPs.  
 *
 * Parameters:
 *
 *   pData    - OUT - Receives frame data
 *   pwLength - IN  - Length of Rx buffer
 *            - OUT - Number of bytes received
 *
 * Return Value:
 *    Return TRUE if frame has been received, FALSE if not.
 */
BOOL OEMEthGetFrame(BYTE *pData, UINT16 *pwLength) 
                      
{
	BYTE isrValue, rxByte, rxStatus, *bPtr = pData;
	WORD i, totalLen = 0, rxLen, *wPtr = (WORD *)pData;

	BYTE status = FALSE;

	
	if (!dm9000aInit)
		return FALSE;

	isrValue = ReadReg(DM9000_ISR);
	if ((isrValue & 0x01) == 0) 
	{
		return FALSE;		//No data in RX buffer
	}
	
	WriteReg(DM9000_IMR, DM9000_DISABLE_INT);	//Disable all interrupt

	WriteReg(DM9000_ISR, isrValue & 0x01);		//clear RX interrupt flag
	
	do {
		rxByte = ReadReg(DM9000_MRCMDX);
		rxByte = ReadReg(DM9000_MRCMDX);

		if (rxByte != 0x01)
		{
			if (rxByte > 0x01)		
				EdbgOutputDebugString("DM9000A: RX Error...(%x)\r\n", rxByte);
			status = TRUE;
			break;
		}

		OutByte(DM9000A_CMD_ADDR, DM9000_MRCMD);

		//Get package header from RX buffer
		if (isByteMode)
		{
			rxByte = InByte(DM9000A_DATA_ADDR);
			rxStatus = InByte(DM9000A_DATA_ADDR);
			rxLen = InByte(DM9000A_DATA_ADDR);
			rxLen += InByte(DM9000A_DATA_ADDR) << 8;
		} else {
			rxStatus = (BYTE)((InWord(DM9000A_DATA_ADDR) >> 8) & 0xff);
			rxLen = InWord(DM9000A_DATA_ADDR);
		}
		
		if (rxStatus & 0xbf)
		{
			//skip all data in bad package
			EdbgOutputDebugString("DM9000A: Bad Package(%x).\r\n", rxStatus);
			if (isByteMode)
			{
				for (i=0; i<rxLen; i++)
				{
					InByte(DM9000A_DATA_ADDR);
				}

			} else {
				for (i=0; i<((rxLen+1)/2); i++)
				{
					InWord(DM9000A_DATA_ADDR);
				}
			}
			continue;
		}

		if ((totalLen + rxLen)> *pwLength)
		{
			EdbgOutputDebugString("DM9000A: RX Package is too large.\r\n");
			status = FALSE;
			break;
		}

		//Get data from RX buffer
		totalLen += rxLen;
		if (isByteMode)
		{
			for (i=0; i<rxLen; i++)
			{
				*bPtr++ = InByte(DM9000A_DATA_ADDR);
			}

		} else {
			for (i=0; i<((rxLen+1)/2); i++)
			{
				*wPtr++ = InWord(DM9000A_DATA_ADDR);
			}
		}
	} while(1);
	
	*pwLength = totalLen;
	WriteReg(DM9000_IMR, DM9000_ENABLE_INT);		//Enable all interrupt

//	EdbgOutputDebugString("DM9000A: Received packet of %d bytes\r\n", rxLen);
//	DumpFrame(pData, rxLen);
	
	return status;
}

/* OEMEthSendFrame
 *
 *   Send Ethernet frame.  
 *
 * Parameters:
 *
 *   pData    - IN - Data buffer
 *   dwLength - IN - Length of buffer
 *
 *  Return Value:
 *   TRUE if frame successfully sent, FALSE otherwise.
 */
BOOL OEMEthSendFrame(BYTE *pData, DWORD dwLength)
{
	WORD *wPtr = (WORD *)pData;
	BYTE *bPtr = pData;
	DWORD dwLen, i;

	if (!dm9000aInit)
		return FALSE;
	
//	EdbgOutputDebugString("DM9000A: Send packet of %d bytes\r\n", dwLength);
//	DumpFrame(pData, dwLength);
	
	WriteReg(DM9000_IMR, DM9000_DISABLE_INT);	//Disable all interrupt
	
	WriteReg(DM9000_TXPLL, (BYTE)(dwLength & 0xff));		//Set data length
	WriteReg(DM9000_TXPLH, (BYTE)((dwLength >> 8) & 0xff));

	OutByte(DM9000A_CMD_ADDR, DM9000_MWCMD);

	if (isByteMode)
	{
		for (i=0; i<dwLength; i++)
		{
			OutByte(DM9000A_DATA_ADDR, *bPtr++);
		}
	} else {
		dwLen = (dwLength + 1) / 2;
		for (i=0; i<dwLen; i++)
		{
			OutWord(DM9000A_DATA_ADDR, *wPtr++);
		}
	}

	WriteReg(DM9000_TCR, 0x01);	//Send data in SRAM

	WriteReg(DM9000_IMR, DM9000_ENABLE_INT);	//Enable all interrupt

	while(ReadReg(DM9000_TCR) & 0x01);		//wait send completed

	return TRUE;

}

//Write 1 byte to DM9000
static void WriteReg(BYTE addr, BYTE data)		
{	
	OutByte(DM9000A_CMD_ADDR, addr);
	OutByte(DM9000A_DATA_ADDR, data);

	return;
}

//Read 1 byte from DM9000
static BYTE ReadReg(BYTE addr)
{	
	OutByte(DM9000A_CMD_ADDR, addr);

	return InByte(DM9000A_DATA_ADDR);
}

//PHY read
static WORD PHYRead(BYTE reg)
{
	/* Fill the phyxcer register into REG_0C */
	WriteReg(DM9000_EPAR, DM9000_PHY|reg);

	WriteReg(DM9000_EPCR, 0xc); 	/* Issue phyxcer read command */

	while(ReadReg(DM9000_EPCR) & 0x01);	/* Wait read complete */
	
	WriteReg(DM9000_EPCR, 0x0); 	/* Clear phyxcer read command */

	/* The read data keeps on REG_0D & REG_0E */
	return (ReadReg(DM9000_EPDRH) << 8 ) | ReadReg(DM9000_EPDRL);
}

//PHY Write
static void PHYWrite(BYTE reg, WORD value)
{
	/* Fill the phyxcer register into REG_0C */
	WriteReg(DM9000_EPAR, DM9000_PHY|reg);

	/* Fill the written data into REG_0D & REG_0E */
	WriteReg(DM9000_EPDRL, (value&0xff));
	WriteReg(DM9000_EPDRH, ((value>>8)&0xff));

	WriteReg(DM9000_EPCR, 0xa);	/* Issue phyxcer write command */
	
	while(ReadReg(DM9000_EPCR) & 0x01);	/* Wait write complete */
	
	WriteReg(DM9000_EPCR, 0x0);	/* Clear phyxcer write command */
}

static void delay(volatile int us)
{
	while (us)
		us--;
}

static DWORD GetDM9000ID(void)
{
	DWORD dm9000ID = 0x0;
	
	dm9000ID = ReadReg(DM9000_VID);
	dm9000ID |= ReadReg(DM9000_VID + 1) << 8;
	dm9000ID |= ReadReg(DM9000_PID) << 16;
	dm9000ID |= ReadReg(DM9000_PID + 1) << 24;
	
	return dm9000ID;
}

static DWORD GetPHYID(void)
{
	DWORD phyID = 0x0;

	phyID = PHYRead(2) & 0xffff;
	phyID |= PHYRead(3) << 16;

	return phyID;
}

static void SetPHYMode(void)
{
	//Set PHY controller to Auto-negotiation mode as default.

	PHYWrite(4, 0x01e1);
	PHYWrite(0, 0x1200);

	return;
}


#endif

⌨️ 快捷键说明

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