📄 dm9isa.cpp
字号:
/******************************************************************************** * * $Id: dm9000.cpp,v 1.8 2004/12/16 06:23:12 hychu 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>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -