⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dm9isa.cpp

📁 网络控制器dm9000的wince6.0驱动源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/********************************************************************************
 * 
 * $Id: dm9isa.cpp,v 1.2 2007/07/10 04:16:22 bill Exp $
 *
 * Copyright (c) 2000-2005 Davicom Inc.  All rights reserved.
 *
 ********************************************************************************/

#include	"dm9isa.h"


/*******************************************************************************
 *
 *
 *
 ********************************************************************************/
CONFIG_PARAMETER	g_szDm9ConfigParams[] =
{
	{ CID_CONNECTION_TYPE, -1, NDIS_STRING_CONST("ConnectionType") },
	{ CID_SLOT_NUMBER, -1, NDIS_STRING_CONST("SlotNumber")},
	{ CID_BUFFER_PHYSICAL_ADDRESS, 0, NDIS_STRING_CONST("BufferPhysicalAddress")},
	{ CID_TXBUFFER_NUMBER, 0x20, NDIS_STRING_CONST("XmitBuffer")},
	{ CID_RXBUFFER_NUMBER, 0x10, NDIS_STRING_CONST("RecvBuffer")},
	{ CID_ADAPTER_NUMBER, 0, NDIS_STRING_CONST("AdapterNumber")},
	{ CID_IO_BASE_ADDRESS, 0x300, NDIS_STRING_CONST("IoAddress")},
	{ CID_IO_RANGE, 0x10, NDIS_STRING_CONST("IoRange")},
	{ CID_IRQ_NUMBER, 3, NDIS_STRING_CONST("IrqNumber")},
	{ -1,-1,NULL}
};

/*******************************************************************************
 *
 * Device attributes and characteristics
 *
 ********************************************************************************/
PCONFIG_PARAMETER	C_DM9000::DeviceConfigureParameters(void)
{
	return (PCONFIG_PARAMETER)&g_szDm9ConfigParams[0];
}

void	C_DM9000::DeviceSetEepromFormat(void)
{
	m_szEepromFormat[EID_MAC_ADDRESS] = 0;
	m_szEepromFormat[EID_VENDOR_ID] = 8;
	m_szEepromFormat[EID_PRODUCT_ID] = 10;
}

void	C_DM9000::EDeviceRegisterIoSpace(void)
{
	NIC_DEVICE_OBJECT::EDeviceRegisterIoSpace();
	
	U32	val;
	
	val  = DeviceReadPort(0x2a);
	val |= DeviceReadPort(0x2b)<<8;
	val |= DeviceReadPort(0x28)<<16;
	val |= DeviceReadPort(0x29)<<24;

	DEBUG_PRINT((
		TEXT("[dm9: Chip signature is %08X\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)) )
		THROW((ERR_STRING("Unknown device")));

}

void	C_DM9000::EDeviceValidateConfigurations(void)
{
	NDIS_HANDLE		hndis = m_pUpper->GetNdisHandle();

	// validate slot number
	if( 
		(m_szConfigures[CID_IO_BASE_ADDRESS] == -1) ||
		(m_szConfigures[CID_IRQ_NUMBER] == -1) ) 
		THROW(());

	m_szCurrentSettings[SID_GEN_TRANSMIT_BUFFER_SPACE] = 
		m_szConfigures[CID_TXBUFFER_NUMBER]
		* ETH_MAX_FRAME_SIZE;
	m_szCurrentSettings[SID_GEN_RECEIVE_BUFFER_SPACE] = 
		m_szConfigures[CID_RXBUFFER_NUMBER]
		* ETH_MAX_FRAME_SIZE;

	m_szConfigures[CID_CHECK_FOR_HANG_PERIOD] = 3;
	m_szConfigures[CID_IRQ_GEN_TYPE] = NdisInterruptLatched;
	m_szConfigures[CID_IRQ_SHARED] = TRUE;
	m_szConfigures[CID_IRQ_LEVEL] = 0x0F;
	m_szConfigures[CID_INTERFACE_TYPE] = NdisInterfaceIsa;
	m_szConfigures[CID_BUS_MASTER] = FALSE;

	// set receive mode
	// <5> discard long packet
	// <4> discard CRC error packet
	// <0> rx enable
	m_szCurrentSettings[SID_OP_MODE] = MAKE_MASK3(5,4,0);

	m_szCurrentSettings[SID_802_3_MAXIMUM_LIST_SIZE] = DM9_MULTICAST_LIST;
}


/*******************************************************************************
 *
 * Device access routines
 *
 ********************************************************************************/
#define	ENTER_CRITICAL_SECTION	m_spinAccessToken.Lock();
#define	LEAVE_CRITICAL_SECTION	m_spinAccessToken.Release();
#define	VALIDATE_ADDR_PORT(p) \
	if(m_uLastAddressPort != (p)) \
		NdisRawWritePortUchar( \
		m_szCurrentSettings[SID_PORT_BASE_ADDRESS] + DM9000_ADDR_OFFSET,  \
		(U8) (m_uLastAddressPort=(U32(p))) )


U32	C_DM9000::DeviceWritePort(
	U32		uPort,
	U32		uValue)
{

	ENTER_CRITICAL_SECTION

	VALIDATE_ADDR_PORT(uPort);

	NdisRawWritePortUchar(
		m_szCurrentSettings[SID_PORT_BASE_ADDRESS] + DM9000_DATA_OFFSET, 
		(U8)uValue);

	LEAVE_CRITICAL_SECTION
	
	return uValue;
}


U32	C_DM9000::DeviceReadPort(
	U32		uPort)
{
	U16		val;

	ENTER_CRITICAL_SECTION

	VALIDATE_ADDR_PORT(uPort);

	NdisRawReadPortUchar(
		m_szCurrentSettings[SID_PORT_BASE_ADDRESS] + DM9000_DATA_OFFSET, &val);
	
	LEAVE_CRITICAL_SECTION
	
	return (U32)val;
}

U16	C_DM9000::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);
}

U16	C_DM9000::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);
	
	// stop command
	DeviceWritePort(DM9_EPCNTL,0);

	// extra delay
	NdisStallExecution(1000);
	
	return uValue;
}

U16	C_DM9000::DeviceReadPhy(
	U32		uRegister,
	U32		uOffset)
{
	U16		highbyte,lowbyte;
	
	// assign the phy register offset, internal phy(0x40) plus phy offset
	DeviceWritePort(DM9_EPADDR,(0x40|(uOffset&0x3F)));
	
	// issue PHY select<3> and PHY read command<2>
	DeviceWritePort(DM9_EPCNTL,((1<<3)|(1<<2)) );
	
	// wait until status bit<0> cleared
	DevicePolling(DM9_EPCNTL,(1<<0),0x00);
	
	// stop command
	DeviceWritePort(DM9_EPCNTL,0);

	// retrive data
	lowbyte  = (U16)DeviceReadPort(DM9_EPLOW);
	highbyte = (U16)DeviceReadPort(DM9_EPHIGH);
	
	return ((highbyte<<8) | lowbyte);
}

U16	C_DM9000::DeviceWritePhy(
	U32		uRegister,
	U32		uOffset,
	U16		uValue)
{
	// assign the phy register offset, internal phy(0x40) plus phy offset
	DeviceWritePort(DM9_EPADDR,(0x40|(uOffset&0x3F)));

	// put data
	DeviceWritePort(DM9_EPLOW, LOW_BYTE(uValue));
	DeviceWritePort(DM9_EPHIGH,HIGH_BYTE(uValue));

	// issue PHY select<3> and write command<1>		
	DeviceWritePort(DM9_EPCNTL,((1<<3)|(1<<1)) );
	
	// wait until status bit<0> cleared
	DevicePolling(DM9_EPCNTL,(1<<0),0x00);
	
	// stop command
	DeviceWritePort(DM9_EPCNTL,0);

	return uValue;
}

	
U32		C_DM9000::DeviceReadData(void)
{
	U32		value;

	return	*(PU32)DeviceReadString((PU8)&value,sizeof(value));
}
	
U32		C_DM9000::DeviceReadDataWithoutIncrement(void)
{
	U32		value,tmp;

	ENTER_CRITICAL_SECTION

	VALIDATE_ADDR_PORT(DM9_MRCMDX);

	switch (m_nIoMode)
	{
		case BYTE_MODE:
			NdisRawReadPortUchar(
				m_szCurrentSettings[SID_PORT_BASE_ADDRESS] 
				+ DM9000_DATA_OFFSET, (PU8)&tmp);
			NdisRawReadPortUchar(
				m_szCurrentSettings[SID_PORT_BASE_ADDRESS] 
				+ DM9000_DATA_OFFSET, (PU8)&value);
			value = (value&0x000000FF);
			break;

		case WORD_MODE:
			NdisRawReadPortUshort(
				m_szCurrentSettings[SID_PORT_BASE_ADDRESS] 
				+ DM9000_DATA_OFFSET, (PU16)&tmp);
			NdisRawReadPortUshort(
				m_szCurrentSettings[SID_PORT_BASE_ADDRESS] 
				+ DM9000_DATA_OFFSET, (PU16)&value);
			value = (value&0x0000FFFF);
			break;
				
		case DWORD_MODE:
			NdisRawReadPortUlong(
				m_szCurrentSettings[SID_PORT_BASE_ADDRESS] 
				+ DM9000_DATA_OFFSET, (PU32)&tmp);
			NdisRawReadPortUlong(
				m_szCurrentSettings[SID_PORT_BASE_ADDRESS] 
				+ DM9000_DATA_OFFSET, (PU32)&value);
			break;
				
		default:
			break;
	} // of switch

	LEAVE_CRITICAL_SECTION
	
	return value;
}


PU8		C_DM9000::DeviceReadString(
	PU8		ptrBuffer,
	int		nLength)
{
	int		count;
	
	count = (nLength + m_nIoMaxPad) / m_nIoMode;

	// select port to be read from
	ENTER_CRITICAL_SECTION

	VALIDATE_ADDR_PORT(DM9_MRCMD);

	switch (m_nIoMode)
	{
		case BYTE_MODE:
			NdisRawReadPortBufferUchar(
				m_szCurrentSettings[SID_PORT_BASE_ADDRESS] + DM9000_DATA_OFFSET, 
				ptrBuffer,count);
			break;
			
		case WORD_MODE:
			NdisRawReadPortBufferUshort(
				m_szCurrentSettings[SID_PORT_BASE_ADDRESS] + DM9000_DATA_OFFSET, 
				(PU16)ptrBuffer,count);
			break;

		case DWORD_MODE:
			NdisRawReadPortBufferUlong(
				m_szCurrentSettings[SID_PORT_BASE_ADDRESS] + DM9000_DATA_OFFSET, 
				(PU32)ptrBuffer,count);
			break;
		
		default:
			break;
	} // of switch

	LEAVE_CRITICAL_SECTION
	
	return ptrBuffer;
}


PU8		C_DM9000::DeviceWriteString(
	PU8		ptrBuffer,
	int		nLength)
{
	int		count;
	
	count = (nLength + m_nIoMaxPad) / m_nIoMode;

#if defined(PREEMPTIVE_TX_WRITE) 

	switch (m_nIoMode)
	{
		case BYTE_MODE:
		{
			PU8	pcurr=(PU8)ptrBuffer;
			for(;count--;pcurr++)
			{
				ENTER_CRITICAL_SECTION
				VALIDATE_ADDR_PORT(DM9_MWCMD);

				NdisRawWritePortUchar(
					m_szCurrentSettings[SID_PORT_BASE_ADDRESS] 
					+ DM9000_DATA_OFFSET, *pcurr);
				
				LEAVE_CRITICAL_SECTION
			}
		}
			break;
			
		case WORD_MODE:
		{
			PU16	pcurr=(PU16)ptrBuffer;
			
			for(;count--;pcurr++)
			{
				ENTER_CRITICAL_SECTION
				VALIDATE_ADDR_PORT(DM9_MWCMD);

				NdisRawWritePortUshort(
					m_szCurrentSettings[SID_PORT_BASE_ADDRESS] 
					+ DM9000_DATA_OFFSET, *pcurr);

				LEAVE_CRITICAL_SECTION
			}
		}
			break;

		case DWORD_MODE:
		{
			PU32	pcurr=(PU32)ptrBuffer;
			for(;count--;pcurr++)
			{
				ENTER_CRITICAL_SECTION
				VALIDATE_ADDR_PORT(DM9_MWCMD);

				NdisRawWritePortUlong(
					m_szCurrentSettings[SID_PORT_BASE_ADDRESS] 
					+ DM9000_DATA_OFFSET, *pcurr);
				
				LEAVE_CRITICAL_SECTION
			}
		}
			break;
		
		default:
			break;
	} // of switch
	
#else // !PREEMPTIVE_TX_WRITE
	// select port to be read from
	ENTER_CRITICAL_SECTION

	VALIDATE_ADDR_PORT(DM9_MWCMD);

	switch (m_nIoMode)
	{
		case BYTE_MODE:
			NdisRawWritePortBufferUchar(
				m_szCurrentSettings[SID_PORT_BASE_ADDRESS] + DM9000_DATA_OFFSET, 
				ptrBuffer,count);
			break;
			
		case WORD_MODE:
			NdisRawWritePortBufferUshort(
				m_szCurrentSettings[SID_PORT_BASE_ADDRESS] + DM9000_DATA_OFFSET, 
				(PU16)ptrBuffer,count);
			break;

		case DWORD_MODE:
			NdisRawWritePortBufferUlong(
				m_szCurrentSettings[SID_PORT_BASE_ADDRESS] + DM9000_DATA_OFFSET, 
				(PU32)ptrBuffer,count);
			break;
		
		default:
			break;
	} // of switch
	
	LEAVE_CRITICAL_SECTION

#endif

	return ptrBuffer;
}


/********************************************************************************
 *
 * Devcie control routines
 *
 ********************************************************************************/

void	C_DM9000::DeviceEnableInterrupt(void)
{
	// 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)));
}

void	C_DM9000::DeviceDisableInterrupt(void)
{
	// <7> buffer chain enable
	DeviceWritePort(DM9_IMR,(1<<7));
}

void 	C_DM9000::DeviceEnableReceive(void)
{
	// RX enable RXCR<0>
	if(m_szCurrentSettings[SID_OP_MODE] & MAKE_MASK(0)) return;

⌨️ 快捷键说明

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