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

📄 e100bexadap.cpp

📁 nmE100bex网卡驱动程序
💻 CPP
📖 第 1 页 / 共 5 页
字号:
// E100bexAdap.cpp: implementation of the E100bexAdapter class.
//
//=============================================================================
//
// Compuware Corporation
// NuMega Lab
// 9 Townsend West
// Nashua, NH 03060  USA
//
// Copyright (c) 2000 Compuware Corporation. All Rights Reserved.
// Unpublished - rights reserved under the Copyright laws of the
// United States.
//
//=============================================================================
//
// Portions copied from Microsoft Windows 2000 DDK sample driver containing the
// following copyright
//
/****************************************************************************
** COPYRIGHT (C) 1994-1997 INTEL CORPORATION                               **
** DEVELOPED FOR MICROSOFT BY INTEL CORP., HILLSBORO, OREGON               **
** HTTP://WWW.INTEL.COM/                                                   **
** THIS FILE IS PART OF THE INTEL ETHEREXPRESS PRO/100B(TM) AND            **
** ETHEREXPRESS PRO/100+(TM) NDIS 5.0 MINIPORT SAMPLE DRIVER               **
****************************************************************************/


#include <kndis.h>
#include "E100bexInc.h"


//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////


E100bexAdapter::E100bexAdapter(void) :
	KNdisMiniAdapter(),
	m_CSRIoRange(),
	m_CSRMemoryRange(),
	m_Interrupt(),
	m_Timer(),
	m_NextFreeMapReg(0),
	m_OldestUsedMapReg(0),
	m_MaxPhysicalMappings(MAXIMUM_ETHERNET_PACKET_SIZE),
	m_pCard(NULL),
	m_pRxShMem(NULL),
	m_pCbShMem(NULL),
	m_pRxArea(NULL),
	m_TxCBList(),
	m_ActiveChainList(),
	m_CompletedChainList(),
	m_CoalesceBufferList(),
	m_TxQueue(),
	m_pTempHwDesc(NULL),
	m_XmitCached(NULL),
	m_XmitCachedSize(0)
{
}

E100bexAdapter::~E100bexAdapter(void)
{
	delete m_pRxArea;
	m_pRxArea = NULL;

	// Delete the shared memory we allocated in initialize
	DeleteSharedAdapterMemory();
	
	// Delete our card object, also allocated in initialize
	delete m_pCard;
}


////////////////////////////////////////////////////////////////////
// NDIS callback handlers
////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////
// E100bexAdapter::Initialize
//
// MiniportInitialize is a required function that sets up a NIC (or 
// virtual NIC) for network I/O operations, claims all hardware resources
// necessary to the NIC in the registry, and allocates resources the driver
// needs to carry out network I/O operations
//
// Parameters:
//		Medium	
//			Reference to KNdisMedium object that we have to set the medium 
//			type our NIC supports
//		Config
//			Reference to KNdisConfig object that we use to query various
//			configuration parameters
// IRQL: 
//		PASSIVE_LEVEL
// Return Mode:
//		Synchronous
//
// TODO: 
// 1) Select supported medium in Medium object
// 2) Read config parameters if any using Config object
// 3) Allocate h/w resources, pools, etc.
// 4) Register with NDIS using SetAttributes()
// 5) Register Shutdown Handler
// 6) Initialize and enable the NIC.
// NOTE: Be ready to process INTs even before the function exits
//
NDIS_STATUS E100bexAdapter::Initialize
				(IN OUT KNdisMedium& Medium, IN KNdisConfig& Config)
{
    NDIS_STATUS Status;

	TRACE("E100bexAdapter::Initialize() Entered\n");

	// Select our the Medium (pretending we are Ethernet):
	if (! Medium.Select(NdisMedium802_3) )
		KNDIS_RETURN_ERROR (NDIS_STATUS_UNSUPPORTED_MEDIA);

	// Create our initialization structure for registry overrides
	ADAPTER_INFO Ai;

	// Read some other config stuff from the Registry, e.g.
	if ((Status = ParseRegistryParameters(Config, Ai)) != NDIS_STATUS_SUCCESS)
		KNDIS_RETURN_ERROR (Status);

    // Initialize the number of Tcbs we will have in our queue
    // this is to work around limitations of the hardware and the S-bit
    m_NumTcb = m_RegNumTcb + 1;

	// Reset the Stats counters and other data members if any:
	m_Stats.Reset();

    // Now let NDIS know about the BUS the NIC is on, and any flags that we need set
	// for our adapter. Here's where the NDIS/Adapter-instance
	// handshake takes place. This should happen *before* allocating the h/w resources:
	SetAttributesEx(
		NdisInterfacePci,
        NDIS_ATTRIBUTE_DESERIALIZE | NDIS_ATTRIBUTE_BUS_MASTER);

	// Get h/w resources assigned to our adapter. 
	KNdisPnpResourceRequest request(Config);	// for NDIS 5

	// Our adapter needs the Interrupt, Port and Memory resources.
	// Get descriptors of those. We'll use the descriptors when
	// allocating h/w access objects such as KNdisIoRange and
	// KNdisInterrupt:
	KNdisResource<CmResourceTypeInterrupt>	Int(request);
	KNdisResource<CmResourceTypePort>		Port(request);

	// Look for the last memory bar with a length of 0x1000, as others might
	// be our flash address, a boot ROM address, or otherwise.
	ULONG Ordinal = 0;
	ULONG LastRightSizedOrdinal = 0;
	BOOLEAN Valid;
	do
	{
		KNdisResource<CmResourceTypeMemory>	Memory(request, Ordinal);
		Valid = Memory.IsValid();
		if (Valid && Memory.Length() == 0x1000)
			LastRightSizedOrdinal = Ordinal;
		Ordinal++;
	} while (Valid);
	KNdisResource<CmResourceTypeMemory>	Memory(request, LastRightSizedOrdinal);

	// Make sure the resources are defined in the Registry:
	if (!Int.IsValid())
		KNDIS_RETURN_ERROR (NDIS_STATUS_NOT_ACCEPTED);

	if (!Port.IsValid())
		KNDIS_RETURN_ERROR (NDIS_STATUS_NOT_ACCEPTED);

	if (!Memory.IsValid() || Memory.Length() != 0x1000)
		KNDIS_RETURN_ERROR (NDIS_STATUS_NOT_ACCEPTED);

	// Create the h/w access objects. 

	// Register our i/o ports:	

	m_CSRIoRange.Initialize(this, Port);

	if (! NT_SUCCESS(m_CSRIoRange.Status()))
		 KNDIS_RETURN_ERROR (m_CSRIoRange.Status());

	// Register our memory range:

	m_CSRMemoryRange.Initialize(this, Memory);

	if (! NT_SUCCESS(m_CSRMemoryRange.Status()))
		 KNDIS_RETURN_ERROR (m_CSRMemoryRange.Status());

	// Create an instance of our PCI information class to
	// query information from PCI configuration space
	E100bexPciInformation PciInfo(this);

	// Read the RevisionID
	m_AiRevID = PciInfo.ReadRevisionId();

	// Get the MemoryWriteInvalidateBit, then 'and' it with the value
	// we obtained from the registry to set the control
	Ai.MWIEnable = Ai.MWIEnable && PciInfo.GetMemoryWriteInvalidateBit();

	// Enable bus mastering if not already enabled
	if (FALSE == PciInfo.TestAndSetDmaMasterBit())
	{
		ASSERT(!"Bus master was not enabled\n");
	}

	// Read the subsystem vendor and subsystem device IDs
	PciInfo.ReadSubsystemId(m_AiSubVendor, m_AiSubDevice);

	// Create our "card" object. The real card class might want to use
	// references to m_Ports and m_Interrupt as constructor's parameters.
	m_pCard = new E100bexCard(*this, m_CSRMemoryRange, Ai);

	if ( NULL == m_pCard )
		 KNDIS_RETURN_ERROR ( NDIS_STATUS_RESOURCES );

	// Setup the shared adapter memory
	if ((Status = SetupSharedAdapterMemory()) != NDIS_STATUS_SUCCESS)
		KNDIS_RETURN_ERROR (Status);

    // Disable interrupts on the H/W before registering the interrupt with NDIS
    // Must SetupSharedAdapterMemory() before you can do this
	m_pCard->DisableInterrupt();

	// Register our interrupt: NOTE that we must register an interrupt object
	// as long as we expose Disable/EnableInterrupt() handlers. NDIS would use
	// them internally for KeSynchronizeExecition().
	m_Interrupt.Initialize(
		this,
		Int,
		NdisInterruptLatched);

	if (! NT_SUCCESS(m_Interrupt.Status()))
		 KNDIS_RETURN_ERROR (m_Interrupt.Status());

    // Setup and initialize the transmit structures
	SetupTransmitQueues();

    // set up our link indication variable
    // it doesn't matter what this is right now because it will be
    // set correctly if link fails
    m_LinkIsActive = NdisMediaStateConnected;

	// Set our power state to on.
    m_Power = NdisDeviceStateD0;

	// Initialize our timer object for use with our reset routine
	m_Timer.Initialize(this, KNDIS_MEMBER_CALLBACK(AsyncResetTimerCallback));
	
	// Set default filter and MAC options. In principle, we should also
	// relay that to our card...

	m_uMacOptions = NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |
					NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |
					NDIS_MAC_OPTION_NO_LOOPBACK;

	// Get network address (if any) from the Registry. If specified
	// it will be used instead of burned permanent address:
	if (Config.ReadNetworkAddress(m_AiNodeAddress) != NDIS_STATUS_SUCCESS)
		m_AiNodeAddress.Invalidate();

    // Check if there was a node address over-ride.  If there isn't then 
    // use the adapter's permanent node address as the "current" node address.
    // If a node address over-ride is present in the registry, then use
    // that override address as the node address instead of the permanent
    // address in the adapter's EEPROM
    if ( ! m_AiNodeAddress.IsValid() ) 
    {
        // No node address override so use the permanent address
        TRACE("E100bexAdapter::Initialize: No node address over-ride, using permanent address\n");

		// Read our node address from the EEPROM.
		ETHERNET_ADDRESS PermanentNodeAddress = m_pCard->ReadPermanentNodeAddress();

		m_AiNodeAddress = PermanentNodeAddress;
    }

    TRACE("E100bexAdapter::Initialize: Node Address is  %.2x %.2x %.2x %.2x %.2x %.2x\n",
        m_AiNodeAddress.m_bytes[0],
        m_AiNodeAddress.m_bytes[1],
        m_AiNodeAddress.m_bytes[2],
        m_AiNodeAddress.m_bytes[3],
        m_AiNodeAddress.m_bytes[4],
        m_AiNodeAddress.m_bytes[5]
        );

    // Validate the current node address (make sure its not a mulicast)
    if ((UCHAR) m_AiNodeAddress.m_bytes[0] & 1)
    {
        TRACE("E100bexAdapter::Initialize: Node address invalid -- its a MC address\n");

		KNDIS_RETURN_ERROR (NDIS_STATUS_FAILURE);
    }

	// Create a "receive frame" area.  Must do this before EnableCard
	if ( (Status = SetupReceiveQueues()) != NDIS_STATUS_SUCCESS )
		KNDIS_RETURN_ERROR (Status);

	// Initialize the hardware and enable the interrupt
	if ( (Status = EnableCard()) != NDIS_STATUS_SUCCESS )
		KNDIS_RETURN_ERROR (Status);

	return NDIS_STATUS_SUCCESS;
}


