📄 dm9isa.cpp
字号:
if(m_szCurrentSettings[SID_OP_MODE] & MAKE_MASK(0)) return; m_szCurrentSettings[SID_OP_MODE] |= MAKE_MASK(0); DeviceWritePort(DM9_RXCR,m_szCurrentSettings[SID_OP_MODE]);}void C_DM9000::DeviceDisableReceive(void){ // RX enable RXCR<0> if(!(m_szCurrentSettings[SID_OP_MODE] & MAKE_MASK(0))) return; m_szCurrentSettings[SID_OP_MODE] &= ~MAKE_MASK(0); DeviceWritePort(DM9_RXCR,m_szCurrentSettings[SID_OP_MODE]);}U32 C_DM9000::DeviceGetInterruptStatus(void){ // mask for bits // <3> rx overflow count overflow // <2> rx overflowf // <1> tx completed indication // <0> rx completed indication return DeviceReadPort(DM9_ISR) & MAKE_MASK4(3,2,1,0);}U32 C_DM9000::DeviceSetInterruptStatus( U32 uValue){ return DeviceWritePort(DM9_ISR,uValue);}U32 C_DM9000::DeviceGetReceiveStatus(void){ DEBUG_PRINT(( TEXT("nTxPendings=%d, %d"), m_nTxPendings, m_pUpper->m_TQueue.Size() )); U32 cr; cr = DeviceReadPort(DM9_ROCR); return ((cr>>7)&1)<<31 | (cr&0x7F);}void C_DM9000::DeviceStart(void){#ifdef IMPL_FLOW_CONTROL U32 val; // check full-duplex mode or not<3> val = DeviceReadPort(DM9_NCR); if( val & MAKE_MASK(3)) { /* full duplex mode */ val = DeviceReadPort(DM9_PAUSETH); DeviceWritePort(DM9_PAUSETH,(U8)val); // enable flow control<0> // enable pause packet<5> DeviceWritePort(DM9_FLOW,MAKE_MASK2(5,0)); } else { /* non full duplex mode */ val = DeviceReadPort(DM9_BACKTH); DeviceWritePort(DM9_BACKTH,(U8)val); // enable back pressure<half dumplex mode)<4,3> DeviceWritePort(DM9_FLOW,MAKE_MASK2(4,3)); }#endif // enable interrupt DeviceEnableInterrupt(); DeviceWritePort(DM9_RXCR,m_szCurrentSettings[SID_OP_MODE]);}void C_DM9000::DeviceReset(void){ // announce shutdown m_bShutdown = 1; // wait until all activities are fi. m_mutexRxValidate.Lock(); m_mutexTxValidate.Lock(); C_Exception *pexp; TRY { EDeviceInitialize(++m_nResetCounts); DeviceOnSetupFilter(0); FI; } CATCH(pexp){ // nothing to do CLEAN(pexp); } // of catch // dequeue for all objects in waiting and standby queue PCQUEUE_GEN_HEADER pcurr; for(;(pcurr=m_TQWaiting.Dequeue());) DeviceSendCompleted(pcurr); for(;(pcurr=m_TQStandby.Dequeue());) DeviceSendCompleted(pcurr); m_mutexRxValidate.Release(); m_mutexTxValidate.Release(); m_bShutdown = 0;}void C_DM9000::EDeviceInitialize( int nResetCounts){ U32 val; // reset member varialbes m_uLastAddressPort = (U32)-1; DeviceWritePort(0x1f, 0x00); NdisStallExecution(20); // software reset the device DeviceWritePort(DM9_NCR, 0x03); NdisStallExecution(20); DeviceWritePort(DM9_NCR, 0x03); NdisStallExecution(20); //DeviceWritePort(DM9_NCR, 0x00); // 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)); // output zero to activate internal phy DeviceWritePort(DM9_GPR, 0x00); // clear TX status DeviceWritePort(DM9_NSR, 0x00); // Enable memory chain DeviceWritePort(DM9_IMR, (1<<7)); #ifdef IMPL_STORE_AND_INDICATION if(nResetCounts) return; /* init rx buffers */ U32 m,uaddr; if(!(uaddr = (U32)malloc(sizeof(DATA_BLOCK)* (m=m_szConfigures[CID_RXBUFFER_NUMBER]*2)))) THROW((ERR_STRING("Insufficient memory"))); for(;m--;uaddr+=sizeof(DATA_BLOCK)) m_RQueue.Enqueue((PCQUEUE_GEN_HEADER)uaddr); /* set indication timer */ DeviceInitializeTimer(); #endif// v3.2.9 m_nMaxTxPending = (DeviceReadPort(DM9_CHIPREV) >= 0x10)?2:1; m_nTxPendings = 0;}void C_DM9000::DeviceResetPHYceiver(void){ return;}/******************************************************************************** * * Devcie handler routines * ********************************************************************************/#ifdef IMPL_DEVICE_ISRvoid C_DM9000::DeviceIsr( U32 uState){}#endif#ifdef IMPL_STORE_AND_INDICATIONvoid C_DM9000::DeviceOnTimer(void){ int val = m_RQStandby.Size(); PCQUEUE_GEN_HEADER pcurr; for(;(pcurr=m_RQStandby.Dequeue());m_RQueue.Enqueue(pcurr)) { DeviceReceiveIndication( 0,CQueueGetUserPointer(pcurr),pcurr->nLength); } // of for RQStandby loop }#endifint C_DM9000::DeviceOnSetupFilter( U32 uFilter){ int n; U8 sz[8]; U32 hashval; U32 newmode; // save old op mode newmode = m_szCurrentSettings[SID_OP_MODE]; // clear filter related bits, // pass all multicast<3> and promiscuous<1> newmode &= ~MAKE_MASK2(3,1); // zero input means one reset request if(!(m_szCurrentSettings[SID_GEN_CURRENT_PACKET_FILTER]=uFilter)) { /* 1. set unicast */ // retrive node address DeviceMacAddress(&sz[0]); // set node address for(n=0;n<ETH_ADDRESS_LENGTH;n++) DeviceWritePort(DM9_PAR0+n,(U32)sz[n]); /* 2. clear multicast list and count */ m_nMulticasts = 0; memset((void*)&m_szMulticastList,0,sizeof(m_szMulticastList)); /* 3. clear hash table */ // clear hash table memset((void*)(&sz[0]),0,sizeof(sz)); for(n=0;n<sizeof(sz);n++) DeviceWritePort(DM9_MAR0+n,(U32)sz[n]); return uFilter; } // if promiscuous mode<1> is requested, // just set this bit and return if( (uFilter & NDIS_PACKET_TYPE_PROMISCUOUS) ) { // add promiscuous<1> newmode |= MAKE_MASK(1); DeviceWritePort(DM9_RXCR,m_szCurrentSettings[SID_OP_MODE]=newmode); return uFilter; } // if pass all multicast<3> is requested, if(uFilter & NDIS_PACKET_TYPE_ALL_MULTICAST) newmode |= MAKE_MASK(3); // prepare new hash table memset((void*)(&sz[0]),0,sizeof(sz)); // if broadcast, its hash value is known as 63. if(uFilter & NDIS_PACKET_TYPE_BROADCAST) sz[7] |= 0x80; if(uFilter & NDIS_PACKET_TYPE_MULTICAST) for(n=0;n<m_nMulticasts;n++) { hashval = DeviceCalculateCRC32( &m_szMulticastList[n][0],ETH_ADDRESS_LENGTH,FALSE) & 0x3f; sz[hashval/8] |= 1 << (hashval%8); } // of calculate hash table // submit the new hash table for(n=0;n<sizeof(sz);n++) DeviceWritePort(DM9_MAR0+n,(U32)sz[n]); DeviceWritePort(DM9_RXCR,m_szCurrentSettings[SID_OP_MODE]=newmode); return uFilter;}void C_DM9000::DeviceInterruptEventHandler( U32 uValue){ // check RX activities if(uValue & 0x01) Dm9LookupRxBuffers(); // return if not TX latch if(!(uValue & 0x02)) return; U32 nsr; nsr = DeviceReadPort(DM9_NSR); // check TX-END2 if(nsr & 0x08) { m_nTxPendings--; DeviceSendCompleted(m_TQWaiting.Dequeue()); } // check TX-END1 if(nsr & 0x04) { m_nTxPendings--; DeviceSendCompleted(m_TQWaiting.Dequeue()); } // report tx available now if( nsr & 0x0C ) NdisMSendResourcesAvailable(m_pUpper->GetNdisHandle());}U32 C_DM9000::DeviceHardwareStatus(void){ return m_nTxPendings?0:NIC_HW_TX_IDLE;} int C_DM9000::DeviceSend( PCQUEUE_GEN_HEADER pObject){ PCQUEUE_GEN_HEADER pcurr; if(pObject) m_TQStandby.Enqueue(pObject); /* increment counter */ m_nTxPendings++; /* get first pkt in queue */ m_TQWaiting.Enqueue(pcurr=m_TQStandby.Dequeue()); /* fill data */ DeviceWriteString((PU8)CQueueGetUserPointer(pcurr),pcurr->nLength); DeviceWritePort(DM9_TXLENH,HIGH_BYTE(pcurr->nLength)); DeviceWritePort(DM9_TXLENL,LOW_BYTE(pcurr->nLength)); // TXCR<0>, issue TX request DeviceWritePort(DM9_TXCR, MAKE_MASK(0)); return 0;}int C_DM9000::Dm9LookupRxBuffers(void){ if(!m_mutexRxValidate.TryLock()) return 0; int counts=0; int errors=0; U32 desc; PDM9_RX_DESCRIPTOR pdesc;#ifdef IMPL_STORE_AND_INDICATION PCQUEUE_GEN_HEADER pcurr;#else U8 szbuffer[DRIVER_BUFFER_SIZE];#endif for(pdesc=(PDM9_RX_DESCRIPTOR)&desc;;) { CHECK_SHUTDOWN(); // probe first byte desc = DeviceReadDataWithoutIncrement(); // check if packet available, 01h means available, 00h means no data if(pdesc->bState != 0x01) break; // get the data descriptor again desc = DeviceReadData(); // read out the data to buffer // Performance issue: maybe we may discard the data // just add the rx address. // if the length is greater than buffer size, ... if((pdesc->nLength > DRIVER_BUFFER_SIZE)) { DeviceIndication(AID_LARGE_INCOME_PACKET); break; }#ifdef IMPL_STORE_AND_INDICATION if(!(pcurr=m_RQueue.Dequeue())) { RETAILMSG(TRUE,(TEXT("Queue overflow"))); BREAK; // packet will lost!! break; } DeviceReadString((PU8)CQueueGetUserPointer(pcurr),pcurr->nLength=pdesc->nLength);#else DeviceReadString((PU8)&szbuffer,pdesc->nLength);#endif // check status, as specified in DM9_RXSR, // the following bits are error // <3> PLE // <2> AE // <1> CE // <0> FOE if(pdesc->bStatus & MAKE_MASK4(3,2,1,0)) { errors++;#ifdef IMPL_STORE_AND_INDICATION m_RQueue.Enqueue(pcurr);#endif continue; } // of error happens counts++;#ifdef IMPL_STORE_AND_INDICATION m_RQStandby.Enqueue(pcurr);#else DeviceReceiveIndication( 0, (PVOID)&szbuffer, pdesc->nLength);#endif } // of forever read loop REPORT(TID_GEN_RCV_OK, counts); REPORT(TID_GEN_RCV_ERROR, errors); m_mutexRxValidate.Release();#ifdef IMPL_STORE_AND_INDICATION if (!m_RQStandby.IsQueueEmpty()) DeviceSetTimer(5);#endif return counts;}/******************************************************************* * * Hooked function * *******************************************************************//******************************************************************* * * Device Entry * *******************************************************************/extern "C" NIC_DEVICE_OBJECT *DeviceEntry( NIC_DRIVER_OBJECT *pDriverObject, PVOID pVoid){ return new C_DM9000(pDriverObject,pVoid);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -