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

📄 usbnicadap.cpp

📁 driver studio 中的例子usbnic.rar
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// USBNICAdap.cpp: implementation of the USBNICAdapter class.
//====================================================================
//
// Compuware Corporation
// NuMega Lab
// 9 Townsend West
// Nashua, NH 03060  USA
//
// Copyright (c) 2002 Compuware Corporation. All Rights Reserved.
// Unpublished - rights reserved under the Copyright laws of the
// United States.
//
//====================================================================

#include "USBNICAdap.h"


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

USBNICAdapter::USBNICAdapter() :
		KNdisMiniAdapter(),
		m_HaltFlag(FALSE),
		m_RxIdleEvent(),
		m_RxIrpsOutstanding(0),
		m_RxIrpList()
{
}

USBNICAdapter::~USBNICAdapter()
{
}

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

////////////////////////////////////////////////////////////////////
// USBNICAdapter::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 USBNICAdapter::Initialize
				(IN OUT KNdisMedium& Medium, IN KNdisConfig& Config)
{
	TRACE("USBNICAdapter::Initialize() Entered\n");

	// Select our the Medium:
	if (! Medium.Select(USBNIC_MEDIUM_TYPE) )
		KNDIS_RETURN_ERROR (NDIS_STATUS_UNSUPPORTED_MEDIA);

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

	// Read some other config stuff from the Registry, e.g.
	// This is simply an example of how to do it. The value of uMode is never used
	ULONG	uMode;
	Config.Read(KNDIS_STRING_CONST("Mode"), &uMode);

	// Now let NDIS know about the BUS the NIC is on. Here's where the NDIS/Adapter-instance
	// handshake takes place. This should happen *before* allocating the h/w resources:
	SetAttributesEx(NdisInterfaceInternal,NDIS_ATTRIBUTE_DESERIALIZE);

	// NDIS WDM Specific
	//
	// Get the physical and "TopOfStack" device objects from NDIS for our WDM
	// device.  The "TopOfStack" device object is the device to which we will
	// submit IRPs to talk to the bus driver for our device.  We will use the PDO, along
	// with the "TopOfStack" device object to initialize our lower device object using
	// a DriverWorks's KPnpLowerDevice-derived class (such as KUsbLowerDevice).
	GetDeviceProperty(&m_PhysicalDeviceObject, NULL, &m_TopOfStackDeviceObject);

	// Initialize the IRP pools used to service the bus device for Send and Receive
	// NOTE: the wizard generates hard-coded values for the pool sizes. You
	// might want to use Config to read those values from the Registry, or use
	// some other way of allocating and handling IRPs, e.g. not using the pools at all.
	m_TxIrpPool.Initialize(m_TopOfStackDeviceObject, USBNIC_TX_IRPPOOL_SIZE);

	// Initialize a pool of receive Irps
	m_RxIrpPool.Initialize(m_TopOfStackDeviceObject, USBNIC_RX_IRPPOOL_SIZE);

	// Initialize a pool of control Irps
	m_CntrlIrpPool.Initialize(m_TopOfStackDeviceObject, USBNIC_CNTRL_IRPPOOL_SIZE);

	// Initialize the context block heap. We'll need one block per irp:
	m_ContextHeap.Initialize(USBNIC_TX_IRPPOOL_SIZE + USBNIC_RX_IRPPOOL_SIZE + USBNIC_CNTRL_IRPPOOL_SIZE);

	// Initialize the lower device object.  Since NDIS owns this device object, we
	// use the form of Initialize() that takes the "TopOfStackDevice" as the device to which
	// calls to the lower device should be directed in lieu of actually attaching to the
	// device stack.
	m_BusDevice.Initialize(m_TopOfStackDeviceObject, m_PhysicalDeviceObject);

	// Initialize the interface and pipe object and activate a device configuration.
	// NOTE: This is a SAMPLE code =>
	// TODO: Modify the code to match your device specification.
	m_Interface.Initialize(
		m_BusDevice,	// KUsbLowerDevice instance
		0,		// Interface Number
		1,		// Configuration Value
		0		// Initial Interface Alternate Setting
		);

	m_ReceivePipe.Initialize(m_BusDevice,0x81);
	m_SendPipe.Initialize(m_BusDevice,0x2);
	// The Interrupt pipe is NOT used
	m_InterruptPipe.Initialize(m_BusDevice,0x83,0x08);

	// download the firmware image and tickle the device
	if ( ConfigureAndProbeDevice() == STATUS_SUCCESS )
	{
		m_uMacOptions = NDIS_MAC_OPTION_RECEIVE_SERIALIZED  |
						NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |
						NDIS_MAC_OPTION_NO_LOOPBACK;

		// This sets up the Receive Frame Area including:
		// Allocating internal software Receive Frame Descriptors
		// Allocating packet and buffer pools
		// Initializing and chaining packets, software RFD, buffers
		// Maintains list of software RFD descriptors
		//
		// This driver's requirement is to further initialize the RFD's
		// see global template specialization DescriptorInitialize(..) which
		// is called for each descriptor
		m_pRxArea = new KNdisSystemReceiveArea< USBNICAdapter, WDM_RFD >(
			*this,
			USBNIC_RX_IRPPOOL_SIZE
			);
		m_pRxArea->Initialize();

		if (m_pRxArea == NULL)
			return STATUS_UNSUCCESSFUL;
	}
	else
		return STATUS_UNSUCCESSFUL;

#if BINARY_COMPATIBLE
	m_PacketIndicate.Initialize(this);
#endif

	return STATUS_SUCCESS;
}



