📄 dm9000dbg.c
字号:
/******************************************************************************* dm9000dbg.c* This driver is eboot driver for DM9000/DM9000A/DM9010.* Created by Spenser, DAVICOM, www.davicom.com.tw.* V1.00 - 30/05/2005* V1.01 - 29/06/2005* V1.02 - 12/07/2005* - Add revision detection.* - DM9000 = 0 or 1, DM9000A E4=18h, E5 = 19H, DM9010 E4 = 10h, E5 = 11h.* V1.03 - 04/10/2005 - TX/RX move data according to DM9000_iomode * - DM9000DBG_Init function wait link ok* V1.04 - 08/11/2005 - Close interrupt enable in DM9000DBG_Init()* - Only enable RX interrupt in DM9000DBG_EnableInts()* - Clean ISR in DM9000DBG_GetFrame()* V1.05 - 28/11/2005 - Add 32 bit mode*******************************************************************************/ #include <windows.h>#include <halether.h>#define DM9000_ID 0x90000A46// Hash creation constants.//#define CRC_PRIME 0xFFFFFFFF;#define CRC_POLYNOMIAL 0x04C11DB6;#define IOREAD(o) ((UCHAR)*((volatile UCHAR *)(o)))#define IOWRITE(o, d) *((volatile UCHAR *)(o)) = (UCHAR)(d)#define IOREAD16(o) ((USHORT)*((volatile USHORT *)(o)))#define IOWRITE16(o, d) *((volatile USHORT *)(o)) = (USHORT)(d)#define IOREAD32(o) ((ULONG)*((volatile ULONG *)(o)))#define IOWRITE32(o, d) *((volatile ULONG *)(o)) = (ULONG)(d)#define MEMREAD(o) ((USHORT)*((volatile USHORT *)(dwEthernetMemBase + (o))))#define MEMWRITE(o, d) *((volatile USHORT *)(dwEthernetMemBase + (o))) = (USHORT)(d)static DWORD dwEthernetIOBase;static DWORD dwEthernetDataPort;static UCHAR DM9000_iomode;static USHORT hash_table[4];static DWORD dwEthernetMemBase;//V1.02static UCHAR DM9000_rev; #define DM9000_DWORD_MODE 1#define DM9000_BYTE_MODE 2#define DM9000_WORD_MODE 0//#define DM9000_MEM_MODE#ifdef DM9000_MEM_MODE#define READ_REG1 ReadReg#define READ_REG2 MEMREAD#define WRITE_REG1 WriteReg#define WRITE_REG2 MEMWRITE#else#define READ_REG1 ReadReg#define READ_REG2 ReadReg#define WRITE_REG1 WriteReg#define WRITE_REG2 WriteReg#endifstatic BOOL bIsPacket;static UCHARReadReg(USHORT offset){ IOWRITE(dwEthernetIOBase, offset); return IOREAD(dwEthernetDataPort);}static void WriteReg(USHORT offset, UCHAR data){ IOWRITE(dwEthernetIOBase, offset); IOWRITE(dwEthernetDataPort, data);}/* @func BYTE | CalculateHashIndex | Computes the logical addres filter hash index value. This used when there are multiple destination addresses to be filtered. @rdesc Hash index value. @comm @xref */BYTE CalculateHashIndex( BYTE *pMulticastAddr ){ DWORD CRC; BYTE HashIndex; BYTE AddrByte; DWORD HighBit; int Byte; int Bit; // Prime the CRC. CRC = CRC_PRIME; // For each of the six bytes of the multicast address. for ( Byte=0; Byte<6; Byte++ ) { AddrByte = *pMulticastAddr++; // For each bit of the byte. for ( Bit=8; Bit>0; Bit-- ) { HighBit = CRC >> 31; CRC <<= 1; if ( HighBit ^ (AddrByte & 1) ) { CRC ^= CRC_POLYNOMIAL; CRC |= 1; } AddrByte >>= 1; } } // Take the least significant six bits of the CRC and copy them // to the HashIndex in reverse order. for( Bit=0,HashIndex=0; Bit<6; Bit++ ) { HashIndex <<= 1; HashIndex |= (BYTE)(CRC & 1); CRC >>= 1; } return(HashIndex);}void DM9000_Delay(DWORD dwCounter){ // Simply loop... while (dwCounter--);} void dm9000_hash_table(USHORT *mac){ USHORT i, oft; /* Set Node address */ WRITE_REG1(0x10, (UINT8)(mac[0] & 0xFF)); WRITE_REG1(0x11, (UINT8)(mac[0] >> 8)); WRITE_REG1(0x12, (UINT8)(mac[1] & 0xFF)); WRITE_REG1(0x13, (UINT8)(mac[1] >> 8)); WRITE_REG1(0x14, (UINT8)(mac[2] & 0xFF)); WRITE_REG1(0x15, (UINT8)(mac[2] >> 8)); /* Clear Hash Table */ for (i = 0; i < 4; i++) hash_table[i] = 0x0; /* broadcast address */ hash_table[3] = 0x8000; /* Write the hash table to MAC MD table */ for (i = 0, oft = 0x16; i < 4; i++) { WRITE_REG1(oft++, (UINT8)(hash_table[i] & 0xff)); WRITE_REG1(oft++, (UINT8)((hash_table[i] >> 8) & 0xff)); } }/* * This function is used to detect DM9000 chip * input : void * return : TRUE, detect DM9000 * FALSE, Not find DM9000 */static BOOL Probe(void){ BOOL r = FALSE; DWORD id_val; id_val = READ_REG1(0x28); id_val |= READ_REG1(0x29) << 8; id_val |= READ_REG1(0x2a) << 16; id_val |= READ_REG1(0x2b) << 24; if (id_val == DM9000_ID) { RETAILMSG(1, (TEXT("INFO: Probe: DM9000 is detected.\r\n"))); DM9000_rev = READ_REG1(0x2c); r = TRUE; } else { RETAILMSG(1, (TEXT("ERROR: Probe: Can not find DM9000.\r\n"))); } return r;}/* * This function enables TX/RX interrupt mask * input : void * return : viod */void DM9000DBG_EnableInts(void){ /*only enable RX interrupt*/ WRITE_REG1(0xff, 0x81);}/* * This function disables TX/RX interrupt mask * input : void * return void */void DM9000DBG_DisableInts(void){ WRITE_REG1(0xff, 0x80);}/* Send a data block via Ethernet. */static USHORT dm9000_send (BYTE *pbData, USHORT length){ int i; int tmplen; IOWRITE(dwEthernetIOBase, 0xf8); /* data copy ready set */ /* copy data to FIFO */ switch (DM9000_iomode) { case DM9000_BYTE_MODE: tmplen = length ; for (i = 0; i < tmplen; i++) IOWRITE(dwEthernetDataPort, ((UCHAR *)pbData)[i]); break; case DM9000_WORD_MODE: tmplen = (length+1)/2; for (i = 0; i < tmplen; i++) IOWRITE16(dwEthernetDataPort, ((USHORT *)pbData)[i]); break; case DM9000_DWORD_MODE: tmplen = (length+3)/4; for (i = 0; i < tmplen; i++) IOWRITE32(dwEthernetDataPort, ((ULONG *)pbData)[i]); default: EdbgOutputDebugString("[DM9000][TX]Move data error!!!"); break; } /*set packet leng */ WRITE_REG1(0xfd, (length >> 8) & 0xff); WRITE_REG1(0xfc, length & 0xff); /* start transmit */ WRITE_REG1(0x02, 1); /*wait TX complete*/ while(1) { if (READ_REG1(0xfe) & 2) { //TX completed WRITE_REG1(0xfe, 2); break; } DM9000_Delay(1000); } return 0;}/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*//*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/BOOL DM9000DBG_Init(BYTE *iobase, ULONG membase, USHORT MacAddr[3]){ BOOL r = FALSE; bIsPacket = FALSE; dwEthernetIOBase = (DWORD)iobase; dwEthernetDataPort = dwEthernetIOBase + 4; dwEthernetMemBase = membase; r = Probe(); /*Detect DM9000 */ EdbgOutputDebugString("DM9000: MAC Address: %x:%x:%x:%x:%x:%x\r\n", MacAddr[0] & 0x00FF, MacAddr[0] >> 8, MacAddr[1] & 0x00FF, MacAddr[1] >> 8, MacAddr[2] & 0x00FF, MacAddr[2] >> 8); /* set the internal PHY power-on, GPIOs normal */ WRITE_REG1(0x1f, 0); /* GPR (reg_1Fh)bit GPIO0=0 pre-activate PHY */ DM9000_Delay(200000000); /* do a software reset */ WRITE_REG1(0x0, 3); /* NCR (reg_00h) bit[0] RST=1 & Loopback=1, reset on */ DM9000_Delay(200000000); WRITE_REG1(0x0, 3); /* NCR (reg_00h) bit[0] RST=1 & Loopback=1, reset on */ DM9000_Delay(200000000); /* I/O mode */ DM9000_iomode = READ_REG1(0xfe) >> 6; /* ISR bit7:6 keeps I/O mode */ /* Program operating register */ WRITE_REG1(0x0, 0); WRITE_REG1(0x02, 0); /* TX Polling clear */ WRITE_REG1(0x2f, 0); /* Special Mode */ WRITE_REG1(0x01, 0x2c); /* clear TX status */ WRITE_REG1(0xfe, 0x0f); /* Clear interrupt status */ /* Set address filter table */ dm9000_hash_table(MacAddr); /* Activate DM9000A/DM9010 */ WRITE_REG1(0x05, 0x30 | 1); /* Discard long packet and CRC error packets*//* RX enable */ WRITE_REG1(0xff, 0x80); /* Enable SRAM automatically return */ /* wait link ok */ while(1) { if(READ_REG1(0x01)&0x40) break; } return r;}//----------------------------------------------------------------------DWORDDM9000DBG_GetPendingInts(void){ UCHAR intr_state; intr_state = READ_REG1(0xfe); WRITE_REG1(0xfe, intr_state); /*clean ISR*/ return(1);}/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*//*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/UINT16 DM9000DBG_GetFrame(BYTE *pbData, UINT16 *pwLength){ int i; unsigned long tmp32; unsigned short rxlen, tmplen; unsigned short status; UCHAR RxRead; READ_REG1(0x3); READ_REG1(0x4); /*Try & work run*/ /* read the first byte*/ RxRead = READ_REG1(0xf0); RxRead = IOREAD(dwEthernetDataPort); RxRead = IOREAD(dwEthernetDataPort); /* the fist byte is ready or not */ if ((RxRead & 3) != 1) /* no data */ return 0; IOWRITE(dwEthernetIOBase, 0xf2); /* set read ptr ++ */ switch (DM9000_iomode) { case DM9000_BYTE_MODE: status = IOREAD(dwEthernetDataPort)+(IOREAD(dwEthernetDataPort)<<8); rxlen = IOREAD(dwEthernetDataPort) + (IOREAD(dwEthernetDataPort)<<8); break; case DM9000_WORD_MODE: status = IOREAD16(dwEthernetDataPort); rxlen = IOREAD16(dwEthernetDataPort); break; case DM9000_DWORD_MODE: tmp32 = IOREAD32(dwEthernetDataPort); status = (unsigned short)(tmp32&0xffff); rxlen = (unsigned short)((tmp32>>16)&0xffff); default: EdbgOutputDebugString("[DM9000]Get status and rxlen error!!!"); break; } if (status & 0xbf00) EdbgOutputDebugString("[DM9000]RX status error!!!=[%x]",(status>>8) ); /* move data from FIFO to memory */ switch (DM9000_iomode) { case DM9000_BYTE_MODE: tmplen = rxlen ; for (i = 0; i < tmplen; i++) ((UCHAR *)pbData)[i] = IOREAD(dwEthernetDataPort); break; case DM9000_WORD_MODE: tmplen = (rxlen+1)/2; for (i = 0; i < tmplen; i++) ((USHORT *)pbData)[i] = IOREAD16(dwEthernetDataPort); break; case DM9000_DWORD_MODE: tmplen = (rxlen+3)/4; for (i = 0; i < tmplen; i++) ((ULONG *)pbData)[i] = IOREAD32(dwEthernetDataPort); default: EdbgOutputDebugString("[DM9000][RX]Move data error!!!"); break; } *pwLength = rxlen; /* clean ISR */ WRITE_REG1(0xfe,READ_REG1(0xfe)); return rxlen; }/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*//*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/UINT16 DM9000DBG_SendFrame( BYTE *pbData, DWORD dwLength ) {// EdbgOutputDebugString("[DM9000A]: DM9000DBG_SendFrame()..........\r\n"); return dm9000_send(pbData, (UINT16)dwLength);}/* @func void | DM9000DBG_CurrentPacketFilter | Sets a receive packet h/w filter. @rdesc N/A. @comm @xref */void DM9000DBG_CurrentPacketFilter(DWORD dwFilter){ UCHAR uTemp; USHORT i, oft; EdbgOutputDebugString("[DM9000A]: DM9000DBG_CurrentPacketFilter()..........\r\n"); // What kind of filtering do we want to apply? // // NOTE: the filter provided might be 0, but since this EDBG driver is used for KITL, we don't want // to stifle the KITL connection, so broadcast and directed packets should always be accepted. // if (dwFilter & PACKET_TYPE_ALL_MULTICAST) { // Accept *all* multicast packets. uTemp = READ_REG1(0x05); WRITE_REG1(0x05, uTemp | 0x08); //Enable pass all multicast }#if 0 //Always can receive multicast address according to hash table. if (dwFilter & PACKET_TYPE_MULTICAST) { // Accept multicast packets. }#endif if (dwFilter & PACKET_TYPE_BROADCAST) { /* broadcast address */ hash_table[3] = 0x8000; /* Write the hash table to MAC MD table */ for (i = 0, oft = 0x16; i < 4; i++) { WRITE_REG1(oft++, hash_table[i] & 0xff); WRITE_REG1(oft++, (hash_table[i] >> 8) & 0xff); } } // Promiscuous mode is causing random hangs - it's not strictly needed. if (dwFilter & PACKET_TYPE_PROMISCUOUS) { // Accept anything. uTemp = READ_REG1(0x05); WRITE_REG1(0x05, uTemp | 0x02); //Enable pass all multicast } EdbgOutputDebugString("DM9000: Set receive packet filter [Filter=0x%x].\r\n", dwFilter);} // DM9000DBG_CurrentPacketFilter()./* @func BOOL | DM9000DBG_MulticastList | Sets a multicast address filter list. @rdesc TRUE = Success, FALSE = Failure. @comm @xref */BOOL DM9000DBG_MulticastList(PUCHAR pucMulticastAddresses, DWORD dwNumAddresses){ BYTE nCount; BYTE nIndex; BYTE i, oft; BYTE Reg5; //Stop RX Reg5 = READ_REG1(0x05); WRITE_REG1(0x05, Reg5 & 0xfe); // Compute the logical address filter value. // for (nCount = 0 ; nCount < dwNumAddresses ; nCount++) { EdbgOutputDebugString("DM9000: Multicast[%d of %d] = %x-%x-%x-%x-%x-%x\r\n", (nCount + 1), dwNumAddresses, pucMulticastAddresses[6*nCount + 0], pucMulticastAddresses[6*nCount + 1], pucMulticastAddresses[6*nCount + 2], pucMulticastAddresses[6*nCount + 3], pucMulticastAddresses[6*nCount + 4], pucMulticastAddresses[6*nCount + 5]); nIndex = CalculateHashIndex(&pucMulticastAddresses[6*nCount]); hash_table[nIndex/16] |= 1 << (nIndex%16); } EdbgOutputDebugString("DM9000: Logical Address Filter = %x.%x.%x.%x.\r\n", hash_table[3], hash_table[2], hash_table[1], hash_table[0]); /* Write the hash table to MAC MD table */ for (i = 0, oft = 0x16; i < 4; i++) { WRITE_REG1(oft++, hash_table[i] & 0xff); WRITE_REG1(oft++, (hash_table[i] >> 8) & 0xff); } //Start RX WRITE_REG1(0x05, Reg5); return(TRUE);} // DM9000DBG_MulticastList().
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -