📄 e100bexadap.cpp
字号:
#if DBG
if ( m_pCard->ReceiveUnitStarted() )
{
TRACE("RU is active\n");
}
// Big hack to check to make sure that all of the RFDs are indeed clear.
// If they are not then we'll generate a break point.
for (UINT i=0; i< m_pRxArea->GetNumberFreeDescriptors(); i++)
{
KNdisPacket Packet(reinterpret_cast<KNdisReceiveArea*>(m_pRxArea)
->Complete(reinterpret_cast<PHW_RFD>(m_pRxArea->GetHeadDescriptor())));
ASSERT( Packet.IsValid() );
PHW_RFD pHwRfd = reinterpret_cast<PHW_RFD>(m_pRxArea->GetDescriptor(Packet));
ASSERT( pHwRfd );
if (pHwRfd->RfdCbHeader.CbStatus & RFD_STATUS_COMPLETE)
{
TRACE("RFD NOT PROCESSED!!!\n");
// DbgBreakPoint();
}
reinterpret_cast<KNdisReceiveArea*>(m_pRxArea)->Reclaim(Packet);
}
#endif //DBG
// Get the physical address of the current descriptor (accesses
// the head of the free RFD list in KNdisSharedReceiveArea)
PNDIS_PHYSICAL_ADDRESS pPhysAddr = m_pRxArea->GetHeadPhysicalAddress();
ASSERT( 0 != pPhysAddr->LowPart );
// Call the card method to start the receive unit.
m_pCard->StartReceiveUnit(pPhysAddr);
return Status;
}
////////////////////////////////////////////////////////////////////
// E100bexAdapter::ParseRegistryParameters
//
// This routine will read our parameters from the registry
//
// Parameters:
// Config
// Reference to KNdisConfig object that we use to query various
// configuration parameters
// Ai
// Reference to ADAPTER_INFO object used to store certain registry paramters
// IRQL:
// PASSIVE_LEVEL
// Return Mode:
// Synchronous
//
// NOTE:
//
NDIS_STATUS E100bexAdapter::ParseRegistryParameters(IN KNdisConfig& Config, IN ADAPTER_INFO& Ai)
{
#if DBG
// debug trace mask
ULONG nDebug = Config.Read(KNDIS_STRING_CONST("Debug"), E100BEX_Debug_DEFAULT,
E100BEX_Debug_MIN, E100BEX_Debug_MAX, NdisParameterInteger);
// The debug trace mask will be stored in the high word of KNdisOidDebug::sm_uTraceMask
// Left shift the debug trace mask by 16 bits so that the high word will be used
nDebug <<= 16;
// Access the current KNdisOidDebug::sm_uTraceMask and or with the debug trace mask
// KNdisOidDebug::sm_uTraceMask utilizes the low word. The high word will be masked off
// for our purposes (this drivers debug trace mask)
nDebug |= ( 0x0000FFFF & KNdisOidDebug::TraceMask());
// Update KNdisOidDebug::sm_uTraceMask to have the original KNdisOidDebug::sm_uTraceMask
// stored in the low word and the debug trace mask in the high word.
KNdisOidDebug::EnableTrace(nDebug);
#endif // DBG
m_NumRfd = static_cast<UINT>(Config.Read(KNDIS_STRING_CONST("NumRfd"),
E100BEX_NumRfd_DEFAULT, E100BEX_NumRfd_MIN, E100BEX_NumRfd_MAX));
m_RegNumTcb = static_cast<UINT>(Config.Read(KNDIS_STRING_CONST("NumTcb"),
E100BEX_RegNumTcb_DEFAULT, E100BEX_RegNumTcb_MIN, E100BEX_RegNumTcb_MAX));
m_NumTbdPerTcb = static_cast<UINT>(Config.Read(KNDIS_STRING_CONST("NumTbdPerTcb"),
E100BEX_NumTbdPerTcb_DEFAULT, E100BEX_NumTbdPerTcb_MIN, E100BEX_NumTbdPerTcb_MAX));
m_NumCoalesce = static_cast<UINT>(Config.Read(KNDIS_STRING_CONST("NumCoalesce"),
E100BEX_NumCoalesce_DEFAULT, E100BEX_NumCoalesce_MIN, E100BEX_NumCoalesce_MAX));
m_NumMapRegisters = static_cast<UINT>(Config.Read(KNDIS_STRING_CONST("MapRegisters"),
E100BEX_NumMapRegisters_DEFAULT, E100BEX_NumMapRegisters_MIN, E100BEX_NumMapRegisters_MAX));
m_AiThreshold = static_cast<USHORT>(Config.Read(KNDIS_STRING_CONST("Threshold"),
E100BEX_AiThreshold_DEFAULT, E100BEX_AiThreshold_MIN, E100BEX_AiThreshold_MAX));
Ai.PhyAddress = static_cast<UINT>(Config.Read(KNDIS_STRING_CONST("PhyAddress"),
E100BEX_PhyAddress_DEFAULT, E100BEX_PhyAddress_MIN, E100BEX_PhyAddress_MAX));
Ai.Connector = static_cast<UCHAR>(Config.Read(KNDIS_STRING_CONST("Connector"),
E100BEX_Connector_DEFAULT, E100BEX_Connector_MIN, E100BEX_Connector_MAX));
Ai.AiTxFifo = static_cast<USHORT>(Config.Read(KNDIS_STRING_CONST("TxFifo"),
E100BEX_AiTxFifo_DEFAULT, E100BEX_AiTxFifo_MIN, E100BEX_AiTxFifo_MAX));
Ai.AiRxFifo = static_cast<USHORT>(Config.Read(KNDIS_STRING_CONST("RxFifo"),
E100BEX_AiRxFifo_DEFAULT, E100BEX_AiRxFifo_MIN, E100BEX_AiRxFifo_MAX));
Ai.AiTxDmaCount = static_cast<UCHAR>(Config.Read(KNDIS_STRING_CONST("TxDmaCount"),
E100BEX_AiTxDmaCount_DEFAULT, E100BEX_AiTxDmaCount_MIN, E100BEX_AiTxDmaCount_MAX));
Ai.AiRxDmaCount = static_cast<UCHAR>(Config.Read(KNDIS_STRING_CONST("RxDmaCount"),
E100BEX_AiRxDmaCount_DEFAULT, E100BEX_AiRxDmaCount_MIN, E100BEX_AiRxDmaCount_MAX));
Ai.AiUnderrunRetry = static_cast<UCHAR>(Config.Read(KNDIS_STRING_CONST("UnderrunRetry"),
E100BEX_AiUnderrunRetry_DEFAULT, E100BEX_AiUnderrunRetry_MIN, E100BEX_AiUnderrunRetry_MAX));
Ai.AiForceDpx = static_cast<UCHAR>(Config.Read(KNDIS_STRING_CONST("ForceDpx"),
E100BEX_AiForceDpx_DEFAULT, E100BEX_AiForceDpx_MIN, E100BEX_AiForceDpx_MAX));
Ai.AiTempSpeed = static_cast<USHORT>(Config.Read(KNDIS_STRING_CONST("Speed"),
E100BEX_AiTempSpeed_DEFAULT, E100BEX_AiTempSpeed_MIN, E100BEX_AiTempSpeed_MAX));
Ai.McTimeoutFlag = static_cast<UINT>(Config.Read(KNDIS_STRING_CONST("MCWA"),
E100BEX_McTimeoutFlag_DEFAULT, E100BEX_McTimeoutFlag_MIN, E100BEX_McTimeoutFlag_MAX));
Ai.MWIEnable = static_cast<BOOLEAN>(Config.Read(KNDIS_STRING_CONST("MWIEnable"),
E100BEX_MWIEnable_DEFAULT, E100BEX_MWIEnable_MIN, E100BEX_MWIEnable_MAX));
Ai.Congest = static_cast<UCHAR>(Config.Read(KNDIS_STRING_CONST("Congest"),
E100BEX_Congest_DEFAULT, E100BEX_Congest_MIN, E100BEX_Congest_MAX));
return NDIS_STATUS_SUCCESS;
}
PUCHAR E100bexAdapter::AlignSharedMemory(
IN OUT PULONG pLowPhysAddr,
ULONG Alignment,
KNdisSharedMemory& ShMem
)
{
ASSERT( pLowPhysAddr );
ASSERT( ShMem.IsValid() );
PUCHAR pMem = NULL;
if ( pLowPhysAddr && ShMem.IsValid() )
{
ULONG LowPhysAddr = *pLowPhysAddr;
LowPhysAddr += Alignment - 1;
LowPhysAddr &= ~(Alignment - ULONG(1));
pMem = reinterpret_cast<PUCHAR>(ShMem.VirtualAddress()) + LowPhysAddr - NdisGetPhysicalAddressLow( *ShMem.PhysicalAddress() );
*pLowPhysAddr = LowPhysAddr;
}
return pMem;
}
////////////////////////////////////////////////////////////////////
// E100bexAdapter::SetupSharedAdapterMemory
//
// This routine will setup the adapter memory shared with the NIC card
//
// Parameters:
//
// IRQL:
// PASSIVE_LEVEL
// Return Mode:
// Synchronous
//
// NOTE:
//
NDIS_STATUS E100bexAdapter::SetupSharedAdapterMemory(void)
{
NDIS_STATUS Status;
// set this up here to make sure we always have enough MAP REGISTERS
// for all the TBDs we have allocated
// Total number of TBDs equals number of TCBs * number of TBDs per TCB
m_NumTbd = (m_NumTcb * m_NumTbdPerTcb);
// Number of map registers is equal to the number of TBDs
m_NumMapRegisters = m_NumTbd;
TRACE("Allocating %x map registers\n", m_NumMapRegisters);
// NOTE -- This call MUST be made, even if you don't really want any map
// registers, if you are going to allocate any shared memory.
Status = NdisMAllocateMapRegisters(
*this,
0,
TRUE,
m_NumMapRegisters,
m_MaxPhysicalMappings);
if (Status != NDIS_STATUS_SUCCESS)
{
TRACE("NdisMAllocateMapRegister Failed - %x\n", Status);
m_NumMapRegisters = 0;
KNDIS_RETURN_ERROR_1PARAM(NDIS_ERROR_CODE_OUT_OF_RESOURCES, EVENT_11);
}
// Allocate memory for the shared receive resources with enough
// extra to paragraph align everything.
ULONG Length = 16 + (m_NumRfd * sizeof(HW_RFD));
// Allocate the initial shared memory for the receive data structures.
m_pRxShMem = new KNdisSharedMemory( this, Length);
if( ! m_pRxShMem->IsValid() )
{
TRACE("Could not allocate %d bytes for m_pShMem mem\n", Length);
KNDIS_RETURN_ERROR_1PARAM(NDIS_ERROR_CODE_OUT_OF_RESOURCES, EVENT_13);
}
TRACE("Allocated %08x %8d bytes for RecvUnCached mem\n", m_pRxShMem->VirtualAddress(), m_pRxShMem->Length());
// Allocate cached memory for the SW transmit structures.
m_XmitCachedSize = (m_NumTcb * sizeof(D100SwTcb)) + (m_NumCoalesce * sizeof(COALESCE));
m_XmitCached = new UCHAR[m_XmitCachedSize];
if (m_XmitCached == NULL)
{
TRACE("Could not allocate %d bytes for XmitCached mem\n", m_XmitCachedSize);
KNDIS_RETURN_ERROR_1PARAM(NDIS_ERROR_CODE_OUT_OF_RESOURCES, EVENT_14);
}
TRACE("Allocated %08x %8d bytes for XmitCached mem\n", m_XmitCached, m_XmitCachedSize);
// initialize this recently allocated area to zeros
NdisZeroMemory(m_XmitCached, m_XmitCachedSize);
// Allocate memory for the shared transmit resources with enough extra mem
// to paragraph align everything & ask the card object how much mem it needs
// for its shared resources
// We will allocate one buffer for the transmit stuctures and the card object's
// shared memory. The first chunk of the buffer will be for the card object's
// shared memory. The card object is queried for how much memory it requires.
UINT CbUnCachedSize =
m_pCard->GetSharedMemorySize() + // Card object shared memory
MINIMUM_ETHERNET_PACKET_SIZE +
(m_NumTcb * sizeof(TXCB_STRUC)) + 0x100 + // Transmit structures...
(m_NumTbd * sizeof(TBD_STRUC)) + 16 +
((m_NumCoalesce + 1) * COALESCE_BUFFER_SIZE);
m_pCbShMem = new KNdisSharedMemory(
this,
CbUnCachedSize
);
if( ! m_pCbShMem->IsValid() )
{
TRACE("Could not allocate %d bytes for m_pCbShMem mem\n", CbUnCachedSize);
KNDIS_RETURN_ERROR_1PARAM(NDIS_ERROR_CODE_OUT_OF_RESOURCES, EVENT_13);
}
TRACE("Allocated %08x %8d bytes for XmitUnCached mem\n", m_pCbShMem->VirtualAddress(), m_pCbShMem->Length() );
// Initialize the 82557 Control Structures pointers
PUCHAR pMem = NULL;
ULONG CbPhys = NdisGetPhysicalAddressLow( *m_pCbShMem->PhysicalAddress() );
// The first part of the shared memory will be reserved for the card object's structures.
// Notify the card object of its memory (the start of the buffer). The card object
// will adjust the pointers to just beyond the end of the card object's structures.
CbPhys = m_pCard->SetupSharedMemory(CbPhys, *m_pCbShMem);
// Save Transmit Memory Structures Starting Addresses
pMem = AlignSharedMemory(&CbPhys, 0x100, *m_pCbShMem);
m_XmitUnCached = pMem;
m_XmitUnCachedPhys = *m_pCbShMem->PhysicalAddress();
NdisSetPhysicalAddressLow(m_XmitUnCachedPhys, CbPhys);
TRACE("First Transmit Block ptr=%x\n", m_XmitUnCached);
return NDIS_STATUS_SUCCESS;
}
////////////////////////////////////////////////////////////////////
// E100bexAdapter::DeleteSharedAdapterMemory
//
// This routine will delete the adapter memory shared with the NIC card
//
// Parameters:
//
// IRQL:
// PASSIVE_LEVEL
// Return Mode:
// Synchronous
//
// NOTE:
//
VOID E100bexAdapter::DeleteSharedAdapterMemory(void)
{
// Free any memory allocated for the shared receive structures (RFDs)
if ( m_pRxShMem )
{
TRACE("Freeing %d bytes m_pShMem\n", m_pRxShMem->Length() );
delete m_pRxShMem;
m_pRxShMem = NULL;
}
// Free any memory allocated for the Software transmit structures (SwTcbs)
TRACE("Freeing %d bytes XmitCached\n", m_XmitCachedSize);
delete m_XmitCached;
m_XmitCached = NULL;
// Free any memory allocated for the shared transmit structures (TCBs,
// TBDs, non transmit command blocks, etc.)
if ( m_pCbShMem )
{
TRACE("Freeing %d bytes XmitUnCached\n", m_pCbShMem->Length() );
delete m_pCbShMem;
m_pCbShMem = NULL;
m_XmitUnCached = NULL;
NdisSetPhysicalAddressLow(m_XmitUnCachedPhys,0);
}
// If this is a miniport driver we must free our allocated map registers
if (m_NumMapRegisters)
{
NdisMFreeMapRegisters(*this);
}
}
////////////////////////////////////////////////////////////////////
// E100bexAdapter::Halt
//
// MiniportHalt is a required function that deallocates resources when
// the NIC is removed and halts the NIC.
//
// Parameters:
// None
// IRQL:
// PASSIVE_LEVEL
// Return Mode:
// Synchronous
//
// NOTE: Miniports has no "unload" for the driver. The Halt() is the last
// function called into a miniport, so everything should be stopped
// and freed right here. The KNDIS framework takes care of destroying
// the adapter object itself, so this member function is merery required
// to undo things done by the Initialize() above - in the reverse order.
//
// Alternatevely, the driver writer can move all the deallocations to the
// destructor: the destructor will be called immediatelly after Halt()
// returns. Our sample follows this practice.
//
VOID E100bexAdapter::Halt(void)
{
TRACE("E100bexAdapter::Halt() Entered\n");
DisableCard();
}
////////////////////////////////////////////////////////////////////
// E100bexAdapter::DisableCard
//
// This routine will disable the card and disable the interrupt
//
// Parameters:
// IRQL:
// PASSIVE_LEVEL
// Return Mode:
// Synchronous
//
// NOTE:
// This routine will be called from Halt, and also from
// setOID_PNP_SET_POWER when transitioning from D0 to D3 power state.
//
VOID E100bexAdapter::DisableCard(void)
{
// Cancel our timer
if ( /*m_ResetInProgress && */!m_Timer.Cancel())
{
// A reset could be in progress here. We might want to add m_ResetInProgress
// BOOLEAN that we wait on if TRUE and the cancel timer fails, meaning that our
// Async callback routine will be called
}
// Disable the device's interrupt line.
m_pCard->DisableInterrupt();
// check to make sure there are no outstanding transmits
while(!m_TxQueue.IsEmpty())
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -