⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 e100bexadap.cpp

📁 nmE100bex网卡驱动程序
💻 CPP
📖 第 1 页 / 共 5 页
字号:

#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 + -