📄 dm9000a.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 + -