////////////////////////////////////////////////////////////////////
// USBNICAdapter::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 inversed 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 USBNICAdapter::Halt(VOID)
{
	TRACE("USBNICAdapter::Halt() Entered\n");

	m_HaltFlag = TRUE;

	// Cancel all of the IRPs in the Rx IRP list.
	PWDM_RFD pWdmRfd = m_RxIrpList.Head();
	while (pWdmRfd)
	{
		if(pWdmRfd->m_Irp->CancelRoutine)
			IoCancelIrp(pWdmRfd->m_Irp);
		pWdmRfd = m_RxIrpList.Next(pWdmRfd);
	}

	// Wait for all of the Rx IRPs to be completed
	LARGE_INTEGER DueTime;
	DueTime.QuadPart = -(10000 * 20000);	// 20 seconds
	if ( m_RxIdleEvent.Wait() == FALSE )
	{
		ASSERT(!"All Rx IRPs were not accounted for");
	}

	// Wait for all of the Tx IRPs to be completed
	if ( m_TxIrpPool.Wait(1000) == STATUS_TIMEOUT )
	{
		ASSERT(!"All Tx IRPs were not accounted for");
	}

	// Wait for all of the Control IRPs to be completed
	if ( m_CntrlIrpPool.Wait(1000) == STATUS_TIMEOUT )
	{
		ASSERT(!"All Control IRPs were not accounted for");
	}

	m_BusDevice.DeActivateConfiguration();

	// Deallocate our receive area.
	TRACE("USBNICAdapter::Halt() Deleting Receive Area\n");
	delete m_pRxArea;
	m_pRxArea = NULL;

}

////////////////////////////////////////////////////////////////////
// USBNICAdapter::Reset
//
// MiniportReset is a required function that issues a hardware reset
// to the NIC and/or resets the driver's software state.
//
// Parameters:
//		AddressingReset
//			Points to a variable that MiniportReset sets to TRUE if the
//			NDIS library should call MiniportSetInformation to restore
//			addressing information to the current values.
// IRQL:
//		DISPATCH_LEVEL
// Return Mode:
//		Asynchronous
NDIS_STATUS USBNICAdapter::Reset
			(OUT PBOOLEAN AddressingReset)
{
	TRACE("USBNICAdapter::Reset() Entered\n");
	// TODO:	Reset the card
	// This may include sumiting an URB via the control pipe
	return NDIS_STATUS_SUCCESS;
}

////////////////////////////////////////////////////////////////////
// USBNICAdapter::Shutdown
//
// MiniportShutdown does nothing more than restore the NIC to its
// initial state (before the miniport's DriverEntry function runs)
//
// Parameters:
//		None
// IRQL:
//		If MiniportShutdown is called due to a user-initiated system shutdown,
//		it runs at IRQL PASSIVE_LEVEL in a system-thread context. If it is called
//		due to an unrecoverable error, MiniportShutdown runs at an arbitrary IRQL
//		and in the context of whatever component raised the error.
// Return Mode:
//		Synchronous
VOID USBNICAdapter::Shutdown(VOID)
{
	TRACE("USBNICAdapter::Shutdown() Entered\n");
	// This may include sumiting an URB via the control pipe
}

///////////////////////////////////////////////////////////////////////
// USBNICAdapter::CompletionTxRoutine
//
// Parameters:
// 	pIrp                 - irp being completed
// 	Context              - context passed when the irp had been submitted
// IRQL:
//		IRQL DISPATCH_LEVEL
// Returns:
// 	Usually, STATUS_MORE_PROCESSING_REQUIRED
// Comments:
// 	Processes asynchronous "send" IRP completions: this is a "HandleInterrupt()"
//  thing for NDIS WDM drivers.So, the logic is similar to HandleInterrupt():
//  If a pended Tx packet gets completed, return the packet to NDIS.
//  The important point is that if the the irps are be recycled back to the pools they
//  came from, STATUS_MORE_PROCESSING_REQUIRED should be returned to the system.
NTSTATUS USBNICAdapter::CompletionTxRoutine(PIRP pIrp, USBNICAdapter::IRP_CONTEXT* Context)
{
	//TRACE("USBNICAdapter::CompletionTxRoutine() Entered\n");

	NTSTATUS status;
	KIrp I(pIrp);
	status = I.Status();
	if(status)
		TRACE("IRP TX completion status = %08X\n",ULONG(I.Status()));

	if ( status == STATUS_DEVICE_DATA_ERROR )
	{
		// The device may have been disconnected
		// TODO: add code to handle your case
	}

	// Complete the packet we just processed
	SendComplete(Context->type.m_Packet, NDIS_STATUS_SUCCESS);

	// Put the Irp to put back to the Transmit Irp pool
	m_TxIrpPool.Free(I);

	// Destroy the associated Urb
	delete Context->m_pUrb;

	// Destroy the Context
	delete Context;

	if ( status != STATUS_DEVICE_DATA_ERROR )
	{
		// Update the transmit stats
		m_GenStats->xmit_ok++;

		// If Packets are in the Queue, dequeue them and send them
		KNdisPacket QueuedPacket = m_TxQueue.RemoveHead();
		while (QueuedPacket.IsValid())
		{
			TRACE("Sending Queued Tx Packets\n");
			// Retry to transmit previously queued packets
			NDIS_STATUS status = Transmit(QueuedPacket);
			if (status == NDIS_STATUS_RESOURCES)
			{
				// The packet can not be transmited because of a lack of resources
				// so requeue it for later
				m_TxQueue.InsertHead(QueuedPacket);
				QueuedPacket = NULL;
			}
			else
			{
				// Get the next queued packet
				QueuedPacket = m_TxQueue.RemoveHead();
			}
		}
	}

	return STATUS_MORE_PROCESSING_REQUIRED;
}

////////////////////////////////////////////////////////////////////
// USBNICAdapter::Send
//
// Transfers a protocol-supplied packet over the network
//
// Parameters:
//		Packet
//			Points to a packet descriptor specifying the data to be transmitted.
//		Flags
//			Specifies the packet flags, if any, set by the protocol.
// IRQL:
//		DISPATCH_LEVEL
// Return Mode:
//		Asynchronous
// NOTE:
//		The return code determines the ownership of the packet and further
//		interaction between NDIS and our driver. Specifically,
//
//      NDIS_STATUS_SUCCESS - Done with.
//      NDIS_STATUS_PENDING - We keep it until further notice.
//      NDIS_STATUS_RESOURCES - We didn't have the resouces *now*, so tell NDIS
//                              please hold it on until further notice.
//
NDIS_STATUS USBNICAdapter::Send(
			IN	PNDIS_PACKET			Packet,
			IN	UINT					Flags
			)
{
	//TRACE("USBNICAdapter::Send() Entered\n");
	NDIS_STATUS status = NDIS_STATUS_SUCCESS;
	// declare for convenience
	KNdisPacket pkt(Packet);

	// Attempt to transmit the packet
	status  = Transmit(Packet);
	if (status == NDIS_STATUS_RESOURCES)
	{
		// We can never return NDIS_STATUS_RESOURCES to NDIS, and must
		// instead queue This packet for the Deserialized Miniport
		m_TxQueue.InsertTail(Packet);
		TRACE("!!!Queueing packet\n");
	}

	// Deserialized drivers always return pending.
	return NDIS_STATUS_PENDING;
}

///////////////////////////////////////////////////////////////////////
// USBNICAdapter::Transmit
//
// Parameters:
//  Packet			- Packet supplied by NDIS to transmit
// IRQL:
//				<= DISPATCH_LEVEL
// Returns:
// 	NDIS_STATUS
// Comments:
// 	This routine compliments the Send() method. It does the necessary
//  checking and builds the URB that must be transmitted.
//
NDIS_STATUS USBNICAdapter::Transmit(PNDIS_PACKET Packet)
{
	PURB			pUrb;
	NDIS_STATUS		status = NDIS_STATUS_SUCCESS;

	//TRACE("USBNICAdapter::Transmit() Entered\n");

	// declare for convenience
	KNdisPacket pkt(Packet);
	KNdisBuffer buf = pkt.QueryFirstBuffer();

	// Get an available IRP from the Tx Irp pool
	KIrp I = m_TxIrpPool.Allocate();
	// Validate the Irp
	if (I.IsNull())
	{
		// Return failure so that send can queue the packet
		return NDIS_STATUS_RESOURCES;
	}

	// Allocate and initialize the context block:
	IRP_CONTEXT* Context = new (&m_ContextHeap) IRP_CONTEXT (this, Packet);
	// Validate the new context
	if(Context == NULL)
	{
		m_TxIrpPool.Free(I);
		// Return failure so that send can queue the packet
		return NDIS_STATUS_RESOURCES;
	}

	// Copy the data to be transmitted to the transfer buffer
	// Also calculate the new size
	int count = 2;
	int Size = 0;
	while (buf.IsValid())
	{
		Size = buf.Length();
		PUCHAR Buffer = (PUCHAR)buf.Address();

⌨️ 快捷键说明

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