📄 dm9000.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
//------------------------------------------------------------------------------
//
// File: DM9000.c
//
#include <windows.h>
#include <ceddk.h>
#include <ethdbg.h>
#include <DM9000.h>
extern void Wait(unsigned);
//------------------------------------------------------------------------------
#define DM9000A_EISA_NUMBER 0x630e
#define RETRY_COUNT 0x00100000
//------------------------------------------------------------------------------
volatile DM9000_REGS *g_pDM9000;
volatile BYTE *g_pDM9000Frank;
static UINT16 g_hash[4];
static UINT32 g_filter;
DWORD dwConfigOptions;
//------------------------------------------------------------------------------
static UINT16 ReadPacketPage(UINT16 address);
static VOID WritePacketPage(UINT16 address, UINT16 data);
static UINT32 ComputeCRC(UINT8 *pBuffer, UINT32 length);
/*add by frank*/
#define DM9000_VID 0x0A46
#define DM9000_PID 0x9000
#define DM9000_ADDR_OFFSET 0x00
//#define DM9000_DATA_OFFSET 0x04
#define DM9000_DATA_OFFSET 0x4000
typedef enum {
DM9_NCR = 0,
DM9_NSR, /* 0x01 */
DM9_TXCR, /* 0x02 */
DM9_TXSR1, /* 0x03 */
DM9_TXSR2, /* 0x04 */
DM9_RXCR, /* 0x05 */
DM9_RXSR, /* 0x06 */
DM9_ROCR, /* 0x07 */
DM9_BACKTH, /* 0x08 */
DM9_PAUSETH,/* 0x09 */
DM9_FLOW, /* 0x0s */
DM9_EPCNTL, /* 0x0B */
DM9_EPADDR, /* 0x0c */
DM9_EPLOW, /* 0x0d */
DM9_EPHIGH, /* 0x0e */
DM9_WCR, /* 0x0f */
DM9_PAR0 = 0x10,
DM9_PAR1, /* 0x11 */
DM9_PAR2, /* 0x12 */
DM9_PAR3, /* 0x13 */
DM9_PAR4, /* 0x14 */
DM9_PAR5, /* 0x15 */
DM9_MAR0 = 0x16,
DM9_MAR1, /* 0x17 */
DM9_MAR2, /* 0x18 */
DM9_MAR3, /* 0x19 */
DM9_MAR4, /* 0x1a */
DM9_MAR5, /* 0x1b */
DM9_MAR6, /* 0x1c */
DM9_MAR7, /* 0x1d */
DM9_GPCR = 0x1E,
DM9_GPR, /* 0x1f */
DM9_TRAL = 0x22,
DM9_TRAH = 0x23,
DM9_VIDL = 0x28,
DM9_VIDH, /* 0x29 */
DM9_PIDL, /* 0x2a */
DM9_PIDH, /* 0x2b */
DM9_SMCR = 0x2f,
DM9_MRCMDX = 0xF0,
DM9_MRCMD = 0xF2,
DM9_MDRAH = 0xF4,
DM9_MDRAL, /* 0xf5 */
DM9_MWCMDX = 0xF6,
DM9_MWCMD = 0xF8,
DM9_MDWAL = 0xFA,
DM9_MDWAH = 0xFB,
DM9_TXLENL = 0xFC,
DM9_TXLENH, /* 0xfd */
DM9_ISR = 0xFE,
DM9_IMR /* 0xff */
} DM9000_REGISTER_TYPE;
typedef unsigned long U32;
typedef unsigned long *PU32;
typedef unsigned short U16;
typedef unsigned short *PU16;
typedef unsigned char U8;
typedef unsigned char *PU8;
#define DIM(a) (sizeof(a) / sizeof(a[0]))
#define MINI(a,b) (((a)<(b)) ? (a):(b))
#define MAXI(a,b) (((a)>(b)) ? (a):(b))
#define MAKE_MASK(a) MAKE_MASK1(a)
#define MAKE_MASK1(a) (1<<(a))
#define MAKE_MASK2(a,b) (MAKE_MASK1(a)|MAKE_MASK1(b))
#define MAKE_MASK3(a,b,c) (MAKE_MASK2(a,b)|MAKE_MASK1(c))
#define MAKE_MASK4(a,b,c,d) (MAKE_MASK2(a,b)|MAKE_MASK2(c,d))
#define MAKE_MASK6(a,b,c,d,e,f) \
(MAKE_MASK4(a,b,c,d)|MAKE_MASK2(e,f))
#define MAKE_MASK7(a,b,c,d,e,f,g) \
(MAKE_MASK4(a,b,c,d)|MAKE_MASK3(e,f,g))
#define MAKE_MASK8(a,b,c,d,e,f,g,h) \
(MAKE_MASK4(a,b,c,d)|MAKE_MASK4(e,f,g,h))
#define HIGH_BYTE(n) (((n)&0xFF00)>>8)
#define LOW_BYTE(n) ((n)&0x00FF)
#define HIGH_WORD(n) (((n)&0xFFFF0000)>>16)
#define LOW_WORD(n) ((n)&0x0000FFFF)
#define MAKE_WORD(l,h) ( ((h)<<8) | ((l)&0xff) )
#define MAKE_DWORD(ll,lh,hl,hh) \
( (MAKE_WORD(hl,hh) << 16 ) | MAKE_WORD(ll,lh) )
U32 m_uLastAddressPort = 0;
int m_nIoMode;
int m_nIoMaxPad;
/**/
#define VALIDATE_ADDR_PORT(p) \
if( m_uLastAddressPort != (p) ) \
{ \
/*OALMSG("Writ 0x%X to port 0x%X \r\n", p, (g_pDM9000Frank + DM9000_ADDR_OFFSET) );*/ \
*(U16*)(g_pDM9000Frank + DM9000_ADDR_OFFSET) =(U16)(p);\
m_uLastAddressPort = (p);\
}
static U32 DeviceReadPort( U32 uPort);
static U32 DeviceWritePort(U32 uPort, U32 uValue);
static U32 DeviceReadPort( U32 uPort)
{
U16 val;
VALIDATE_ADDR_PORT(uPort)
val = *(U16*)(g_pDM9000Frank + DM9000_DATA_OFFSET);
val &= 0xffff;
//OALMSG("Read port 0x%X is 0x%X\r\n", (g_pDM9000Frank + DM9000_DATA_OFFSET),val);
return (U32)val;
}
static U32 DeviceWritePort(
U32 uPort,
U32 uValue)
{
VALIDATE_ADDR_PORT(uPort)
//OALMSG("Writ 0x%X to port 0x%X \r\n", uValue, (g_pDM9000Frank + DM9000_DATA_OFFSET) );
*(U16*)(g_pDM9000Frank + DM9000_DATA_OFFSET) = (U16)uValue;
return uValue;
}
DWORD DM9000AGetPendingInterrupts(void)
{
OALMSG("+DM9000AGetPendingInterrupts\r\n");
OALMSG("-DM9000AGetPendingInterrupts\r\n");
return 0;
}
BOOL DM9000AReadEEPROM( UINT16 EEPROMAddress , UINT16 *pwVal)
{
OALMSG("+DM9000AReadEEPROM\r\n");
OALMSG("-DM9000AReadEEPROM\r\n");
return FALSE;
}
BOOL DM9000AWriteEEPROM( UINT16 EEPROMAddress, UINT16 Data )
{
OALMSG("+DM9000AWriteEEPROM\r\n");
OALMSG("-DM9000AWriteEEPROM\r\n");
return FALSE;
}
DWORD DM9000ASetOptions(DWORD dwOptions)
{
DWORD dwOldOptions = dwConfigOptions;
dwConfigOptions = dwOptions;
OALMSG("+DM9000ASetOptions\r\n");
OALMSG("-DM9000ASetOptions\r\n");
return dwOldOptions;
}
void DebugDelay(int i)
{
while(i--);
}
void DebugSegment7(unsigned long value)
{
#define CACHED_TO_UNCACHED_OFFSET 0x20000000
#define SEGMENT7_BASE_PHYSICAL 0x12000000
#define SEGMENT7_BASE_C_VIRTUAL 0x9E800000
#define SEGMENT7_BASE_U_VIRTUAL (SEGMENT7_BASE_C_VIRTUAL + CACHED_TO_UNCACHED_OFFSET)
volatile unsigned long *v_pSegment7=(volatile unsigned long *)SEGMENT7_BASE_U_VIRTUAL;
unsigned char seg7table[16] = {
#if 0
//0 1 2 3 4 5 6 7
0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8,
//8 9 a b c d e f
0x80, 0x90, 0x88, 0x83, 0xc5, 0xa1, 0x86, 0x8e
#else
//0 1 2 3 4 5 6 7
0x24, 0xF5, 0x07, 0x45, 0xD4, 0x4C, 0x0C, 0xE4,
//8 9 a b c d e f
0x04, 0x44, 0x84, 0x1C, 0x2E, 0x15, 0x0E, 0x8e
#endif
};
unsigned char low = (unsigned char)(value &0xf);
unsigned char high = (unsigned char)((value & 0xf0)>>4);
unsigned new_value = (seg7table[high]<<8) + seg7table[low];
if(value == 0xffFFffFF)
new_value = 0xffff;
*v_pSegment7 = new_value;
}
void DebugLed(void)
{
typedef unsigned long XLLP_UINT32_T, *P_XLLP_UINT32_T;
typedef volatile XLLP_UINT32_T XLLP_VUINT32_T, *P_XLLP_VUINT32_T;
/**
GPIO Register Definitions
**/
typedef struct
{
XLLP_VUINT32_T GPLR0; /* Level Detect Reg. Bank 0 */
XLLP_VUINT32_T GPLR1; /* Level Detect Reg. Bank 1 */
XLLP_VUINT32_T GPLR2; /* Level Detect Reg. Bank 2 */
XLLP_VUINT32_T GPDR0; /* Data Direction Reg. Bank 0 */
XLLP_VUINT32_T GPDR1; /* Data Direction Reg. Bank 1 */
XLLP_VUINT32_T GPDR2; /* Data Direction Reg. Bank 2 */
XLLP_VUINT32_T GPSR0; /* Pin Output Set Reg. Bank 0 */
XLLP_VUINT32_T GPSR1; /* Pin Output Set Reg. Bank 1 */
XLLP_VUINT32_T GPSR2; /* Pin Output Set Reg. Bank 2 */
XLLP_VUINT32_T GPCR0; /* Pin Output Clr Reg. Bank 0 */
XLLP_VUINT32_T GPCR1; /* Pin Output Clr Reg. Bank 1 */
XLLP_VUINT32_T GPCR2; /* Pin Output Clr Reg. Bank 2 */
XLLP_VUINT32_T GRER0; /* Ris. Edge Detect Enable Reg. Bank 0 */
XLLP_VUINT32_T GRER1; /* Ris. Edge Detect Enable Reg. Bank 1 */
XLLP_VUINT32_T GRER2; /* Ris. Edge Detect Enable Reg. Bank 2 */
XLLP_VUINT32_T GFER0; /* Fal. Edge Detect Enable Reg. Bank 0 */
XLLP_VUINT32_T GFER1; /* Fal. Edge Detect Enable Reg. Bank 1 */
XLLP_VUINT32_T GFER2; /* Fal. Edge Detect Enable Reg. Bank 2 */
XLLP_VUINT32_T GEDR0; /* Edge Detect Status Reg. Bank 0 */
XLLP_VUINT32_T GEDR1; /* Edge Detect Status Reg. Bank 1 */
XLLP_VUINT32_T GEDR2; /* Edge Detect Status Reg. Bank 2 */
XLLP_VUINT32_T GAFR0_L; /* Alt. Function Select Reg.[ 0:15 ] */
XLLP_VUINT32_T GAFR0_U; /* Alt. Function Select Reg.[ 16:31 ] */
XLLP_VUINT32_T GAFR1_L; /* Alt. Function Select Reg.[ 32:47 ] */
XLLP_VUINT32_T GAFR1_U; /* Alt. Function Select Reg.[ 48:63 ] */
XLLP_VUINT32_T GAFR2_L; /* Alt. Function Select Reg.[ 64:79 ] */
XLLP_VUINT32_T GAFR2_U; /* Alt. Function Select Reg.[ 80:95 ] */
XLLP_VUINT32_T GAFR3_L; /* Alt. Function Select Reg.[ 96:111] */
XLLP_VUINT32_T GAFR3_U; /* Alt. Function Select Reg.[112:120] */
XLLP_VUINT32_T RESERVED1[35]; /* addr. offset 0x074-0x0fc */
XLLP_VUINT32_T GPLR3; /* Level Detect Reg. Bank 3 */
XLLP_VUINT32_T RESERVED2[2]; /* addr. offset 0x104-0x108 */
XLLP_VUINT32_T GPDR3; /* Data Direction Reg. Bank 3 */
XLLP_VUINT32_T RESERVED3[2]; /* addr. offset 0x110-0x114 */
XLLP_VUINT32_T GPSR3; /* Pin Output Set Reg. Bank 3 */
XLLP_VUINT32_T RESERVED4[2]; /* addr. offset 0x11c-0x120 */
XLLP_VUINT32_T GPCR3; /* Pin Output Clr Reg. Bank 3 */
XLLP_VUINT32_T RESERVED5[2]; /* addr. offset 0x128-0x12c */
XLLP_VUINT32_T GRER3; /* Ris. Edge Detect Enable Reg. Bank 3 */
XLLP_VUINT32_T RESERVED6[2]; /* addr. offset 0x134-0x138 */
XLLP_VUINT32_T GFER3; /* Fal. Edge Detect Enable Reg. Bank 3 */
XLLP_VUINT32_T RESERVED7[2]; /* addr. offset 0x140-0x144 */
XLLP_VUINT32_T GEDR3; /* Edge Detect Status Reg. Bank 3 */
} XLLP_GPIO_T, *P_XLLP_GPIO_T;
#define PERIF_BASE_C_VIRTUAL 0x84000000
#define CACHED_TO_UNCACHED_OFFSET 0x20000000
#define PERIF_BASE_U_VIRTUAL (PERIF_BASE_C_VIRTUAL+CACHED_TO_UNCACHED_OFFSET)
#define GPIO_OFFSET 0x00E00000 // GPIO
#define GPIO_BASE_U_VIRTUAL (PERIF_BASE_U_VIRTUAL + GPIO_OFFSET)
volatile XLLP_GPIO_T *v_pGPIOReg;
v_pGPIOReg = (volatile XLLP_GPIO_T *)GPIO_BASE_U_VIRTUAL;
while(1)
{
int i=1;
v_pGPIOReg->GPSR1 = 0x80;
while(i<0xffffff)i++;
v_pGPIOReg->GPCR1 = 0x80;
i=1;
while(i<0xffffff)i++;
}
}
BOOL DevicePolling(
U32 uPort,
U32 uMask,
U32 uExpected,
U32 uInterval, /* in millisecond */
U32 uRetries)
{
for(;uRetries;uRetries--)
{
if((DeviceReadPort(uPort) & uMask) == uExpected) break;
Wait(uInterval);
} // of retry loop
return (BOOL)uRetries;
}
U16 DeviceReadEeprom( U32 uWordAddress)
{
U16 highbyte,lowbyte;
// assign the register offset
DeviceWritePort(DM9_EPADDR,uWordAddress);
// issue EEPROM read command<2>
DeviceWritePort(DM9_EPCNTL,(1<<2));
// wait until status bit<0> cleared
// 80 uS, 5 times
if(!DevicePolling(DM9_EPCNTL,(1<<0),0x00,80,5))
return (U16)-1;
// stop command
DeviceWritePort(DM9_EPCNTL,0);
// retrive data
lowbyte = (U16)DeviceReadPort(DM9_EPLOW);
highbyte = (U16)DeviceReadPort(DM9_EPHIGH);
return ((highbyte<<8) | lowbyte);
}
typedef enum {
BYTE_MODE=1,
WORD_MODE=2,
DWORD_MODE=4,
} DEVICE_IO_MODE;
typedef enum {
NIC_HW_OK,
NIC_HW_TX_IDLE,
NIC_HW_TX_BUSY,
} NIC_HW_STATUS_TYPE;
#define REPORT(evt,val)
#define CHECK_SHUTDOWN()
/********************************************************************************
*
* EEPROM 93C46 Parameters
*
********************************************************************************/
#define BITS_PER_BYTE 8
#define EEPROM_93C46_BITS 1024
#define EEPROM_93C46_SIZE (EEPROM_93C46_BITS/BITS_PER_BYTE)
#define EEPROM_93C46_MAX_CYCLES 25
#define EEPROM_93C46_ADDRESS_BITS 6
#define EEPROM_93C46_DATA_BITS 16
#define EEPROM_93C46_DELAY 20
typedef unsigned short EEPROM_93C46_DATA_TYPE;
/********************************************************************************
*
* EEPROM Parameters
*
********************************************************************************/
#define EEPROM_SIZE EEPROM_93C46_SIZE
#define EEPROM_MAX_CYCLES EEPROM_93C46_MAX_CYCLES
#define EEPROM_DELAY EEPROM_93C46_DELAY
#define EEPROM_ADDRESS_BITS EEPROM_93C46_ADDRESS_BITS
#define EEPROM_DATA_BITS EEPROM_93C46_DATA_BITS
#define EEPROM_DATA_TYPE EEPROM_93C46_DATA_TYPE
/********************************************************************************
*
* PHY Parameters
*
********************************************************************************/
#define MII_INTERNAL_PHY_ADDR 1
#define MII_PHY_ADDR_LEN 5
#define MII_REG_ADDR_LEN 5
#define MII_DELAY 20
#define MII_PREAMBLES 32
#define MII_OFFSET_BMCR 0x00
#define MII_OFFSET_BMSR 0x01
#define MII_OFFSET_OUI_M 0x02
#define MII_OFFSET_OUI_L 0x03
#define MII_OFFSET_ANAR 0x04
#define MII_OFFSET_ALPAR 0x05
/********************************************************************************
*
* Configuration definitions
*
********************************************************************************/
#define CONNECTION_NONE 0x00000000
#define CONNECTION_AUTO 0x00000001
#define CONNECTION_10_HALF 0x00000002
#define CONNECTION_10_FULL 0x00000003
#define CONNECTION_100_HALF 0x00000004
#define CONNECTION_100_FULL 0x00000005
#define CONNECTION_1M8_HPNA 0x00000100
#define CONNECTION_10M8_HPNA 0x00000200
/********************************************************************************
*
* CRC32 Routine
*
* This routine calculates the CRC based on the following polynominal
* x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1
*
* About the CRC value of one EEPROM
*
* eeprom<126-127> = CRC value = (U16)crc32(eeprom<0..125>);
*
*
*
*******************************************************************************/
U32 DeviceCalculateCRC32(
PU8 ptrBuffer,
int nLength,
BOOL bReverse)
{
U32 Crc, Carry;
int i, j;
U8 CurByte;
Crc = 0xffffffff;
for (i = 0; i < nLength; i++) {
CurByte = ptrBuffer[i];
for (j = 0; j < 8; j++) {
Carry = ((Crc & 0x80000000) ? 1 : 0) ^ (CurByte & 0x01);
Crc <<= 1;
CurByte >>= 1;
if (Carry) {
Crc = (Crc ^ 0x04c11db6) | Carry;
}
}
}
for (i=0, Carry=0x0L; i < 32 ; i++) {
Carry <<= 1;
if (Crc & 0x1) {
Carry |= 0x1L;
}
Crc >>= 1;
}
return bReverse?~Carry:Carry;
}
U16 DeviceWriteEeprom( U32 uWordAddress, U16 uValue);
void EDeviceLoadEeprom(void)
{
int n;
static U8 m_szEeprom[EEPROM_SIZE];
EEPROM_DATA_TYPE *pcurr=(EEPROM_DATA_TYPE*)&m_szEeprom[0];
for(n=0;n<(DIM(m_szEeprom)/sizeof(EEPROM_DATA_TYPE));n++,pcurr++)
{
*pcurr = DeviceReadEeprom(n);
} // of for offset n
DeviceCalculateCRC32(&m_szEeprom[0],DIM(m_szEeprom)-2,TRUE);
pcurr=(EEPROM_DATA_TYPE*)&m_szEeprom[0];
for(n=0;n<(DIM(m_szEeprom)/sizeof(EEPROM_DATA_TYPE));n++,pcurr++)
{
OALMSG("%X ",*pcurr);
if(((n+1)%8)==0)OALMSG("\n");
} // of for offset n
#if 0
for(n=0;n<(DIM(m_szEeprom)/sizeof(EEPROM_DATA_TYPE));n++)
{
OALMSG("%X ",DeviceWriteEeprom(n,n+5));
if(((n+1)%8)==0)OALMSG("\n");
} // of for offset n
pcurr=(EEPROM_DATA_TYPE*)&m_szEeprom[0];
for(n=0;n<(DIM(m_szEeprom)/sizeof(EEPROM_DATA_TYPE));n++,pcurr++)
{
*pcurr = DeviceReadEeprom(n);
} // of for offset n
DeviceCalculateCRC32(&m_szEeprom[0],DIM(m_szEeprom)-2,TRUE);
pcurr=(EEPROM_DATA_TYPE*)&m_szEeprom[0];
for(n=0;n<(DIM(m_szEeprom)/sizeof(EEPROM_DATA_TYPE));n++,pcurr++)
{
OALMSG("%X ",*pcurr);
if(((n+1)%8)==0)OALMSG("\n");
} // of for offset n
#endif
}
U16 DeviceWriteEeprom(
U32 uWordAddress,
U16 uValue)
{
// assign the register offset
DeviceWritePort(DM9_EPADDR,uWordAddress);
// put data
DeviceWritePort(DM9_EPLOW, LOW_BYTE(uValue));
DeviceWritePort(DM9_EPHIGH,HIGH_BYTE(uValue));
// issue EEPROM write enable<4> and write command<1>
DeviceWritePort(DM9_EPCNTL,MAKE_MASK2(4,1));
// wait until status bit<0> cleared
DevicePolling(DM9_EPCNTL,MAKE_MASK(0),0x00,20,-1);
// stop command
DeviceWritePort(DM9_EPCNTL,0);
return uValue;
}
void EDeviceInitialize(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -