📄 miniport.c
字号:
/*++
Copyright (c) Microsoft Corporation. All rights reserved.
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
PURPOSE.
Module Name:
Miniport.C
Abstract:
The purpose of this sample is to illustrate functionality of a deserialized
NDIS miniport driver without requiring a physical network adapter. This
sample is based on E100BEX sample present in the DDK. It is basically a
simplified version of E100bex driver. The driver can be installed either
manually using Add Hardware wizard as a root enumerated virtual miniport
driver or on a virtual bus (like toaster bus). Since the driver does not
interact with any hardware, it makes it very easy to understand the miniport
interface and the usage of various NDIS functions without the clutter of
hardware specific code normally found in a fully functional driver.
This sample provides an example of minimal driver intended for education
purposes. Neither the driver or it's sample test programs are intended
for use in a production environment.
Author: Eliyas Yakub (Nov 20th 2002)
Revision History:
Notes:
--*/
#include "miniport.h"
#pragma NDIS_INIT_FUNCTION(DriverEntry)
#pragma NDIS_PAGEABLE_FUNCTION(MPInitialize)
#pragma NDIS_PAGEABLE_FUNCTION(MPHalt)
#pragma NDIS_PAGEABLE_FUNCTION(MPUnload)
#ifdef NDIS51_MINIPORT
#pragma NDIS_PAGEABLE_FUNCTION(MPPnPEventNotify)
#endif
MP_GLOBAL_DATA GlobalData;
INT MPDebugLevel = MP_INFO;
NDIS_HANDLE NdisWrapperHandle;
NDIS_STATUS
DriverEntry(
PVOID DriverObject,
PVOID RegistryPath)
/*++
Routine Description:
In the context of its DriverEntry function, a miniport driver associates
itself with NDIS, specifies the NDIS version that it is using, and
registers its entry points.
Arguments:
PVOID DriverObject - pointer to the driver object.
PVOID RegistryPath - pointer to the driver registry path.
Return Value:
NDIS_STATUS_xxx code
--*/
{
NDIS_STATUS Status;
NDIS_MINIPORT_CHARACTERISTICS MPChar;
DEBUGP(MP_TRACE, ("---> DriverEntry built on "__DATE__" at "__TIME__ "\n"));
//
// Associate the miniport driver with NDIS by calling the
// NdisMInitializeWrapper. This function allocates a structure
// to represent this association, stores the miniport driver-
// specific information that the NDIS Library needs in this
// structure, and returns NdisWrapperHandle. The driver must retain and
// pass this handle to NdisMRegisterMiniport when it registers its entry
// points. NDIS will use NdisWrapperHandle to identify the miniport driver.
// The miniport driver must retain this handle but it should never attempt
// to access or interpret this handle.
//
NdisMInitializeWrapper(
&NdisWrapperHandle,
DriverObject,
RegistryPath,
NULL
);
if(!NdisWrapperHandle){
DEBUGP(MP_ERROR, ("NdisMInitializeWrapper failed\n"));
return NDIS_STATUS_FAILURE;
}
//
// Fill in the Miniport characteristics structure with the version numbers
// and the entry points for driver-supplied MiniportXxx
//
NdisZeroMemory(&MPChar, sizeof(MPChar));
//
// The NDIS version number, in addition to being included in
// NDIS_MINIPORT_CHARACTERISTICS, must also be specified when the
// miniport driver source code is compiled.
//
MPChar.MajorNdisVersion = MP_NDIS_MAJOR_VERSION;
MPChar.MinorNdisVersion = MP_NDIS_MINOR_VERSION;
MPChar.InitializeHandler = MPInitialize;
MPChar.HaltHandler = MPHalt;
MPChar.SetInformationHandler = MPSetInformation;
MPChar.QueryInformationHandler = MPQueryInformation;
MPChar.SendPacketsHandler = MPSendPackets;
MPChar.ReturnPacketHandler = MPReturnPacket;
MPChar.ResetHandler = MPReset;
MPChar.CheckForHangHandler = MPCheckForHang; //optional
MPChar.AllocateCompleteHandler = MPAllocateComplete;//optional
MPChar.DisableInterruptHandler = MPDisableInterrupt; //optional
MPChar.EnableInterruptHandler = MPEnableInterrupt; //optional
MPChar.HandleInterruptHandler = MPHandleInterrupt;
MPChar.ISRHandler = MPIsr;
#ifdef NDIS51_MINIPORT
MPChar.CancelSendPacketsHandler = MPCancelSendPackets;
MPChar.PnPEventNotifyHandler = MPPnPEventNotify;
MPChar.AdapterShutdownHandler = MPShutdown;
#endif
DEBUGP(MP_LOUD, ("Calling NdisMRegisterMiniport...\n"));
//
// Registers miniport's entry points with the NDIS library as the first
// step in NIC driver initialization. The NDIS will call the
// MiniportInitialize when the device is actually started by the PNP
// manager.
//
Status = NdisMRegisterMiniport(
NdisWrapperHandle,
&MPChar,
sizeof(NDIS_MINIPORT_CHARACTERISTICS));
if (Status != NDIS_STATUS_SUCCESS) {
DEBUGP(MP_ERROR, ("Status = 0x%08x\n", Status));
NdisTerminateWrapper(NdisWrapperHandle, NULL);
} else {
//
// Initialize the global variables. The ApaterList in the
// GloablData structure is used to track the multiple instances
// of the same adapter. Make sure you do that before registering
// the unload handler.
//
NdisAllocateSpinLock(&GlobalData.Lock);
NdisInitializeListHead(&GlobalData.AdapterList);
//
// Register an Unload handler for global data cleanup. The unload handler
// has a more global scope, whereas the scope of the MiniportHalt function
// is restricted to a particular miniport instance.
//
NdisMRegisterUnloadHandler(NdisWrapperHandle, MPUnload);
}
DEBUGP(MP_TRACE, ("<--- DriverEntry\n"));
return Status;
}
NDIS_STATUS
MPInitialize(
OUT PNDIS_STATUS OpenErrorStatus,
OUT PUINT SelectedMediumIndex,
IN PNDIS_MEDIUM MediumArray,
IN UINT MediumArraySize,
IN NDIS_HANDLE MiniportAdapterHandle,
IN NDIS_HANDLE WrapperConfigurationContext)
/*++
Routine Description:
The MiniportInitialize function 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.
MiniportInitialize runs at IRQL = PASSIVE_LEVEL.
Arguments:
Return Value:
NDIS_STATUS_xxx code
--*/
{
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
PMP_ADAPTER Adapter=NULL;
NDIS_HANDLE ConfigurationHandle;
UINT index;
DEBUGP(MP_TRACE, ("---> MPInitialize\n"));
do {
//
// Check to see if our media type exists in an array of supported
// media types provided by NDIS.
//
for(index = 0; index < MediumArraySize; ++index)
{
if(MediumArray[index] == NIC_MEDIA_TYPE) {
break;
}
}
if(index == MediumArraySize)
{
DEBUGP(MP_ERROR, ("Expected media is not in MediumArray.\n"));
Status = NDIS_STATUS_UNSUPPORTED_MEDIA;
break;
}
//
// Set the index value as the selected medium for our device.
//
*SelectedMediumIndex = index;
//
// Allocate adapter context structure and initialize all the
// memory resources for sending and receiving packets.
//
Status = NICAllocAdapter(&Adapter);
if(Status != NDIS_STATUS_SUCCESS)
{
break;
}
MP_INC_REF(Adapter);
//
// NdisMGetDeviceProperty function enables us to get the:
// PDO - created by the bus driver to represent our device.
// FDO - created by NDIS to represent our miniport as a function driver.
// NextDeviceObject - deviceobject of another driver (filter)
// attached to us at the bottom.
// In a pure NDIS miniport driver, there is no use for this
// information, but a NDISWDM driver would need to know this so that it
// can transfer packets to the lower WDM stack using IRPs.
//
NdisMGetDeviceProperty(MiniportAdapterHandle,
&Adapter->Pdo,
&Adapter->Fdo,
&Adapter->NextDeviceObject,
NULL,
NULL);
Adapter->AdapterHandle = MiniportAdapterHandle;
//
// Read Advanced configuration information from the registry
//
Status = NICReadRegParameters(Adapter, WrapperConfigurationContext);
if(Status != NDIS_STATUS_SUCCESS)
{
break;
}
//
// Inform NDIS about significant features of the NIC. A
// MiniportInitialize function must call NdisMSetAttributesEx
// (or NdisMSetAttributes) before calling any other NdisMRegisterXxx
// or NdisXxx function that claims hardware resources. If your
// hardware supports busmaster DMA, you must specify NDIS_ATTRIBUTE_BUS_MASTER.
// If this is NDIS51 miniport, it should use safe APIs. But if this
// is NDIS 5.0, the driver claim to use safe APIs by setting
// NDIS_ATTRIBUTE_USES_SAFE_BUFFER_APIS
//
NdisMSetAttributesEx(
MiniportAdapterHandle,
(NDIS_HANDLE) Adapter,
0,
#ifdef NDIS50_MINIPORT
NDIS_ATTRIBUTE_DESERIALIZE|
NDIS_ATTRIBUTE_USES_SAFE_BUFFER_APIS,
#else
NDIS_ATTRIBUTE_DESERIALIZE,
#endif
NIC_INTERFACE_TYPE);
//
// Get the Adapter Resources & Initialize the hardware.
//
Status = NICInitializeAdapter(Adapter, WrapperConfigurationContext);
if(Status != NDIS_STATUS_SUCCESS) {
Status = NDIS_STATUS_FAILURE;
break;
}
//
// Setup a timer function for Receive Indication
//
NdisInitializeTimer(
&Adapter->RecvTimer,
(PNDIS_TIMER_FUNCTION)NICIndicateReceiveTimerDpc,
(PVOID)Adapter);
//
// Setup a timer function for use with our MPReset routine.
//
NdisInitializeTimer(
&Adapter->ResetTimer,
(PNDIS_TIMER_FUNCTION) NICResetCompleteTimerDpc,
(PVOID) Adapter);
NdisInitializeEvent(&Adapter->RemoveEvent);
} while(FALSE);
if(Status == NDIS_STATUS_SUCCESS) {
//
// Attach this Adapter to the global list of adapters managed by
// this driver.
//
NICAttachAdapter(Adapter);
//
// Create an IOCTL interface
//
NICRegisterDevice();
}
else {
if(Adapter){
MP_DEC_REF(Adapter);
NICFreeAdapter(Adapter);
}
}
DEBUGP(MP_TRACE, ("<--- MPInitialize Status = 0x%08x%\n", Status));
return Status;
}
VOID
MPHalt(
IN NDIS_HANDLE MiniportAdapterContext
)
/*++
Routine Description:
Halt handler is called when NDIS receives IRP_MN_STOP_DEVICE,
IRP_MN_SUPRISE_REMOVE or IRP_MN_REMOVE_DEVICE requests from the
PNP manager. Here, the driver should free all the resources acquired
in MiniportInitialize and stop access to the hardware. NDIS will
not submit any further request once this handler is invoked.
1) Free and unmap all I/O resources.
2) Disable interrupt and deregister interrupt handler.
3) Deregister shutdown handler regsitered by
NdisMRegisterAdapterShutdownHandler .
4) Cancel all queued up timer callbacks.
5) Finally wait indefinitely for all the outstanding receive
packets indicated to the protocol to return.
MiniportHalt runs at IRQL = PASSIVE_LEVEL.
Arguments:
MiniportAdapterContext Pointer to the Adapter
Return Value:
None.
--*/
{
PMP_ADAPTER Adapter = (PMP_ADAPTER) MiniportAdapterContext;
BOOLEAN bDone=TRUE;
BOOLEAN bCancelled;
LONG nHaltCount = 0, Count;
MP_SET_FLAG(Adapter, fMP_ADAPTER_HALT_IN_PROGRESS);
DEBUGP(MP_TRACE, ("---> MPHalt\n"));
//
// Call Shutdown handler to disable interrupt and turn the hardware off
// by issuing a full reset
//
#if defined(NDIS50_MINIPORT)
MPShutdown(MiniportAdapterContext);
#elif defined(NDIS51_MINIPORT)
//
// On XP and later, NDIS notifies our PNP event handler the
// reason for calling Halt. So before accessing the device, check to see
// if the device is surprise removed, if so don't bother calling
// the shutdown handler to stop the hardware because it doesn't exist.
//
if(!MP_TEST_FLAG(Adapter, fMP_ADAPTER_SURPRISE_REMOVED)) {
MPShutdown(MiniportAdapterContext);
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -