📄 dm9000.c
字号:
int nResetCounts)
{
U32 val;
// reset member varialbes
m_uLastAddressPort = (U32)-1;
DeviceWritePort(0x1f, 0x00);
Wait(20);
// software reset the device
DeviceWritePort(DM9_NCR, 0x03);
Wait(20);
DeviceWritePort(DM9_NCR, 0x03);
Wait(20);
// read the io orgnization
// ISR<7:6> == x1, dword
// ISR<7:6> == 0x, word
// ISR<7:6> == 10, byte mode
val = DeviceReadPort(DM9_ISR);
if(val & MAKE_MASK(6))
{
m_nIoMode = DWORD_MODE;
m_nIoMaxPad = 3;
}
else if(!(val & MAKE_MASK(7)))
{
m_nIoMode = WORD_MODE;
m_nIoMaxPad = 1;
}
else
{
m_nIoMode = BYTE_MODE;
m_nIoMaxPad = 0;
}
// activate internal phy
// select GPIO 0<0>, set it to output
DeviceWritePort(DM9_GPCR, (1<<0));
Wait(20);
// output zero to activate internal phy
DeviceWritePort(DM9_GPR, 0x00);
Wait(20);
// Enable memory chain
DeviceWritePort(DM9_IMR, (1<<7));
Wait(20);
DeviceWritePort( DM9_TXCR, 0); /* TX Polling clear */
Wait(20);
DeviceWritePort( DM9_BACKTH, 0x3f); /* Less 3kb, 600us */
Wait(20);
DeviceWritePort( DM9_SMCR, 0); /* Special Mode */
Wait(20);
DeviceWritePort( DM9_NSR, 0x2c); /* clear TX status */
Wait(20);
DeviceWritePort( DM9_ISR, 0x0f); /* Clear interrupt status */
Wait(20);
OALMSG("val =%X, m_nIoMode:%X m_nIoMaxPad:%X\r\n",val,m_nIoMode,m_nIoMaxPad);
DeviceWritePort(DM9_PAR0+0,(U32)0xc000);
DeviceWritePort(DM9_PAR0+1,(U32)0x2826);
DeviceWritePort(DM9_PAR0+2,(U32)0x3096);
/* Activate DM9000A/DM9010 */
DeviceWritePort(DM9_RXCR, 0x30 | 1 | MAKE_MASK(1) ); /* RX enable */
// DeviceWritePort(DM9_RXCR, 1 | MAKE_MASK(1) ); /* RX enable */
DeviceWritePort(DM9_IMR, 0x80); // Enable TX/RX interrupt mask
}
//------------------------------------------------------------------------------
//
// Function: DM9000AInit
//
BOOL DM9000AInit(BYTE *pAddress, DWORD dwMultiplier, USHORT mac[3])
{
U32 val;
OALMSG("+DM9000AInit(0x%X, %B:%B:%B:%B:%B:%B)\r\n",pAddress, mac[0]&0xFF, mac[0]>>8, mac[1]&0xFF, mac[1]>>8,mac[2]&0xFF, mac[2]>>8);
// Save address
g_pDM9000 = (volatile DM9000_REGS*)pAddress;
g_pDM9000Frank = pAddress;
// DebugSegment7(0x08);
val = DeviceReadPort(0x2a);
val |= DeviceReadPort(0x2b) << 8;
val |= DeviceReadPort(0x28) << 16;
val |= DeviceReadPort(0x29) << 24;
OALMSG("[dm9: Chip signature is 0x%X\r\n", val);
if( ( DeviceReadPort(DM9_VIDL) != LOW_BYTE(DM9000_VID) ) ||
( DeviceReadPort(DM9_VIDH) != HIGH_BYTE(DM9000_VID) ) ||
( DeviceReadPort(DM9_PIDL) != LOW_BYTE(DM9000_PID) ) ||
( DeviceReadPort(DM9_PIDH) != HIGH_BYTE(DM9000_PID) ) )
{
OALMSG("Unknown device\n");
// DebugSegment7(0x09);
}
// DebugSegment7(0x0a);
// EDeviceLoadEeprom();
EDeviceInitialize(0);
return TRUE;
}
PU8 DeviceWriteString(PU8 ptrBuffer, int nLength)
{
#if 1
int count;
PU16 pcurr=(PU16)ptrBuffer;
// count = (nLength + m_nIoMaxPad) / m_nIoMode;
switch (m_nIoMode)
{
case BYTE_MODE:
break;
case WORD_MODE:
{
#if 0
int i;
OALMSG("Len is %X \n",nLength);
for(i=0;i<nLength;i++,pcurr++)
{
OALMSG("%X ", *pcurr);
}
OALMSG("\n");
#endif
count = (nLength+1)/2;
pcurr=(PU16)ptrBuffer;
*(U16*)(g_pDM9000Frank + DM9000_ADDR_OFFSET) =(U16)(DM9_MWCMD);
for(;count--;pcurr++)
{
*(U16*)(g_pDM9000Frank + DM9000_DATA_OFFSET) = *pcurr;
}
}
break;
case DWORD_MODE:
break;
default:
break;
} // of switch
#endif
return ptrBuffer;
}
//------------------------------------------------------------------------------
//
// Function: DM9000ASendFrame
//
UINT16 DM9000ASendFrame(BYTE *pData, DWORD length)
{
/* fill data */
DeviceWriteString(pData,length);
DeviceWritePort(DM9_TXLENH,HIGH_BYTE(length));
DeviceWritePort(DM9_TXLENL,LOW_BYTE(length));
// TXCR<0>, issue TX request
DeviceWritePort(DM9_TXCR, MAKE_MASK(0));
return 0;
}
U8 check_rx_ready(U8 rxbyte)
{
if (!(rxbyte & 0x01))
return 0;
return ((rxbyte >> 4) | 0x01);
}
#pragma pack(push, 1)
typedef struct _RX_DESC
{
U8 rxbyte;
U8 status;
U16 length;
}RX_DESC;
typedef union{
U8 buf[4];
RX_DESC desc;
} rx_t;
#pragma pack(pop)
#define DM9_SETUP_FRAME 0xBadBeef0
#define DM9_MULTICAST_LIST 64
typedef struct {
U8 bState;
U8 bStatus;
U16 nLength;
} DM9_RX_DESCRIPTOR, *PDM9_RX_DESCRIPTOR;
#define ETH_MAX_FRAME_SIZE 1514
#define ETH_HEADER_SIZE 14
#define ETH_ADDRESS_LENGTH 6
#define ETH_CRC_SIZE 4
#define MAX_MULTICAST_LIST 64
#define DRIVER_BUFFER_SIZE 0x5F0
PU8 DeviceReadString( PU8 ptrBuffer, int nLength)
{
#if 1
int count;
// count = (nLength + m_nIoMaxPad) / m_nIoMode;
VALIDATE_ADDR_PORT(DM9_MRCMD);
switch (m_nIoMode)
{
case BYTE_MODE:
break;
case WORD_MODE:
{
PU16 pcurr=(PU16)ptrBuffer;
count = (nLength+1)/2;
for(;count--;pcurr++)
{
*pcurr = *(U16*)(g_pDM9000Frank + DM9000_DATA_OFFSET);
}
}
break;
case DWORD_MODE:
break;
default:
break;
} // of switch
#endif
return ptrBuffer;
}
U32 DeviceReadData(void)
{
U32 value;
return *(PU32)DeviceReadString((PU8)&value,sizeof(value));
}
U32 DeviceReadDataWithoutIncrement(void)
{
U32 value;
VALIDATE_ADDR_PORT(DM9_MRCMDX);
switch (m_nIoMode)
{
case BYTE_MODE:
break;
case WORD_MODE:
value = *(U16*)(g_pDM9000Frank + DM9000_DATA_OFFSET);
break;
case DWORD_MODE:
break;
default:
break;
} // of switch
return value;
}
//------------------------------------------------------------------------------
//
// Function: DM9000AGetFrame
//
// OALMSG("+DM9000AGetFrame(0x%X, %d)\r\n", pData, *pLength);
//OALMSG("-DM9000AGetFrame(length = %d)\r\n", *pLength);
UINT16 DM9000AGetFrame(UINT8 *pData, UINT16 *pLength)
{
int errors=0;
U32 desc;
PDM9_RX_DESCRIPTOR pdesc;
//OALMSG("+DM9000AGetFrame(0x%X, %d)\r\n", pData, *pLength);
//OALMSG("DM9_RXSR is %x\r\n",DeviceReadPort(DM9_RXSR));
//OALMSG("DM9_ROCR is %x\r\n",DeviceReadPort(DM9_ROCR));
DeviceReadPort(DM9_RXSR);
DeviceReadPort(DM9_ROCR);
for(pdesc=(PDM9_RX_DESCRIPTOR)&desc;;)
{
// probe first byte
desc = DeviceReadDataWithoutIncrement();
//OALMSG("desc is %X\r\n",desc);
// check if packet available, 01h means available, 00h means no data
if(pdesc->bState != 0x01)
{
*pLength = 0;
break;
}
// get the data descriptor again
desc = DeviceReadData();
//OALMSG("desc is %X\r\n",desc);
// read out the data to buffer
// Performance issue: maybe we may discard the data
// just add the rx address.
// if the length is greater than buffer size, ...
if((pdesc->nLength > *pLength))
{
OALMSG("AID_LARGE_INCOME_PACKET\r\n");
break;
}
DeviceReadString((PU8)pData,pdesc->nLength);
// check status, as specified in DM9_RXSR,
// the following bits are error
// <3> PLE
// <2> AE
// <1> CE
// <0> FOE
if(pdesc->bStatus & MAKE_MASK4(3,2,1,0))
{
errors++;
OALMSG("errors = %d\r\n", errors);
continue;
} // of error happens
*pLength =pdesc->nLength;
{
#if 0
int i;
PU8 pcurr =(PU8) pData;
OALMSG("Len is %X \n",*pLength);
for(i=0;i<*pLength;i++,pcurr++)
{
OALMSG("%B ", *pcurr);
if(((i+1)%8)==0)OALMSG("\r\n");
}
OALMSG("\r\n");
#endif
}
break;
} // of forever read loop
//OALMSG("-DM9000AGetFrame(length = %d)\r\n", *pLength);
return *pLength;
}
#if 0
UINT16 DM9000AGetFrame(UINT8 *pData, UINT16 *pLength)
{
U8 rxbyte, val;
U16 i, GoodPacket, tmplen = 0, MDRAH, MDRAL;
U32 tmpdata;
U16 * ptr = (U16*)pData;
PU16 pcurr=(PU16)pData;
U8* rdptr =(U8*)pData;
rx_t * rx_p = (rx_t*)pData;
OALMSG("+DM9000AGetFrame(0x%X, %d)\r\n", pData, *pLength);
do {
/*store the value of Memory Data Read address register*/
MDRAH=DeviceReadPort( DM9_MDRAH);
MDRAL=DeviceReadPort( DM9_MDRAL);
//DeviceReadPort( DM9_MRCMDX); /* Dummy read */
rxbyte =(U16) DeviceReadPort( DM9_MRCMDX);; /* Got most updated data */
/* packet ready to receive check */
if(!(val = check_rx_ready(rxbyte))) break;
/* A packet ready now & Get status/length */
GoodPacket = TRUE;
*(U16*)(g_pDM9000Frank + DM9000_ADDR_OFFSET) =(U16)(DM9_MRCMD);
/* Read packet status & length */
switch (m_nIoMode)
{
case BYTE_MODE:
break;
case WORD_MODE:
*ptr = *(U16*)(g_pDM9000Frank + DM9000_DATA_OFFSET);
*(ptr+1) = *(U16*)(g_pDM9000Frank + DM9000_DATA_OFFSET);
break;
case DWORD_MODE:
break;
default:
break;
}
/* Packet status check */
if (rx_p->desc.status & 0xbf)
{
GoodPacket = FALSE;
if (rx_p->desc.status & 0x01)
{
OALMSG("<RX FIFO error>\n");
}
if (rx_p->desc.status & 0x02)
{
OALMSG("<RX CRC error>\n");
}
if (rx_p->desc.status & 0x80)
{
OALMSG("<RX Length error>\n");
}
if (rx_p->desc.status & 0x08)
OALMSG("<Physical Layer error>\n");
}
if (!GoodPacket)
{
// drop this packet!!!
switch (m_nIoMode)
{
case BYTE_MODE:
break;
case WORD_MODE:
tmplen = (rx_p->desc.length + 1) / 2;
for (i = 0; i < tmplen; i++)
tmpdata= *(U16*)(g_pDM9000Frank + DM9000_DATA_OFFSET);
break;
case DWORD_MODE:
break;
}
continue;/*next the packet*/
}
/* Read received packet from RX SARM */
switch (m_nIoMode)
{
case BYTE_MODE:
break;
case WORD_MODE:
tmplen = (rx_p->desc.length + 1) / 2;
for (i = 0; i < tmplen; i++)
((U16 *)rdptr)[i] =*(U16*)(g_pDM9000Frank + DM9000_DATA_OFFSET);
break;
case DWORD_MODE:
break;
}
*pLength = rx_p->desc.length;
OALMSG("Len is %X \n",*pLength);
pcurr = (U16*)pData;
tmplen = (rx_p->desc.length + 1) / 2;
for(i=0;i<tmplen;i++,pcurr++)
{
OALMSG("%X ", *pcurr);
}
OALMSG("\n");
break;
}while(rxbyte == 0x01);
OALMSG("-DM9000AGetFrame(length = %d)\r\n", *pLength);
return *pLength;
}
#endif
//------------------------------------------------------------------------------
//
// Function: DM9000AEnableInts
//
VOID DM9000AEnableInts(void)
{
OALMSG("+DM9000AEnableInts\r\n");
// bits to turn on interrupt latch
// <7> buffer chain enable
// <3> rx overflow count overflow
// <2> rx overflow
// <1> tx completed indication
// <0> rx completed indication
DeviceWritePort(DM9_IMR,((1<<7)|(1<<3)|(1<<2)|(1<<1)|(1<<0)));
OALMSG("-DM9000AEnableInts\r\n");
}
//------------------------------------------------------------------------------
//
// Function: DM9000ADisableInts
//
VOID DM9000ADisableInts(void)
{
OALMSG("+DM9000ADisableInts\r\n");
DeviceWritePort(DM9_IMR,(1<<7));
OALMSG("-DM9000ADisableInts\r\n");
}
//------------------------------------------------------------------------------
//
// Function: DM9000ACurrentPacketFilter
//
VOID DM9000ACurrentPacketFilter(UINT32 filter)
{
OALMSG("+DM9000ACurrentPacketFilter(0x%X)\r\n", filter);
g_filter = filter;
OALMSG("-DM9000ACurrentPacketFilter\r\n");
}
//------------------------------------------------------------------------------
//
// Function: DM9000AMulticastList
//
BOOL DM9000AMulticastList(UINT8 *pAddresses, UINT32 count)
{
OALMSG("+RTL8139MulticastList(0x%X, %d)\r\n", pAddresses, count);
OALMSG("-DM9000AMulticastList(rc = 1)\r\n");
return TRUE;
}
//------------------------------------------------------------------------------
static UINT16 ReadPacketPage(UINT16 address)
{
g_pDM9000->PAGEIX = address;
return g_pDM9000->PAGE0;
}
//------------------------------------------------------------------------------
static VOID WritePacketPage(UINT16 address, UINT16 data)
{
g_pDM9000->PAGEIX = address;
g_pDM9000->PAGE0 = data;
}
//------------------------------------------------------------------------------
static UINT32 ComputeCRC(UINT8 *pBuffer, UINT32 length)
{
UINT32 crc, carry, i, j;
UINT8 byte;
crc = 0xffffffff;
for (i = 0; i < length; i++)
{
byte = pBuffer[i];
for (j = 0; j < 8; j++)
{
carry = ((crc & 0x80000000) ? 1 : 0) ^ (byte & 0x01);
crc <<= 1;
byte >>= 1;
if (carry) crc = (crc ^ 0x04c11db6) | carry;
}
}
return crc;
}
void DM9000AStoreMACAddress(WORD macAddressP[3])
{
//WritePacketPage(INDIVIDUAL_ADDRESS + 0, macAddressP[0]);
//WritePacketPage(INDIVIDUAL_ADDRESS + 2, macAddressP[1]);
//WritePacketPage(INDIVIDUAL_ADDRESS + 4, macAddressP[2]);
DeviceWriteEeprom(0, macAddressP[0]);
DeviceWriteEeprom(2, macAddressP[1]);
DeviceWriteEeprom(4, macAddressP[2]);
}
//------------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -