📄 dm9isa.cpp
字号:
/********************************************************************************
*
* $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 + -