////////////////////////////////////////////////////////////////////
// E100bexAdapter::EnableCard
//
// This routine will initializate the hardware and
// enable the card's interrupt.
//
// Parameters:
// IRQL: 
//		PASSIVE_LEVEL
// Return Mode:
//		Synchronous
//
// NOTE:
//		This method MUST NOT be called until the following have been done
//			- The card object has been created
//			- The m_AiNodeAddress has been initialized with the address that
//				will be used by the card.
//			- SetupReceiveQueues has been called
//			- SetupTransmitQueues has been called 
//
//		This routine will be called from Initialize, and also from 
//		setOID_PNP_SET_POWER when transitioning from D3 to D0 power state.
//
NDIS_STATUS E100bexAdapter::EnableCard(void)
{
    NDIS_STATUS Status;

	// Test the adapter hardware
	if (( Status = m_pCard->SelfTest() ) != NDIS_STATUS_SUCCESS)
		KNDIS_RETURN_ERROR (Status);

	if ( !m_pCard->DetectPhy() )
		KNDIS_RETURN_ERROR (NDIS_STATUS_FAILURE);
		
	m_pCard->SetMcTimeoutFlag();

	// Start the card up. Interrupts are disabled...
	if ( ! m_pCard->Init(m_AiNodeAddress) )
		KNDIS_RETURN_ERROR (NDIS_STATUS_FAILURE);

	// Clear all counters on the hardware and in the driver
	m_pCard->ClearAllCounters();

	StartReceiveUnit();

	m_pCard->EnableInterrupt();

	return NDIS_STATUS_SUCCESS;
}


////////////////////////////////////////////////////////////////////
// E100bexAdapter::StartReceiveUnit
//
// This routine will start the receive unit on the NIC.
//
// Parameters:
// IRQL: 
//		PASSIVE_LEVEL
// Return Mode:
//		Synchronous
//
BOOLEAN E100bexAdapter::StartReceiveUnit()
{
    TRACE("E100bexAdapter::StartReceiveUnit\n");

    BOOLEAN Status = FALSE;

    // If the receiver is ready, then don't try to restart.
    if ( m_pCard->ReceiveUnitStarted() )
	{
        return Status;
	}

    TRACE2(("Re-starting the RU\n"))

	KNdisPacket Pkt(m_pRxArea->GetPacket());

	PHW_RFD pRfd = NULL;

	if( Pkt.IsValid() )
	{
		pRfd = reinterpret_cast<PHW_RFD>(m_pRxArea->GetDescriptor(Pkt));
		ASSERT( pRfd );
	}

    // Check to make sure that our RFD head is available.  If its not, then
    // we should process the rest of our receives
    if (( !Pkt.IsValid() || pRfd->RfdCbHeader.CbStatus))
    {
        Status = ProcessRXInterrupt();
    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -