Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1005 lines
24 KiB

  1. /*++
  2. Copyright (c) 1998-1999 Microsoft Corporation
  3. Module Name:
  4. main.c
  5. Abstract:
  6. This is the initialization file for the packet scheduler driver. This driver
  7. is used to provide Local Traffic Control
  8. Author:
  9. Charlie Wickham (charlwi)
  10. Rajesh Sundaram (rajeshsu) 01-Aug-1998.
  11. Environment:
  12. Kernel Mode
  13. Revision History:
  14. --*/
  15. #include "psched.h"
  16. #pragma hdrstop
  17. //
  18. // number of characters that are appended to the RegistryPath when constructing
  19. // the miniport device name
  20. //
  21. #define MPNAME_EXTENSION_SIZE ( 3 * sizeof(WCHAR))
  22. /* External */
  23. /* Static */
  24. /* Forward */
  25. NTSTATUS
  26. DriverEntry(
  27. IN PDRIVER_OBJECT DriverObject,
  28. IN PUNICODE_STRING RegistryPath
  29. );
  30. NDIS_STATUS
  31. InitializeNdisWrapper(
  32. IN PDRIVER_OBJECT DriverObject,
  33. IN PUNICODE_STRING RegistryPath
  34. );
  35. NDIS_STATUS
  36. DoMiniportInit(
  37. IN PDRIVER_OBJECT DriverObject,
  38. IN PUNICODE_STRING RegistryPath
  39. );
  40. NDIS_STATUS
  41. DoProtocolInit(IN PDRIVER_OBJECT DriverObject,
  42. IN PUNICODE_STRING RegistryPath);
  43. NTSTATUS
  44. RegisterWithGpc();
  45. NDIS_STATUS
  46. InitializeScheduler(VOID);
  47. VOID
  48. InitializationCleanup(ULONG ShutdownMask);
  49. VOID
  50. GetTimerInfo (OUT PULONG TimerResolution);
  51. VOID
  52. PSUnload(IN PDRIVER_OBJECT pDriverObject);
  53. /* End Forward */
  54. #pragma NDIS_INIT_FUNCTION(DriverEntry)
  55. #pragma NDIS_INIT_FUNCTION(InitializeNdisWrapper)
  56. #pragma NDIS_INIT_FUNCTION(DoProtocolInit)
  57. #pragma NDIS_INIT_FUNCTION(DoMiniportInit)
  58. NTSTATUS
  59. DriverEntry(
  60. IN PDRIVER_OBJECT DriverObject,
  61. IN PUNICODE_STRING RegistryPath
  62. )
  63. /*++
  64. Routine Description:
  65. This is the NT OS specific driver entry point. It kicks off initialization
  66. for the driver. Currently, it is not PnP aware. Return from this routine
  67. only after protocol registration, layered miniport registration, and both
  68. miniport and higher layer protocol initialization has been done.
  69. Arguments:
  70. DriverObject - NT OS specific Object
  71. RegistryPath - NT OS specific pointer to registry location for Psched
  72. Return Values:
  73. STATUS_SUCCESS
  74. STATUS_FAILURE
  75. --*/
  76. {
  77. NDIS_STATUS Status;
  78. NTSTATUS NtStatus;
  79. PVOID DumpData;
  80. #if DBG
  81. //
  82. // announce the version
  83. //
  84. PsDbgOut(DBG_INFO, DBG_INIT, (VersionHerald, VersionNumber, VersionTimestamp));
  85. #endif
  86. //
  87. // store a copy of our driver object. Used by NdisWriteEventLogEntry
  88. //
  89. PsDriverObject = DriverObject;
  90. //
  91. // Initialize the Driver refcount and DriverState
  92. //
  93. gDriverState = DriverStateLoaded;
  94. PS_INIT_SPIN_LOCK(&DriverUnloadLock);
  95. NdisInitializeEvent(&DriverUnloadEvent);
  96. NdisSetEvent(&DriverUnloadEvent);
  97. NdisInitializeEvent(&gZAWEvent);
  98. //
  99. // initialize global data and ndis request lookaside list
  100. //
  101. InitializeListHead(&AdapterList);
  102. PS_INIT_SPIN_LOCK(&AdapterListLock);
  103. InitializeListHead(&PsComponentList);
  104. PS_INIT_SPIN_LOCK(&PsComponentListLock);
  105. InitializeListHead(&PsProfileList);
  106. PS_INIT_SPIN_LOCK(&PsProfileLock);
  107. // Initialize scheduling components
  108. InitializeTbConformer(&TbConformerInfo);
  109. InitializeDrrSequencer(&DrrSequencerInfo);
  110. InitializeTimeStmp(&TimeStmpInfo);
  111. InitializeSchedulerStub(&SchedulerStubInfo);
  112. //
  113. // Add these components to the component list
  114. //
  115. InsertHeadList(&PsComponentList, &TbConformerInfo.Links );
  116. InsertHeadList(&PsComponentList, &DrrSequencerInfo.Links );
  117. InsertHeadList(&PsComponentList, &TimeStmpInfo.Links );
  118. InsertHeadList(&PsComponentList, &SchedulerStubInfo.Links );
  119. PsProcs.DropPacket = DropPacket;
  120. PsProcs.NdisPipeHandle = GetNdisPipeHandle;
  121. PsProcs.GetTimerInfo = GetTimerInfo;
  122. //
  123. // init the LLists for NdisRequest, MCM_VC, AND CLIENT_VC structs
  124. // as these will be in high demand at times.
  125. //
  126. // Lookaside list depth is automatically managed by the executive.
  127. //
  128. NdisInitializeNPagedLookasideList(&NdisRequestLL,
  129. NULL,
  130. NULL,
  131. 0,
  132. sizeof(PS_NDIS_REQUEST),
  133. NdisRequestTag,
  134. (USHORT)0);
  135. NdisInitializeNPagedLookasideList(&GpcClientVcLL,
  136. NULL,
  137. NULL,
  138. 0,
  139. sizeof( GPC_CLIENT_VC ),
  140. GpcClientVcTag,
  141. (USHORT)0);
  142. //
  143. // get driver wide configuration data from the registry
  144. //
  145. Status = PsReadDriverRegistryDataInit();
  146. if(NT_SUCCESS(Status))
  147. {
  148. Status = PsReadDriverRegistryData();
  149. if(!NT_SUCCESS(Status))
  150. {
  151. PsDbgOut(DBG_FAILURE, DBG_INIT, ("DriverEntry: PsReadDriverRegistryData - Status: 0x%x\n",
  152. Status));
  153. goto DriverEntryError;
  154. }
  155. }
  156. else
  157. {
  158. PsDbgOut(DBG_FAILURE, DBG_INIT, ("DriverEntry: PsReadDriverRegistryDataInit - Status: 0x%x\n",
  159. Status));
  160. goto DriverEntryError;
  161. }
  162. //
  163. // Initialize space for WanLinks. Note that we don't need a lock to protect
  164. // this table - We recognize lineups only on the NDISWAN-IP binding, so we
  165. // can use the Adapter lock from the binding for synchronization.
  166. //
  167. PsAllocatePool(g_WanLinkTable,
  168. WAN_TABLE_INITIAL_SIZE * sizeof(ULONG_PTR),
  169. WanTableTag);
  170. if(!g_WanLinkTable)
  171. {
  172. PsDbgOut(DBG_CRITICAL_ERROR,
  173. DBG_INIT,
  174. ("[DriverEntry]: Cannot allocate memory for wanlinks \n"));
  175. NdisWriteEventLogEntry(PsDriverObject,
  176. EVENT_PS_NO_RESOURCES_FOR_INIT,
  177. 0,
  178. 0,
  179. NULL,
  180. 0,
  181. NULL);
  182. goto DriverEntryError;
  183. }
  184. g_WanTableSize = WAN_TABLE_INITIAL_SIZE;
  185. NdisZeroMemory(g_WanLinkTable, g_WanTableSize * sizeof(ULONG_PTR));
  186. //
  187. // The first entry is never used.
  188. //
  189. g_WanLinkTable[0] = (ULONG_PTR) -1;
  190. g_NextWanIndex = 1;
  191. //
  192. // Register with the Generic Packet Classifier
  193. //
  194. NtStatus = RegisterWithGpc();
  195. if(!NT_SUCCESS(NtStatus))
  196. {
  197. PsDbgOut(DBG_CRITICAL_ERROR,
  198. DBG_INIT,
  199. ("RegisterWithGpc Failed! Status: 0x%x\n", NtStatus));
  200. DumpData = &NtStatus;
  201. NdisWriteEventLogEntry(PsDriverObject,
  202. EVENT_PS_GPC_REGISTER_FAILED,
  203. 0,
  204. 0,
  205. NULL,
  206. sizeof(NTSTATUS),
  207. DumpData);
  208. goto DriverEntryError;
  209. }
  210. InitShutdownMask |= SHUTDOWN_DEREGISTER_GPC;
  211. //
  212. // initialize the wrapper with NDIS
  213. //
  214. Status = InitializeNdisWrapper( PsDriverObject, RegistryPath );
  215. if ( !NT_SUCCESS( Status )) {
  216. PsDbgOut(DBG_FAILURE, DBG_INIT,
  217. ("DriverEntry: InitializeNdisWrapper - Status: 0x%x\n", Status ));
  218. NdisWriteEventLogEntry(PsDriverObject,
  219. EVENT_PS_NO_RESOURCES_FOR_INIT,
  220. 0,
  221. 0,
  222. NULL,
  223. 0,
  224. NULL);
  225. goto DriverEntryError;
  226. }
  227. //
  228. // Initialize as a Miniport driver to the transports.
  229. //
  230. Status = DoMiniportInit(PsDriverObject, RegistryPath);
  231. if (!NT_SUCCESS(Status)){
  232. PsDbgOut(DBG_CRITICAL_ERROR,
  233. DBG_INIT | DBG_MINIPORT,
  234. ("DoMiniportInit Failed! Status: 0x%x\n", Status));
  235. DumpData = &Status;
  236. NdisWriteEventLogEntry(PsDriverObject,
  237. EVENT_PS_REGISTER_MINIPORT_FAILED,
  238. 0,
  239. 0,
  240. NULL,
  241. sizeof( Status ),
  242. DumpData);
  243. //
  244. // Terminate the wrapper
  245. //
  246. NdisTerminateWrapper(MpWrapperHandle, NULL);
  247. goto DriverEntryError;
  248. }
  249. InitShutdownMask |= SHUTDOWN_DEREGISTER_MINIPORT;
  250. //
  251. // do Protocol initialize first
  252. //
  253. Status = DoProtocolInit( PsDriverObject, RegistryPath );
  254. if (!NT_SUCCESS(Status)){
  255. PsDbgOut(DBG_CRITICAL_ERROR,
  256. DBG_INIT | DBG_PROTOCOL,
  257. ("DoProtocolInit Failed! Status: 0x%x\n", Status));
  258. DumpData = &Status;
  259. NdisWriteEventLogEntry(PsDriverObject,
  260. EVENT_PS_REGISTER_PROTOCOL_FAILED,
  261. 0,
  262. 0,
  263. NULL,
  264. sizeof( Status ),
  265. DumpData);
  266. NdisTerminateWrapper(MpWrapperHandle, NULL);
  267. goto DriverEntryError;
  268. }
  269. InitShutdownMask |= SHUTDOWN_DEREGISTER_PROTOCOL;
  270. NdisIMAssociateMiniport(LmDriverHandle, ClientProtocolHandle);
  271. return (STATUS_SUCCESS);
  272. //
  273. // An error occured so we need to cleanup things
  274. //
  275. DriverEntryError:
  276. InitializationCleanup(InitShutdownMask);
  277. return (STATUS_UNSUCCESSFUL);
  278. } // DriverEntry
  279. NDIS_STATUS
  280. InitializeNdisWrapper(
  281. IN PDRIVER_OBJECT DriverObject,
  282. IN PUNICODE_STRING RegistryPath
  283. )
  284. /*++
  285. Routine Description:
  286. Initialize the Ndis wrapper for both the miniport and protocol
  287. sections. Since the name in the registry path is the Protocol
  288. key (PSched), 'Mp' is appended onto the end to initialize
  289. the wrapper for the miniport side of the PS
  290. Arguments:
  291. DriverObject - pointer to NT driver object
  292. RegistryPath - pointer to path to driver params in registry
  293. Return Values:
  294. NDIS_STATUS_SUCCESS
  295. NDIS_STATUS_BAD_VERSION
  296. NDIS_STATUS_FAILURE
  297. --*/
  298. {
  299. NDIS_STATUS Status;
  300. USHORT MpDeviceNameLength;
  301. NDIS_PHYSICAL_ADDRESS HighAddress = NDIS_PHYSICAL_ADDRESS_CONST( -1, -1 );
  302. ULONG i;
  303. PWCHAR RegistryPathBuffer;
  304. //
  305. // NT needs the MP name to be different from the protocol name
  306. //
  307. MpDeviceNameLength = RegistryPath->Length + MPNAME_EXTENSION_SIZE;
  308. PsAllocatePool(RegistryPathBuffer,
  309. MpDeviceNameLength,
  310. PsMiscTag);
  311. if ( RegistryPathBuffer == NULL ) {
  312. PsDbgOut(DBG_CRITICAL_ERROR,
  313. DBG_INIT,
  314. ("Can't allocate buffer for MP Device Name\n" ));
  315. return NDIS_STATUS_RESOURCES;
  316. }
  317. //
  318. // max length includes a trailing null, while length is just the string
  319. //
  320. PsMpName.MaximumLength = MpDeviceNameLength;
  321. PsMpName.Length = PsMpName.MaximumLength - sizeof( WCHAR );
  322. PsMpName.Buffer = RegistryPathBuffer;
  323. NdisMoveMemory(PsMpName.Buffer,
  324. RegistryPath->Buffer,
  325. RegistryPath->Length );
  326. i = RegistryPath->Length / sizeof( WCHAR );
  327. RegistryPathBuffer[ i++ ] = L'M';
  328. RegistryPathBuffer[ i++ ] = L'P';
  329. RegistryPathBuffer[ i ] = L'\0';
  330. NdisMInitializeWrapper(&MpWrapperHandle,
  331. DriverObject,
  332. &PsMpName,
  333. NULL);
  334. return NDIS_STATUS_SUCCESS;
  335. } // InitializeNdisWrapper
  336. NDIS_STATUS
  337. DoMiniportInit(
  338. IN PDRIVER_OBJECT DriverObject,
  339. IN PUNICODE_STRING RegistryPath
  340. )
  341. /*++
  342. Routine Name:
  343. DoMiniportInit
  344. Routine Description:
  345. This routines registers Psched as a Miniport driver with the NDIS wrapper.
  346. Arguments:
  347. None
  348. Return Values:
  349. NDIS_STATUS_SUCCESS
  350. NDIS_STATUS_BAD_VERSION
  351. NDIS_STATUS_FAILURE
  352. --*/
  353. {
  354. NDIS_MINIPORT_CHARACTERISTICS MiniportChars;
  355. NDIS_STATUS Status;
  356. MiniportChars.MajorNdisVersion = 5;
  357. MiniportChars.MinorNdisVersion = 0;
  358. MiniportChars.Reserved = 0;
  359. MiniportChars.HaltHandler = MpHalt;
  360. MiniportChars.InitializeHandler = MpInitialize;
  361. MiniportChars.QueryInformationHandler = MpQueryInformation;
  362. MiniportChars.ResetHandler = MpReset;
  363. MiniportChars.SetInformationHandler = MpSetInformation;
  364. MiniportChars.TransferDataHandler = MpTransferData;
  365. //
  366. // Unused handlers
  367. //
  368. MiniportChars.ReconfigureHandler = NULL;
  369. MiniportChars.DisableInterruptHandler = NULL;
  370. MiniportChars.EnableInterruptHandler = NULL;
  371. MiniportChars.HandleInterruptHandler = NULL;
  372. MiniportChars.ISRHandler = NULL;
  373. //
  374. // We will disable the check for hang timeout so we do not
  375. // need a check for hang handler!
  376. //
  377. MiniportChars.CheckForHangHandler = NULL;
  378. //
  379. // Ndis 4.0 handlers. No regular send routine since we have a
  380. // SendPackets handler.
  381. //
  382. MiniportChars.ReturnPacketHandler = MpReturnPacket;
  383. MiniportChars.SendPacketsHandler = NULL;
  384. MiniportChars.AllocateCompleteHandler = NULL;
  385. MiniportChars.SendHandler = MpSend;
  386. //
  387. // 4.1 handlers
  388. //
  389. MiniportChars.CoCreateVcHandler = NULL;
  390. MiniportChars.CoDeleteVcHandler = NULL;
  391. MiniportChars.CoActivateVcHandler = NULL;
  392. MiniportChars.CoDeactivateVcHandler = NULL;
  393. MiniportChars.CoSendPacketsHandler = NULL;
  394. MiniportChars.CoRequestHandler = NULL;
  395. Status = NdisIMRegisterLayeredMiniport(MpWrapperHandle,
  396. &MiniportChars,
  397. sizeof(MiniportChars),
  398. &LmDriverHandle);
  399. //
  400. // Hook the unload function
  401. //
  402. NdisMRegisterUnloadHandler(MpWrapperHandle, PSUnload);
  403. return (Status);
  404. } // DoMiniportInit
  405. NDIS_STATUS
  406. DoProtocolInit(
  407. IN PDRIVER_OBJECT DriverObject,
  408. IN PUNICODE_STRING RegistryPath
  409. )
  410. /*++
  411. Routine Name:
  412. DoProtocolInit
  413. Routine Description:
  414. This function registers the PS twice as a protocol - once for the protocol
  415. section of the LM and the other for the CM section.
  416. Arguments:
  417. RegistryPath - pointer to our key in the registry
  418. Return Values:
  419. NDIS_STATUS_BAD_CHARACTERISTICS
  420. NDIS_STATUS_BAD_VERSION
  421. NDIS_STATUS_RESOURCES
  422. NDIS_STATUS_SUCCESS
  423. --*/
  424. {
  425. NDIS_PROTOCOL_CHARACTERISTICS ProtocolChars;
  426. NDIS_STATUS Status;
  427. NDIS_STRING PsName = NDIS_STRING_CONST( "PSched" );
  428. //
  429. // register the client portion of the PS
  430. //
  431. NdisZeroMemory(&ProtocolChars, sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
  432. ProtocolChars.Name.Length = PsName.Length;
  433. ProtocolChars.Name.Buffer = (PVOID)PsName.Buffer;
  434. ProtocolChars.MajorNdisVersion = 5;
  435. ProtocolChars.MinorNdisVersion = 0;
  436. ProtocolChars.OpenAdapterCompleteHandler = ClLowerMpOpenAdapterComplete;
  437. ProtocolChars.CloseAdapterCompleteHandler = ClLowerMpCloseAdapterComplete;
  438. ProtocolChars.SendCompleteHandler = ClSendComplete;
  439. ProtocolChars.TransferDataCompleteHandler = ClTransferDataComplete;
  440. ProtocolChars.ResetCompleteHandler = ClResetComplete;
  441. ProtocolChars.RequestCompleteHandler = ClRequestComplete;
  442. ProtocolChars.ReceiveHandler = ClReceiveIndication;
  443. ProtocolChars.ReceiveCompleteHandler = ClReceiveComplete;
  444. ProtocolChars.StatusHandler = ClStatusIndication;
  445. ProtocolChars.StatusCompleteHandler = ClStatusIndicationComplete;
  446. ProtocolChars.ReceivePacketHandler = ClReceivePacket;
  447. ProtocolChars.BindAdapterHandler = ClBindToLowerMp;
  448. ProtocolChars.UnbindAdapterHandler = ClUnbindFromLowerMp;
  449. ProtocolChars.UnloadHandler = ClUnloadProtocol;
  450. ProtocolChars.CoSendCompleteHandler = ClCoSendComplete;
  451. ProtocolChars.CoStatusHandler = ClCoStatus;
  452. ProtocolChars.CoReceivePacketHandler = ClCoReceivePacket;
  453. ProtocolChars.CoAfRegisterNotifyHandler = ClCoAfRegisterNotifyHandler;
  454. ProtocolChars.PnPEventHandler = ClPnPEventHandler;
  455. NdisRegisterProtocol(&Status,
  456. &ClientProtocolHandle,
  457. &ProtocolChars,
  458. sizeof(NDIS_PROTOCOL_CHARACTERISTICS) + ProtocolChars.Name.Length);
  459. return Status;
  460. } // DoProtocolInit
  461. NTSTATUS
  462. RegisterWithGpc(
  463. )
  464. /*++
  465. Routine Name:
  466. RegisterWithGpc
  467. Routine Description:
  468. This function initializes the Gpc and gets its list of entry points.
  469. Next, it registers the PS as a client of the GPC and gets a GPC client
  470. handle. The PS must be a client of the GPC before it can classify packets.
  471. Arguments:
  472. GpcHandle - points to the location into which to write the handle which
  473. the GPC gives out to represent this client.
  474. Return Values:
  475. --*/
  476. {
  477. NTSTATUS Status;
  478. //
  479. // Function list for CF_INFO_QOS
  480. //
  481. GPC_CLIENT_FUNC_LIST GpcQosFuncList = {
  482. GpcMajorVersion,
  483. QosAddCfInfoComplete,
  484. QosAddCfInfoNotify,
  485. QosModifyCfInfoComplete,
  486. QosModifyCfInfoNotify,
  487. QosRemoveCfInfoComplete,
  488. QosRemoveCfInfoNotify,
  489. QosClGetCfInfoName
  490. };
  491. #if CBQ
  492. //
  493. // Function List for CF_INFO_CLASS_MAP
  494. //
  495. GPC_CLIENT_FUNC_LIST GpcClassMapFuncList = {
  496. GpcMajorVersion,
  497. ClassMapAddCfInfoComplete,
  498. ClassMapAddCfInfoNotify,
  499. ClassMapModifyCfInfoComplete,
  500. ClassMapModifyCfInfoNotify,
  501. ClassMapRemoveCfInfoComplete,
  502. ClassMapRemoveCfInfoNotify,
  503. ClassMapClGetCfInfoName
  504. };
  505. #endif
  506. Status = GpcInitialize(&GpcEntries);
  507. if(!NT_SUCCESS(Status))
  508. {
  509. return Status;
  510. }
  511. PsAssert(GpcEntries.GpcRegisterClientHandler);
  512. //
  513. // Register for CF_INFO_QOS
  514. //
  515. Status = GpcEntries.GpcRegisterClientHandler(GPC_CF_QOS,
  516. GPC_FLAGS_FRAGMENT,
  517. 1,
  518. &GpcQosFuncList,
  519. (GPC_CLIENT_HANDLE)PS_QOS_CF,
  520. &GpcQosClientHandle);
  521. if (!NT_SUCCESS(Status))
  522. {
  523. GpcQosClientHandle = NULL;
  524. return Status;
  525. }
  526. #if CBQ
  527. //
  528. // Register for the CF_INFO_CLASS_MAP
  529. //
  530. Status = GpcEntries.GpcRegisterClientHandler(
  531. GPC_CF_CLASS_MAP,
  532. GPC_FLAGS_FRAGMENT,
  533. 1,
  534. &GpcClassMapFuncList,
  535. (GPC_CLIENT_HANDLE)PS_CLASS_MAP_CF,
  536. &GpcClassMapClientHandle);
  537. if (!NT_SUCCESS(Status))
  538. {
  539. GpcClassMapClientHandle = NULL;
  540. GpcEntries.GpcDeregisterClientHandler(GpcQosClientHandle);
  541. GpcQosClientHandle = NULL;
  542. return Status;
  543. }
  544. #endif
  545. return Status;
  546. }
  547. VOID
  548. InitializationCleanup(
  549. ULONG ShutdownMask
  550. )
  551. /*++
  552. Routine Description:
  553. This routine is responsible for cleaning up all allocated resources during
  554. initialization
  555. Arguments:
  556. ShutdownMask - A Mask that indicates the items that need to be cleaned up.
  557. Return Values:
  558. None
  559. --*/
  560. {
  561. NDIS_STATUS Status;
  562. PPSI_INFO PsComponent;
  563. PLIST_ENTRY NextProfile, NextComponent;
  564. PPS_PROFILE PsProfile;
  565. //
  566. // Deregister the protocol; we should have no references that would cause
  567. // this to pend
  568. //
  569. if(ShutdownMask & SHUTDOWN_DEREGISTER_MINIPORT){
  570. if(LmDriverHandle){
  571. NdisIMDeregisterLayeredMiniport(LmDriverHandle);
  572. }
  573. }
  574. if(ShutdownMask & SHUTDOWN_DEREGISTER_PROTOCOL){
  575. if(ClientProtocolHandle){
  576. NdisDeregisterProtocol(&Status, ClientProtocolHandle);
  577. if(Status != NDIS_STATUS_SUCCESS){
  578. PsDbgOut(DBG_CRITICAL_ERROR,
  579. DBG_INIT,
  580. ("[InitializationCleanup]: NdisDeregisterProtocol failed - Status 0x%x \n", Status));
  581. }
  582. }
  583. }
  584. //
  585. // Deregister with the GPC
  586. //
  587. if(ShutdownMask & SHUTDOWN_DEREGISTER_GPC){
  588. PsAssert(GpcEntries.GpcDeregisterClientHandler);
  589. Status = GpcEntries.GpcDeregisterClientHandler(GpcQosClientHandle);
  590. if(Status != GPC_STATUS_SUCCESS){
  591. PsDbgOut(DBG_CRITICAL_ERROR,
  592. DBG_INIT,
  593. ("[InitializationCleanup]: DeregisterGpc failed - Status %08X\n",
  594. Status));
  595. }
  596. #if CBQ
  597. Status = GpcEntries.GpcDeregisterClientHandler(GpcClassMapClientHandle);
  598. if(Status != GPC_STATUS_SUCCESS)
  599. {
  600. PsDbgOut(DBG_CRITICAL_ERROR,
  601. DBG_INIT,
  602. ("[InitializationCleanup]: DeregisterGpc failed - Status %08X\n",
  603. Status));
  604. }
  605. #endif
  606. }
  607. //
  608. // free the lookaside list resources
  609. //
  610. NdisDeleteNPagedLookasideList( &NdisRequestLL );
  611. NdisDeleteNPagedLookasideList( &GpcClientVcLL );
  612. //
  613. // Free up the components
  614. //
  615. NextComponent = PsComponentList.Flink;
  616. while ( NextComponent != &PsComponentList ) {
  617. PsComponent = CONTAINING_RECORD( NextComponent, PSI_INFO, Links );
  618. if(PsComponent->AddIn == TRUE) {
  619. if(PsComponent->ComponentName.Buffer) {
  620. PsFreePool(PsComponent->ComponentName.Buffer);
  621. }
  622. NextComponent = NextComponent->Flink;
  623. PsFreePool(PsComponent);
  624. }
  625. else {
  626. NextComponent = NextComponent->Flink;
  627. }
  628. }
  629. //
  630. // Free up the Profiles
  631. //
  632. NextProfile = PsProfileList.Flink;
  633. while( NextProfile != &PsProfileList) {
  634. PsProfile = CONTAINING_RECORD(NextProfile, PS_PROFILE, Links);
  635. if(PsProfile->ProfileName.Buffer) {
  636. PsFreePool(PsProfile->ProfileName.Buffer);
  637. }
  638. NextProfile = NextProfile->Flink;
  639. PsFreePool(PsProfile);
  640. }
  641. if(g_WanLinkTable)
  642. {
  643. PsFreePool(g_WanLinkTable);
  644. }
  645. if(PsMpName.Buffer)
  646. PsFreePool(PsMpName.Buffer);
  647. //
  648. // Free the locks
  649. //
  650. NdisFreeSpinLock(&AdapterListLock);
  651. NdisFreeSpinLock(&DriverUnloadLock);
  652. NdisFreeSpinLock(&PsComponentListLock);
  653. NdisFreeSpinLock(&PsProfileLock);
  654. //
  655. // TIMESTMP CLEANUP
  656. // 1. Get rid of all the TS_ENTRYs. Release all the memory allocated for them.
  657. // 2. Delete the spin lock.
  658. //
  659. UnloadConformr();
  660. UnloadSequencer();
  661. UnloadTimeStmp();
  662. UnloadPsStub();
  663. // Free the logging stuff //
  664. #if DBG
  665. SchedDeInitialize();
  666. #endif
  667. } // InitializationCleanup
  668. /*++
  669. Routine Description:
  670. This routine returns the timer resolution to the requesting scheduling component.
  671. Arguments:
  672. TimerResolution - Pointer to location in which to return timer resolution.
  673. Return Values:
  674. None
  675. --*/
  676. VOID
  677. GetTimerInfo (
  678. OUT PULONG TimerResolution
  679. )
  680. {
  681. // *TimerResolution = gTimerResolutionActualTime;
  682. *TimerResolution = 0;
  683. } // GetTimerInfo
  684. /*++
  685. Routine Description:
  686. This routine is the driver unload routine.
  687. Arguments:
  688. pDriverObject - The DriverObject that is being unloaded
  689. Return Values:
  690. None
  691. --*/
  692. VOID PSUnload(
  693. IN PDRIVER_OBJECT pDriverObject)
  694. {
  695. PADAPTER Adapter;
  696. PLIST_ENTRY NextAdapter;
  697. NDIS_STATUS Status;
  698. PsDbgOut(DBG_INFO,
  699. DBG_INIT,
  700. ("[PsUnload]: pDriverObject: %x\n", pDriverObject));
  701. PS_LOCK(&DriverUnloadLock);
  702. gDriverState = DriverStateUnloading;
  703. PS_UNLOCK(&DriverUnloadLock);
  704. //
  705. // We wait here till all binds are complete. All future binds are rejected
  706. //
  707. NdisWaitEvent(&DriverUnloadEvent, 0);
  708. //
  709. // we don't have to close opens from the unload handler. Our call
  710. // to NdisDeRegisterProtocol will not return until it issues unbinds
  711. //
  712. InitializationCleanup( 0xffffffff );
  713. PsDbgOut(DBG_INFO, DBG_INIT, (" Unloading psched....\n"));
  714. return;
  715. }
  716. /* end main.c */