eboot下使用的DM9000驱动源代码

#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.02
static 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
#endif
static BOOL bIsPacket;

static UCHAR
ReadReg(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;
}
//----------------------------------------------------------------------
DWORD
DM9000DBG_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().

你可能感兴趣的:(源代码,职场,驱动,休闲)