📄 dm9isa.cpp
字号:
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;
// set PHY supports flow control
DeviceWritePhy(0, 4, (DeviceReadPhy(0,4)|(1<<10)));
// 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_ISR
void C_DM9000::DeviceIsr(
U32 uState)
{
}
#endif
#ifdef IMPL_STORE_AND_INDICATION
void 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
}
#endif
int 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 + -