1006 lines
24 KiB
C
1006 lines
24 KiB
C
/*++
|
||
|
||
Copyright (c) 1998-1999 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
main.c
|
||
|
||
Abstract:
|
||
|
||
This is the initialization file for the packet scheduler driver. This driver
|
||
is used to provide Local Traffic Control
|
||
|
||
Author:
|
||
|
||
Charlie Wickham (charlwi)
|
||
Rajesh Sundaram (rajeshsu) 01-Aug-1998.
|
||
|
||
Environment:
|
||
|
||
Kernel Mode
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "psched.h"
|
||
|
||
#pragma hdrstop
|
||
|
||
//
|
||
// number of characters that are appended to the RegistryPath when constructing
|
||
// the miniport device name
|
||
//
|
||
|
||
#define MPNAME_EXTENSION_SIZE ( 3 * sizeof(WCHAR))
|
||
|
||
/* External */
|
||
|
||
/* Static */
|
||
|
||
/* Forward */
|
||
|
||
NTSTATUS
|
||
DriverEntry(
|
||
IN PDRIVER_OBJECT DriverObject,
|
||
IN PUNICODE_STRING RegistryPath
|
||
);
|
||
|
||
NDIS_STATUS
|
||
InitializeNdisWrapper(
|
||
IN PDRIVER_OBJECT DriverObject,
|
||
IN PUNICODE_STRING RegistryPath
|
||
);
|
||
|
||
NDIS_STATUS
|
||
DoMiniportInit(
|
||
IN PDRIVER_OBJECT DriverObject,
|
||
IN PUNICODE_STRING RegistryPath
|
||
);
|
||
|
||
NDIS_STATUS
|
||
DoProtocolInit(IN PDRIVER_OBJECT DriverObject,
|
||
IN PUNICODE_STRING RegistryPath);
|
||
|
||
NTSTATUS
|
||
RegisterWithGpc();
|
||
|
||
NDIS_STATUS
|
||
InitializeScheduler(VOID);
|
||
|
||
VOID
|
||
InitializationCleanup(ULONG ShutdownMask);
|
||
|
||
VOID
|
||
GetTimerInfo (OUT PULONG TimerResolution);
|
||
|
||
VOID
|
||
PSUnload(IN PDRIVER_OBJECT pDriverObject);
|
||
|
||
/* End Forward */
|
||
|
||
#pragma NDIS_INIT_FUNCTION(DriverEntry)
|
||
#pragma NDIS_INIT_FUNCTION(InitializeNdisWrapper)
|
||
#pragma NDIS_INIT_FUNCTION(DoProtocolInit)
|
||
#pragma NDIS_INIT_FUNCTION(DoMiniportInit)
|
||
|
||
|
||
|
||
NTSTATUS
|
||
DriverEntry(
|
||
IN PDRIVER_OBJECT DriverObject,
|
||
IN PUNICODE_STRING RegistryPath
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This is the NT OS specific driver entry point. It kicks off initialization
|
||
for the driver. Currently, it is not PnP aware. Return from this routine
|
||
only after protocol registration, layered miniport registration, and both
|
||
miniport and higher layer protocol initialization has been done.
|
||
|
||
Arguments:
|
||
|
||
DriverObject - NT OS specific Object
|
||
RegistryPath - NT OS specific pointer to registry location for Psched
|
||
|
||
Return Values:
|
||
|
||
STATUS_SUCCESS
|
||
STATUS_FAILURE
|
||
|
||
--*/
|
||
{
|
||
NDIS_STATUS Status;
|
||
NTSTATUS NtStatus;
|
||
PVOID DumpData;
|
||
|
||
#if DBG
|
||
//
|
||
// announce the version
|
||
//
|
||
PsDbgOut(DBG_INFO, DBG_INIT, (VersionHerald, VersionNumber, VersionTimestamp));
|
||
#endif
|
||
|
||
//
|
||
// store a copy of our driver object. Used by NdisWriteEventLogEntry
|
||
//
|
||
PsDriverObject = DriverObject;
|
||
|
||
//
|
||
// Initialize the Driver refcount and DriverState
|
||
//
|
||
gDriverState = DriverStateLoaded;
|
||
PS_INIT_SPIN_LOCK(&DriverUnloadLock);
|
||
NdisInitializeEvent(&DriverUnloadEvent);
|
||
NdisSetEvent(&DriverUnloadEvent);
|
||
|
||
NdisInitializeEvent(&gZAWEvent);
|
||
|
||
//
|
||
// initialize global data and ndis request lookaside list
|
||
//
|
||
|
||
InitializeListHead(&AdapterList);
|
||
PS_INIT_SPIN_LOCK(&AdapterListLock);
|
||
|
||
InitializeListHead(&PsComponentList);
|
||
PS_INIT_SPIN_LOCK(&PsComponentListLock);
|
||
|
||
InitializeListHead(&PsProfileList);
|
||
PS_INIT_SPIN_LOCK(&PsProfileLock);
|
||
|
||
// Initialize scheduling components
|
||
|
||
InitializeTbConformer(&TbConformerInfo);
|
||
InitializeDrrSequencer(&DrrSequencerInfo);
|
||
InitializeTimeStmp(&TimeStmpInfo);
|
||
InitializeSchedulerStub(&SchedulerStubInfo);
|
||
|
||
//
|
||
// Add these components to the component list
|
||
//
|
||
|
||
InsertHeadList(&PsComponentList, &TbConformerInfo.Links );
|
||
InsertHeadList(&PsComponentList, &DrrSequencerInfo.Links );
|
||
InsertHeadList(&PsComponentList, &TimeStmpInfo.Links );
|
||
InsertHeadList(&PsComponentList, &SchedulerStubInfo.Links );
|
||
|
||
PsProcs.DropPacket = DropPacket;
|
||
PsProcs.NdisPipeHandle = GetNdisPipeHandle;
|
||
PsProcs.GetTimerInfo = GetTimerInfo;
|
||
|
||
//
|
||
// init the LLists for NdisRequest, MCM_VC, AND CLIENT_VC structs
|
||
// as these will be in high demand at times.
|
||
//
|
||
// Lookaside list depth is automatically managed by the executive.
|
||
//
|
||
|
||
NdisInitializeNPagedLookasideList(&NdisRequestLL,
|
||
NULL,
|
||
NULL,
|
||
0,
|
||
sizeof(PS_NDIS_REQUEST),
|
||
NdisRequestTag,
|
||
(USHORT)0);
|
||
|
||
NdisInitializeNPagedLookasideList(&GpcClientVcLL,
|
||
NULL,
|
||
NULL,
|
||
0,
|
||
sizeof( GPC_CLIENT_VC ),
|
||
GpcClientVcTag,
|
||
(USHORT)0);
|
||
|
||
//
|
||
// get driver wide configuration data from the registry
|
||
//
|
||
|
||
Status = PsReadDriverRegistryDataInit();
|
||
|
||
if(NT_SUCCESS(Status))
|
||
{
|
||
Status = PsReadDriverRegistryData();
|
||
|
||
if(!NT_SUCCESS(Status))
|
||
{
|
||
PsDbgOut(DBG_FAILURE, DBG_INIT, ("DriverEntry: PsReadDriverRegistryData - Status: 0x%x\n",
|
||
Status));
|
||
goto DriverEntryError;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
PsDbgOut(DBG_FAILURE, DBG_INIT, ("DriverEntry: PsReadDriverRegistryDataInit - Status: 0x%x\n",
|
||
Status));
|
||
goto DriverEntryError;
|
||
}
|
||
|
||
//
|
||
// Initialize space for WanLinks. Note that we don't need a lock to protect
|
||
// this table - We recognize lineups only on the NDISWAN-IP binding, so we
|
||
// can use the Adapter lock from the binding for synchronization.
|
||
//
|
||
|
||
PsAllocatePool(g_WanLinkTable,
|
||
WAN_TABLE_INITIAL_SIZE * sizeof(ULONG_PTR),
|
||
WanTableTag);
|
||
|
||
if(!g_WanLinkTable)
|
||
{
|
||
PsDbgOut(DBG_CRITICAL_ERROR,
|
||
DBG_INIT,
|
||
("[DriverEntry]: Cannot allocate memory for wanlinks \n"));
|
||
|
||
NdisWriteEventLogEntry(PsDriverObject,
|
||
EVENT_PS_NO_RESOURCES_FOR_INIT,
|
||
0,
|
||
0,
|
||
NULL,
|
||
0,
|
||
NULL);
|
||
|
||
goto DriverEntryError;
|
||
|
||
}
|
||
|
||
g_WanTableSize = WAN_TABLE_INITIAL_SIZE;
|
||
|
||
NdisZeroMemory(g_WanLinkTable, g_WanTableSize * sizeof(ULONG_PTR));
|
||
|
||
//
|
||
// The first entry is never used.
|
||
//
|
||
g_WanLinkTable[0] = (ULONG_PTR) -1;
|
||
|
||
g_NextWanIndex = 1;
|
||
|
||
|
||
|
||
//
|
||
// Register with the Generic Packet Classifier
|
||
//
|
||
|
||
NtStatus = RegisterWithGpc();
|
||
|
||
if(!NT_SUCCESS(NtStatus))
|
||
{
|
||
PsDbgOut(DBG_CRITICAL_ERROR,
|
||
DBG_INIT,
|
||
("RegisterWithGpc Failed! Status: 0x%x\n", NtStatus));
|
||
|
||
DumpData = &NtStatus;
|
||
NdisWriteEventLogEntry(PsDriverObject,
|
||
EVENT_PS_GPC_REGISTER_FAILED,
|
||
0,
|
||
0,
|
||
NULL,
|
||
sizeof(NTSTATUS),
|
||
DumpData);
|
||
|
||
goto DriverEntryError;
|
||
}
|
||
|
||
InitShutdownMask |= SHUTDOWN_DEREGISTER_GPC;
|
||
|
||
|
||
//
|
||
// initialize the wrapper with NDIS
|
||
//
|
||
|
||
Status = InitializeNdisWrapper( PsDriverObject, RegistryPath );
|
||
|
||
if ( !NT_SUCCESS( Status )) {
|
||
|
||
PsDbgOut(DBG_FAILURE, DBG_INIT,
|
||
("DriverEntry: InitializeNdisWrapper - Status: 0x%x\n", Status ));
|
||
|
||
NdisWriteEventLogEntry(PsDriverObject,
|
||
EVENT_PS_NO_RESOURCES_FOR_INIT,
|
||
0,
|
||
0,
|
||
NULL,
|
||
0,
|
||
NULL);
|
||
|
||
goto DriverEntryError;
|
||
}
|
||
|
||
//
|
||
// Initialize as a Miniport driver to the transports.
|
||
//
|
||
|
||
Status = DoMiniportInit(PsDriverObject, RegistryPath);
|
||
|
||
if (!NT_SUCCESS(Status)){
|
||
|
||
PsDbgOut(DBG_CRITICAL_ERROR,
|
||
DBG_INIT | DBG_MINIPORT,
|
||
("DoMiniportInit Failed! Status: 0x%x\n", Status));
|
||
|
||
DumpData = &Status;
|
||
NdisWriteEventLogEntry(PsDriverObject,
|
||
EVENT_PS_REGISTER_MINIPORT_FAILED,
|
||
0,
|
||
0,
|
||
NULL,
|
||
sizeof( Status ),
|
||
DumpData);
|
||
//
|
||
// Terminate the wrapper
|
||
//
|
||
|
||
NdisTerminateWrapper(MpWrapperHandle, NULL);
|
||
|
||
goto DriverEntryError;
|
||
}
|
||
|
||
InitShutdownMask |= SHUTDOWN_DEREGISTER_MINIPORT;
|
||
|
||
//
|
||
// do Protocol initialize first
|
||
//
|
||
|
||
Status = DoProtocolInit( PsDriverObject, RegistryPath );
|
||
|
||
if (!NT_SUCCESS(Status)){
|
||
|
||
PsDbgOut(DBG_CRITICAL_ERROR,
|
||
DBG_INIT | DBG_PROTOCOL,
|
||
("DoProtocolInit Failed! Status: 0x%x\n", Status));
|
||
|
||
DumpData = &Status;
|
||
NdisWriteEventLogEntry(PsDriverObject,
|
||
EVENT_PS_REGISTER_PROTOCOL_FAILED,
|
||
0,
|
||
0,
|
||
NULL,
|
||
sizeof( Status ),
|
||
DumpData);
|
||
|
||
NdisTerminateWrapper(MpWrapperHandle, NULL);
|
||
|
||
goto DriverEntryError;
|
||
}
|
||
|
||
InitShutdownMask |= SHUTDOWN_DEREGISTER_PROTOCOL;
|
||
|
||
NdisIMAssociateMiniport(LmDriverHandle, ClientProtocolHandle);
|
||
|
||
return (STATUS_SUCCESS);
|
||
|
||
//
|
||
// An error occured so we need to cleanup things
|
||
//
|
||
|
||
DriverEntryError:
|
||
InitializationCleanup(InitShutdownMask);
|
||
|
||
return (STATUS_UNSUCCESSFUL);
|
||
|
||
} // DriverEntry
|
||
|
||
|
||
|
||
NDIS_STATUS
|
||
InitializeNdisWrapper(
|
||
IN PDRIVER_OBJECT DriverObject,
|
||
IN PUNICODE_STRING RegistryPath
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Initialize the Ndis wrapper for both the miniport and protocol
|
||
sections. Since the name in the registry path is the Protocol
|
||
key (PSched), 'Mp' is appended onto the end to initialize
|
||
the wrapper for the miniport side of the PS
|
||
|
||
Arguments:
|
||
|
||
DriverObject - pointer to NT driver object
|
||
RegistryPath - pointer to path to driver params in registry
|
||
|
||
Return Values:
|
||
|
||
NDIS_STATUS_SUCCESS
|
||
NDIS_STATUS_BAD_VERSION
|
||
NDIS_STATUS_FAILURE
|
||
|
||
--*/
|
||
|
||
{
|
||
NDIS_STATUS Status;
|
||
USHORT MpDeviceNameLength;
|
||
NDIS_PHYSICAL_ADDRESS HighAddress = NDIS_PHYSICAL_ADDRESS_CONST( -1, -1 );
|
||
ULONG i;
|
||
PWCHAR RegistryPathBuffer;
|
||
|
||
//
|
||
// NT needs the MP name to be different from the protocol name
|
||
//
|
||
|
||
MpDeviceNameLength = RegistryPath->Length + MPNAME_EXTENSION_SIZE;
|
||
|
||
PsAllocatePool(RegistryPathBuffer,
|
||
MpDeviceNameLength,
|
||
PsMiscTag);
|
||
|
||
if ( RegistryPathBuffer == NULL ) {
|
||
|
||
PsDbgOut(DBG_CRITICAL_ERROR,
|
||
DBG_INIT,
|
||
("Can't allocate buffer for MP Device Name\n" ));
|
||
|
||
return NDIS_STATUS_RESOURCES;
|
||
}
|
||
|
||
//
|
||
// max length includes a trailing null, while length is just the string
|
||
//
|
||
|
||
PsMpName.MaximumLength = MpDeviceNameLength;
|
||
PsMpName.Length = PsMpName.MaximumLength - sizeof( WCHAR );
|
||
PsMpName.Buffer = RegistryPathBuffer;
|
||
|
||
NdisMoveMemory(PsMpName.Buffer,
|
||
RegistryPath->Buffer,
|
||
RegistryPath->Length );
|
||
|
||
i = RegistryPath->Length / sizeof( WCHAR );
|
||
RegistryPathBuffer[ i++ ] = L'M';
|
||
RegistryPathBuffer[ i++ ] = L'P';
|
||
RegistryPathBuffer[ i ] = L'\0';
|
||
|
||
NdisMInitializeWrapper(&MpWrapperHandle,
|
||
DriverObject,
|
||
&PsMpName,
|
||
NULL);
|
||
|
||
return NDIS_STATUS_SUCCESS;
|
||
} // InitializeNdisWrapper
|
||
|
||
|
||
NDIS_STATUS
|
||
DoMiniportInit(
|
||
IN PDRIVER_OBJECT DriverObject,
|
||
IN PUNICODE_STRING RegistryPath
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Name:
|
||
|
||
DoMiniportInit
|
||
|
||
Routine Description:
|
||
|
||
This routines registers Psched as a Miniport driver with the NDIS wrapper.
|
||
|
||
Arguments:
|
||
|
||
None
|
||
|
||
Return Values:
|
||
|
||
NDIS_STATUS_SUCCESS
|
||
NDIS_STATUS_BAD_VERSION
|
||
NDIS_STATUS_FAILURE
|
||
|
||
--*/
|
||
|
||
{
|
||
NDIS_MINIPORT_CHARACTERISTICS MiniportChars;
|
||
NDIS_STATUS Status;
|
||
|
||
MiniportChars.MajorNdisVersion = 5;
|
||
MiniportChars.MinorNdisVersion = 0;
|
||
|
||
MiniportChars.Reserved = 0;
|
||
MiniportChars.HaltHandler = MpHalt;
|
||
MiniportChars.InitializeHandler = MpInitialize;
|
||
MiniportChars.QueryInformationHandler = MpQueryInformation;
|
||
MiniportChars.ResetHandler = MpReset;
|
||
MiniportChars.SetInformationHandler = MpSetInformation;
|
||
MiniportChars.TransferDataHandler = MpTransferData;
|
||
|
||
//
|
||
// Unused handlers
|
||
//
|
||
|
||
MiniportChars.ReconfigureHandler = NULL;
|
||
MiniportChars.DisableInterruptHandler = NULL;
|
||
MiniportChars.EnableInterruptHandler = NULL;
|
||
MiniportChars.HandleInterruptHandler = NULL;
|
||
MiniportChars.ISRHandler = NULL;
|
||
|
||
//
|
||
// We will disable the check for hang timeout so we do not
|
||
// need a check for hang handler!
|
||
//
|
||
|
||
MiniportChars.CheckForHangHandler = NULL;
|
||
|
||
//
|
||
// Ndis 4.0 handlers. No regular send routine since we have a
|
||
// SendPackets handler.
|
||
//
|
||
|
||
MiniportChars.ReturnPacketHandler = MpReturnPacket;
|
||
MiniportChars.SendPacketsHandler = NULL;
|
||
MiniportChars.AllocateCompleteHandler = NULL;
|
||
MiniportChars.SendHandler = MpSend;
|
||
|
||
//
|
||
// 4.1 handlers
|
||
//
|
||
|
||
MiniportChars.CoCreateVcHandler = NULL;
|
||
MiniportChars.CoDeleteVcHandler = NULL;
|
||
MiniportChars.CoActivateVcHandler = NULL;
|
||
MiniportChars.CoDeactivateVcHandler = NULL;
|
||
MiniportChars.CoSendPacketsHandler = NULL;
|
||
MiniportChars.CoRequestHandler = NULL;
|
||
|
||
Status = NdisIMRegisterLayeredMiniport(MpWrapperHandle,
|
||
&MiniportChars,
|
||
sizeof(MiniportChars),
|
||
&LmDriverHandle);
|
||
|
||
//
|
||
// Hook the unload function
|
||
//
|
||
|
||
NdisMRegisterUnloadHandler(MpWrapperHandle, PSUnload);
|
||
|
||
return (Status);
|
||
} // DoMiniportInit
|
||
|
||
|
||
NDIS_STATUS
|
||
DoProtocolInit(
|
||
IN PDRIVER_OBJECT DriverObject,
|
||
IN PUNICODE_STRING RegistryPath
|
||
)
|
||
/*++
|
||
|
||
Routine Name:
|
||
|
||
DoProtocolInit
|
||
|
||
Routine Description:
|
||
|
||
This function registers the PS twice as a protocol - once for the protocol
|
||
section of the LM and the other for the CM section.
|
||
|
||
Arguments:
|
||
|
||
RegistryPath - pointer to our key in the registry
|
||
|
||
Return Values:
|
||
|
||
NDIS_STATUS_BAD_CHARACTERISTICS
|
||
NDIS_STATUS_BAD_VERSION
|
||
NDIS_STATUS_RESOURCES
|
||
NDIS_STATUS_SUCCESS
|
||
|
||
--*/
|
||
{
|
||
NDIS_PROTOCOL_CHARACTERISTICS ProtocolChars;
|
||
NDIS_STATUS Status;
|
||
NDIS_STRING PsName = NDIS_STRING_CONST( "PSched" );
|
||
|
||
//
|
||
// register the client portion of the PS
|
||
//
|
||
NdisZeroMemory(&ProtocolChars, sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
|
||
ProtocolChars.Name.Length = PsName.Length;
|
||
ProtocolChars.Name.Buffer = (PVOID)PsName.Buffer;
|
||
|
||
ProtocolChars.MajorNdisVersion = 5;
|
||
ProtocolChars.MinorNdisVersion = 0;
|
||
|
||
ProtocolChars.OpenAdapterCompleteHandler = ClLowerMpOpenAdapterComplete;
|
||
ProtocolChars.CloseAdapterCompleteHandler = ClLowerMpCloseAdapterComplete;
|
||
ProtocolChars.SendCompleteHandler = ClSendComplete;
|
||
ProtocolChars.TransferDataCompleteHandler = ClTransferDataComplete;
|
||
ProtocolChars.ResetCompleteHandler = ClResetComplete;
|
||
ProtocolChars.RequestCompleteHandler = ClRequestComplete;
|
||
ProtocolChars.ReceiveHandler = ClReceiveIndication;
|
||
ProtocolChars.ReceiveCompleteHandler = ClReceiveComplete;
|
||
ProtocolChars.StatusHandler = ClStatusIndication;
|
||
ProtocolChars.StatusCompleteHandler = ClStatusIndicationComplete;
|
||
ProtocolChars.ReceivePacketHandler = ClReceivePacket;
|
||
ProtocolChars.BindAdapterHandler = ClBindToLowerMp;
|
||
ProtocolChars.UnbindAdapterHandler = ClUnbindFromLowerMp;
|
||
ProtocolChars.UnloadHandler = ClUnloadProtocol;
|
||
ProtocolChars.CoSendCompleteHandler = ClCoSendComplete;
|
||
ProtocolChars.CoStatusHandler = ClCoStatus;
|
||
ProtocolChars.CoReceivePacketHandler = ClCoReceivePacket;
|
||
ProtocolChars.CoAfRegisterNotifyHandler = ClCoAfRegisterNotifyHandler;
|
||
ProtocolChars.PnPEventHandler = ClPnPEventHandler;
|
||
|
||
NdisRegisterProtocol(&Status,
|
||
&ClientProtocolHandle,
|
||
&ProtocolChars,
|
||
sizeof(NDIS_PROTOCOL_CHARACTERISTICS) + ProtocolChars.Name.Length);
|
||
|
||
return Status;
|
||
} // DoProtocolInit
|
||
|
||
|
||
NTSTATUS
|
||
RegisterWithGpc(
|
||
)
|
||
/*++
|
||
|
||
Routine Name:
|
||
|
||
RegisterWithGpc
|
||
|
||
Routine Description:
|
||
|
||
This function initializes the Gpc and gets its list of entry points.
|
||
Next, it registers the PS as a client of the GPC and gets a GPC client
|
||
handle. The PS must be a client of the GPC before it can classify packets.
|
||
|
||
Arguments:
|
||
|
||
GpcHandle - points to the location into which to write the handle which
|
||
the GPC gives out to represent this client.
|
||
|
||
Return Values:
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS Status;
|
||
|
||
//
|
||
// Function list for CF_INFO_QOS
|
||
//
|
||
GPC_CLIENT_FUNC_LIST GpcQosFuncList = {
|
||
GpcMajorVersion,
|
||
QosAddCfInfoComplete,
|
||
QosAddCfInfoNotify,
|
||
QosModifyCfInfoComplete,
|
||
QosModifyCfInfoNotify,
|
||
QosRemoveCfInfoComplete,
|
||
QosRemoveCfInfoNotify,
|
||
QosClGetCfInfoName
|
||
};
|
||
|
||
#if CBQ
|
||
//
|
||
// Function List for CF_INFO_CLASS_MAP
|
||
//
|
||
GPC_CLIENT_FUNC_LIST GpcClassMapFuncList = {
|
||
GpcMajorVersion,
|
||
ClassMapAddCfInfoComplete,
|
||
ClassMapAddCfInfoNotify,
|
||
ClassMapModifyCfInfoComplete,
|
||
ClassMapModifyCfInfoNotify,
|
||
ClassMapRemoveCfInfoComplete,
|
||
ClassMapRemoveCfInfoNotify,
|
||
ClassMapClGetCfInfoName
|
||
};
|
||
#endif
|
||
|
||
|
||
Status = GpcInitialize(&GpcEntries);
|
||
|
||
if(!NT_SUCCESS(Status))
|
||
{
|
||
return Status;
|
||
}
|
||
|
||
PsAssert(GpcEntries.GpcRegisterClientHandler);
|
||
|
||
//
|
||
// Register for CF_INFO_QOS
|
||
//
|
||
Status = GpcEntries.GpcRegisterClientHandler(GPC_CF_QOS,
|
||
GPC_FLAGS_FRAGMENT,
|
||
1,
|
||
&GpcQosFuncList,
|
||
(GPC_CLIENT_HANDLE)PS_QOS_CF,
|
||
&GpcQosClientHandle);
|
||
|
||
if (!NT_SUCCESS(Status))
|
||
{
|
||
GpcQosClientHandle = NULL;
|
||
return Status;
|
||
}
|
||
|
||
#if CBQ
|
||
//
|
||
// Register for the CF_INFO_CLASS_MAP
|
||
//
|
||
Status = GpcEntries.GpcRegisterClientHandler(
|
||
GPC_CF_CLASS_MAP,
|
||
GPC_FLAGS_FRAGMENT,
|
||
1,
|
||
&GpcClassMapFuncList,
|
||
(GPC_CLIENT_HANDLE)PS_CLASS_MAP_CF,
|
||
&GpcClassMapClientHandle);
|
||
|
||
if (!NT_SUCCESS(Status))
|
||
{
|
||
|
||
GpcClassMapClientHandle = NULL;
|
||
|
||
GpcEntries.GpcDeregisterClientHandler(GpcQosClientHandle);
|
||
|
||
GpcQosClientHandle = NULL;
|
||
|
||
return Status;
|
||
}
|
||
#endif
|
||
|
||
return Status;
|
||
}
|
||
|
||
|
||
VOID
|
||
InitializationCleanup(
|
||
ULONG ShutdownMask
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is responsible for cleaning up all allocated resources during
|
||
initialization
|
||
|
||
Arguments:
|
||
|
||
ShutdownMask - A Mask that indicates the items that need to be cleaned up.
|
||
|
||
Return Values:
|
||
|
||
None
|
||
|
||
--*/
|
||
|
||
{
|
||
NDIS_STATUS Status;
|
||
PPSI_INFO PsComponent;
|
||
PLIST_ENTRY NextProfile, NextComponent;
|
||
PPS_PROFILE PsProfile;
|
||
|
||
//
|
||
// Deregister the protocol; we should have no references that would cause
|
||
// this to pend
|
||
//
|
||
|
||
if(ShutdownMask & SHUTDOWN_DEREGISTER_MINIPORT){
|
||
|
||
if(LmDriverHandle){
|
||
|
||
NdisIMDeregisterLayeredMiniport(LmDriverHandle);
|
||
}
|
||
}
|
||
|
||
if(ShutdownMask & SHUTDOWN_DEREGISTER_PROTOCOL){
|
||
|
||
if(ClientProtocolHandle){
|
||
|
||
NdisDeregisterProtocol(&Status, ClientProtocolHandle);
|
||
|
||
if(Status != NDIS_STATUS_SUCCESS){
|
||
|
||
PsDbgOut(DBG_CRITICAL_ERROR,
|
||
DBG_INIT,
|
||
("[InitializationCleanup]: NdisDeregisterProtocol failed - Status 0x%x \n", Status));
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
//
|
||
// Deregister with the GPC
|
||
//
|
||
|
||
if(ShutdownMask & SHUTDOWN_DEREGISTER_GPC){
|
||
|
||
PsAssert(GpcEntries.GpcDeregisterClientHandler);
|
||
Status = GpcEntries.GpcDeregisterClientHandler(GpcQosClientHandle);
|
||
|
||
if(Status != GPC_STATUS_SUCCESS){
|
||
|
||
PsDbgOut(DBG_CRITICAL_ERROR,
|
||
DBG_INIT,
|
||
("[InitializationCleanup]: DeregisterGpc failed - Status %08X\n",
|
||
Status));
|
||
}
|
||
|
||
#if CBQ
|
||
Status = GpcEntries.GpcDeregisterClientHandler(GpcClassMapClientHandle);
|
||
|
||
if(Status != GPC_STATUS_SUCCESS)
|
||
{
|
||
PsDbgOut(DBG_CRITICAL_ERROR,
|
||
DBG_INIT,
|
||
("[InitializationCleanup]: DeregisterGpc failed - Status %08X\n",
|
||
Status));
|
||
}
|
||
#endif
|
||
}
|
||
|
||
//
|
||
// free the lookaside list resources
|
||
//
|
||
|
||
NdisDeleteNPagedLookasideList( &NdisRequestLL );
|
||
NdisDeleteNPagedLookasideList( &GpcClientVcLL );
|
||
|
||
//
|
||
// Free up the components
|
||
//
|
||
|
||
NextComponent = PsComponentList.Flink;
|
||
|
||
while ( NextComponent != &PsComponentList ) {
|
||
|
||
PsComponent = CONTAINING_RECORD( NextComponent, PSI_INFO, Links );
|
||
|
||
if(PsComponent->AddIn == TRUE) {
|
||
|
||
if(PsComponent->ComponentName.Buffer) {
|
||
|
||
PsFreePool(PsComponent->ComponentName.Buffer);
|
||
}
|
||
|
||
NextComponent = NextComponent->Flink;
|
||
|
||
PsFreePool(PsComponent);
|
||
}
|
||
else {
|
||
|
||
NextComponent = NextComponent->Flink;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Free up the Profiles
|
||
//
|
||
|
||
NextProfile = PsProfileList.Flink;
|
||
|
||
while( NextProfile != &PsProfileList) {
|
||
|
||
PsProfile = CONTAINING_RECORD(NextProfile, PS_PROFILE, Links);
|
||
|
||
if(PsProfile->ProfileName.Buffer) {
|
||
PsFreePool(PsProfile->ProfileName.Buffer);
|
||
}
|
||
|
||
NextProfile = NextProfile->Flink;
|
||
PsFreePool(PsProfile);
|
||
|
||
}
|
||
|
||
if(g_WanLinkTable)
|
||
{
|
||
PsFreePool(g_WanLinkTable);
|
||
}
|
||
|
||
if(PsMpName.Buffer)
|
||
PsFreePool(PsMpName.Buffer);
|
||
|
||
//
|
||
// Free the locks
|
||
//
|
||
|
||
NdisFreeSpinLock(&AdapterListLock);
|
||
NdisFreeSpinLock(&DriverUnloadLock);
|
||
NdisFreeSpinLock(&PsComponentListLock);
|
||
NdisFreeSpinLock(&PsProfileLock);
|
||
|
||
//
|
||
// TIMESTMP CLEANUP
|
||
// 1. Get rid of all the TS_ENTRYs. Release all the memory allocated for them.
|
||
// 2. Delete the spin lock.
|
||
//
|
||
UnloadConformr();
|
||
UnloadSequencer();
|
||
UnloadTimeStmp();
|
||
UnloadPsStub();
|
||
|
||
|
||
// Free the logging stuff //
|
||
#if DBG
|
||
|
||
SchedDeInitialize();
|
||
|
||
#endif
|
||
|
||
} // InitializationCleanup
|
||
|
||
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine returns the timer resolution to the requesting scheduling component.
|
||
|
||
Arguments:
|
||
|
||
TimerResolution - Pointer to location in which to return timer resolution.
|
||
|
||
Return Values:
|
||
|
||
None
|
||
|
||
--*/
|
||
VOID
|
||
GetTimerInfo (
|
||
OUT PULONG TimerResolution
|
||
)
|
||
|
||
{
|
||
// *TimerResolution = gTimerResolutionActualTime;
|
||
*TimerResolution = 0;
|
||
} // GetTimerInfo
|
||
|
||
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is the driver unload routine.
|
||
|
||
Arguments:
|
||
|
||
pDriverObject - The DriverObject that is being unloaded
|
||
|
||
Return Values:
|
||
|
||
None
|
||
|
||
--*/
|
||
|
||
VOID PSUnload(
|
||
IN PDRIVER_OBJECT pDriverObject)
|
||
{
|
||
PADAPTER Adapter;
|
||
PLIST_ENTRY NextAdapter;
|
||
NDIS_STATUS Status;
|
||
|
||
PsDbgOut(DBG_INFO,
|
||
DBG_INIT,
|
||
("[PsUnload]: pDriverObject: %x\n", pDriverObject));
|
||
|
||
PS_LOCK(&DriverUnloadLock);
|
||
|
||
gDriverState = DriverStateUnloading;
|
||
|
||
PS_UNLOCK(&DriverUnloadLock);
|
||
|
||
//
|
||
// We wait here till all binds are complete. All future binds are rejected
|
||
//
|
||
NdisWaitEvent(&DriverUnloadEvent, 0);
|
||
|
||
//
|
||
// we don't have to close opens from the unload handler. Our call
|
||
// to NdisDeRegisterProtocol will not return until it issues unbinds
|
||
//
|
||
|
||
InitializationCleanup( 0xffffffff );
|
||
|
||
PsDbgOut(DBG_INFO, DBG_INIT, (" Unloading psched....\n"));
|
||
|
||
return;
|
||
}
|
||
|
||
/* end main.c */
|
||
|