dm9000.c

来自「该BSP是基于PXA270+WINCE的BSP」· C语言 代码 · 共 1,301 行 · 第 1/3 页

C
1,301
字号
	
	// 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(
	int		nResetCounts)
{
	U32		val;
	
	// reset member varialbes
	m_uLastAddressPort = (U32)-1;
	
	DeviceWritePort(0x1f, 0x00);
	mWait(20);

	// software reset the device
	DeviceWritePort(DM9_NCR, 0x03);
	mWait(20);

	DeviceWritePort(DM9_NCR, 0x03);
	mWait(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));
	mWait(20);
	// output zero to activate internal phy
	DeviceWritePort(DM9_GPR,  0x00);
	mWait(20);
	// Enable memory chain
	DeviceWritePort(DM9_IMR, (1<<7));
	mWait(20);	

	DeviceWritePort( DM9_TXCR, 0);		/* TX Polling clear */
	mWait(20);	
	DeviceWritePort( DM9_BACKTH, 0x3f);	/* Less 3kb, 600us */
	mWait(20);	
	DeviceWritePort( DM9_SMCR, 0);		/* Special Mode */
	mWait(20);	
	DeviceWritePort( DM9_NSR, 0x2c);	/* clear TX status */
	mWait(20);	
	DeviceWritePort( DM9_ISR, 0x0f); 	/* Clear interrupt status */
	mWait(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;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?