Leaked source code of windows server 2003
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.

3120 lines
83 KiB

  1. /*++
  2. Copyright (c) 1996-1999 Microsoft Corporation
  3. Module Name:
  4. adapter.c
  5. Abstract:
  6. routines for binding/unbinding to/from underlying miniport drivers
  7. Author:
  8. Charlie Wickham (charlwi) 24-Apr-1996.
  9. Rajesh Sundaram (rajeshsu) 01-Aug-1998.
  10. Environment:
  11. Kernel Mode
  12. Revision History:
  13. --*/
  14. #include "psched.h"
  15. #pragma hdrstop
  16. /* Defines */
  17. /* External */
  18. /* Static */
  19. #define DRIVER_COUNTED_BLOCK \
  20. { \
  21. ++DriverRefCount; \
  22. NdisResetEvent(&DriverUnloadEvent); \
  23. }
  24. #define DRIVER_COUNTED_UNBLOCK \
  25. { \
  26. PS_LOCK(&DriverUnloadLock); \
  27. if( --DriverRefCount == 0) \
  28. NdisSetEvent(&DriverUnloadEvent); \
  29. PS_UNLOCK(&DriverUnloadLock); \
  30. }
  31. /* Forward */
  32. NDIS_STATUS
  33. PsInitializeDeviceInstance(PADAPTER Adapter);
  34. NDIS_STATUS
  35. GetFrameSize(
  36. PADAPTER Adapter
  37. );
  38. NDIS_STATUS
  39. InitializeAdapter(
  40. PADAPTER Adapter,
  41. NDIS_HANDLE BindContext,
  42. PNDIS_STRING MpDeviceName,
  43. PVOID SystemSpecific1);
  44. NDIS_STATUS
  45. UpdateSchedulingPipe(
  46. PADAPTER Adapter
  47. );
  48. VOID
  49. DeleteAdapter(PVOID Adapter, BOOLEAN AdapterListLocked);
  50. VOID
  51. ClUnloadProtocol(
  52. VOID
  53. );
  54. VOID
  55. MpHalt(
  56. IN NDIS_HANDLE MiniportAdapterContext
  57. );
  58. NDIS_STATUS
  59. GetSchedulerPipeContext(
  60. PADAPTER Adapter,
  61. PPS_PIPE_CONTEXT *AdapterPipeContext,
  62. PPSI_INFO *AdapterPsComponent,
  63. PULONG ShutdownMask
  64. );
  65. NDIS_STATUS
  66. FindProfile(
  67. IN PNDIS_STRING ProfileName,
  68. OUT PPS_PROFILE *Profile
  69. );
  70. NDIS_STATUS
  71. RegisterPsComponent(
  72. IN PPSI_INFO PsiComponentInfo,
  73. ULONG Size,
  74. PPS_DEBUG_INFO DebugInfo
  75. );
  76. NDIS_STATUS
  77. FindSchedulingComponent(
  78. IN PNDIS_STRING ComponentName,
  79. OUT PPSI_INFO *Component
  80. );
  81. NDIS_STATUS
  82. PsReadMiniportOIDs(
  83. IN PADAPTER Adapter
  84. );
  85. VOID
  86. CloseAllGpcVcs(
  87. IN PADAPTER Adapter);
  88. /* End Forward */
  89. NTSTATUS
  90. PsIoctl(
  91. IN PDEVICE_OBJECT pdo,
  92. IN PIRP pirp
  93. )
  94. {
  95. PIO_STACK_LOCATION pirpSp;
  96. ULONG ioControlCode;
  97. PLIST_ENTRY NextAdapter;
  98. PADAPTER Adapter;
  99. NTSTATUS Status ;
  100. PGPC_CLIENT_VC Vc;
  101. PLIST_ENTRY NextVc;
  102. PPS_WAN_LINK WanLink;
  103. PVOID pIoBuf;
  104. ULONG InputBufferLength;
  105. ULONG OutputBufferLength;
  106. USHORT Port = 0;
  107. ULONG Ip = 0;
  108. PTIMESTMP_REQ pTsReq = NULL;
  109. #if DBG
  110. KIRQL OldIrql;
  111. KIRQL NewIrql;
  112. OldIrql = KeGetCurrentIrql();
  113. #endif
  114. pirpSp = IoGetCurrentIrpStackLocation(pirp);
  115. ioControlCode = pirpSp->Parameters.DeviceIoControl.IoControlCode;
  116. pirp->IoStatus.Status = Status = STATUS_SUCCESS;
  117. pirp->IoStatus.Information = 0;
  118. /* Both input and output buffers are mapped to "SystemBuffer" in case of direct-IO */
  119. pIoBuf = pirp->AssociatedIrp.SystemBuffer;
  120. InputBufferLength = pirpSp->Parameters.DeviceIoControl.InputBufferLength;
  121. OutputBufferLength = pirpSp->Parameters.DeviceIoControl.OutputBufferLength;
  122. switch(pirpSp->MajorFunction)
  123. {
  124. case IRP_MJ_DEVICE_CONTROL:
  125. switch (ioControlCode)
  126. {
  127. case IOCTL_PSCHED_ZAW_EVENT:
  128. while(InterlockedExchange(&gZAWState, ZAW_STATE_IN_USE) != ZAW_STATE_READY)
  129. {
  130. //
  131. // Some other thread is in this loop. Let's wait
  132. //
  133. NdisResetEvent(&gZAWEvent);
  134. NdisWaitEvent(&gZAWEvent, 0);
  135. }
  136. PsReadDriverRegistryData();
  137. //
  138. // Handle the per adapter settings.
  139. //
  140. PS_LOCK(&AdapterListLock);
  141. NextAdapter = AdapterList.Flink;
  142. while(NextAdapter != &AdapterList)
  143. {
  144. Adapter = CONTAINING_RECORD(NextAdapter, ADAPTER, Linkage);
  145. PS_LOCK_DPC(&Adapter->Lock);
  146. if(Adapter->PsMpState != AdapterStateRunning)
  147. {
  148. PS_UNLOCK_DPC(&Adapter->Lock);
  149. NextAdapter = NextAdapter->Flink;
  150. continue;
  151. }
  152. REFADD(&Adapter->RefCount, 'IOTL');
  153. PS_UNLOCK_DPC(&Adapter->Lock);
  154. PS_UNLOCK(&AdapterListLock);
  155. PsReadAdapterRegistryData(Adapter,
  156. &MachineRegistryKey,
  157. &Adapter->RegistryPath
  158. );
  159. //
  160. // This will apply the effects of the following registry parameters.
  161. //
  162. // NonBestEffortLimit
  163. // TimerResolution (since we update the scheduling pipe)
  164. //
  165. if(Adapter->MediaType != NdisMediumWan)
  166. {
  167. UpdateAdapterBandwidthParameters(Adapter);
  168. //
  169. // Set 802.1p/TOS for b/e Vc
  170. //
  171. Adapter->BestEffortVc.UserPriorityConforming = Adapter->UserServiceTypeBestEffort;
  172. Adapter->BestEffortVc.UserPriorityNonConforming = Adapter->UserServiceTypeNonConforming;
  173. Adapter->BestEffortVc.IPPrecedenceNonConforming = Adapter->IPServiceTypeBestEffortNC;
  174. }
  175. else
  176. {
  177. PS_LOCK(&Adapter->Lock);
  178. NextVc = Adapter->WanLinkList.Flink;
  179. while( NextVc != &Adapter->WanLinkList)
  180. {
  181. WanLink = CONTAINING_RECORD(NextVc, PS_WAN_LINK, Linkage);
  182. PS_LOCK_DPC(&WanLink->Lock);
  183. WanLink->BestEffortVc.UserPriorityConforming = Adapter->UserServiceTypeBestEffort;
  184. WanLink->BestEffortVc.UserPriorityNonConforming = Adapter->UserServiceTypeNonConforming;
  185. WanLink->BestEffortVc.IPPrecedenceNonConforming =
  186. Adapter->IPServiceTypeBestEffortNC;
  187. if(WanLink->State == WanStateOpen)
  188. {
  189. REFADD(&WanLink->RefCount, 'IOTL');
  190. PS_UNLOCK_DPC(&WanLink->Lock);
  191. PS_UNLOCK(&Adapter->Lock);
  192. UpdateWanLinkBandwidthParameters(WanLink);
  193. PS_LOCK(&Adapter->Lock);
  194. NextVc = NextVc->Flink;
  195. REFDEL(&WanLink->RefCount, TRUE, 'IOTL');
  196. }
  197. else
  198. {
  199. PS_UNLOCK_DPC(&WanLink->Lock);
  200. NextVc = NextVc->Flink;
  201. }
  202. }
  203. PS_UNLOCK(&Adapter->Lock);
  204. }
  205. //
  206. // Apply the new TOS/802.1p mapping to the VCs.
  207. //
  208. PS_LOCK(&Adapter->Lock);
  209. NextVc = Adapter->GpcClientVcList.Flink;
  210. while ( NextVc != &Adapter->GpcClientVcList )
  211. {
  212. Vc = CONTAINING_RECORD(NextVc, GPC_CLIENT_VC, Linkage);
  213. NextVc = NextVc->Flink;
  214. PS_LOCK_DPC(&Vc->Lock);
  215. if(Vc->ClVcState == CL_CALL_COMPLETE ||
  216. Vc->ClVcState == CL_INTERNAL_CALL_COMPLETE )
  217. {
  218. SetTOSIEEEValues(Vc);
  219. }
  220. PS_UNLOCK_DPC(&Vc->Lock);
  221. }
  222. PS_UNLOCK(&Adapter->Lock);
  223. PS_LOCK(&AdapterListLock);
  224. NextAdapter = NextAdapter->Flink;
  225. REFDEL(&Adapter->RefCount, TRUE, 'IOTL');
  226. }
  227. PS_UNLOCK(&AdapterListLock);
  228. InterlockedExchange(&gZAWState, ZAW_STATE_READY);
  229. NdisSetEvent(&gZAWEvent);
  230. break;
  231. default:
  232. Status = STATUS_NOT_SUPPORTED;
  233. break;
  234. }
  235. break;
  236. case IRP_MJ_CREATE:
  237. break;
  238. case IRP_MJ_CLOSE:
  239. break;
  240. case IRP_MJ_CLEANUP:
  241. break;
  242. case IRP_MJ_READ:
  243. break;
  244. case IRP_MJ_SHUTDOWN:
  245. break;
  246. default:
  247. Status = STATUS_NOT_SUPPORTED;
  248. break;
  249. }
  250. if( Status == STATUS_SUCCESS)
  251. {
  252. pirp->IoStatus.Status = Status;
  253. IoCompleteRequest(pirp, IO_NETWORK_INCREMENT);
  254. }
  255. else
  256. {
  257. pirp->IoStatus.Status = Status;
  258. IoCompleteRequest(pirp, IO_NO_INCREMENT);
  259. }
  260. PsAssert( OldIrql == KeGetCurrentIrql());
  261. return Status;
  262. }
  263. NDIS_STATUS
  264. PsIoctlInit()
  265. {
  266. int i;
  267. NDIS_STATUS Status;
  268. PDRIVER_DISPATCH DispatchTable[IRP_MJ_MAXIMUM_FUNCTION+1];
  269. for(i=0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
  270. {
  271. DispatchTable[i] = PsIoctl;
  272. }
  273. DispatchTable[IRP_MJ_SYSTEM_CONTROL] = WMIDispatch;
  274. Status = NdisMRegisterDevice(MpWrapperHandle,
  275. &PsDriverName,
  276. &PsSymbolicName,
  277. DispatchTable,
  278. &PsDeviceObject,
  279. &PsDeviceHandle);
  280. if(Status == NDIS_STATUS_SUCCESS)
  281. {
  282. InitShutdownMask |= SHUTDOWN_DELETE_DEVICE;
  283. PsDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  284. IoWMIRegistrationControl(PsDeviceObject, WMIREG_ACTION_REGISTER);
  285. }
  286. else
  287. {
  288. PsDeviceHandle = PsDeviceObject = 0;
  289. }
  290. return Status;
  291. }
  292. VOID
  293. PsAddDevice()
  294. {
  295. //
  296. // The first Adapter will create the DeviceObject which will enable us to receive
  297. // irps and become a WMI data provider. The last DeviceObject will unregister from
  298. // WMI and delete the DeviceObject.
  299. //
  300. MUX_ACQUIRE_MUTEX( &CreateDeviceMutex );
  301. ++AdapterCount;
  302. if(AdapterCount == 1)
  303. {
  304. //
  305. // This is the first adapter, so we create a DeviceObject
  306. // that allows us to get irps and registers as a WMI data
  307. // provider.
  308. PsIoctlInit();
  309. }
  310. MUX_RELEASE_MUTEX( &CreateDeviceMutex);
  311. }
  312. NDIS_STATUS
  313. PsInitializeDeviceInstance(PADAPTER Adapter)
  314. {
  315. NDIS_STATUS Status;
  316. PsAssert(KeGetCurrentIrql() < DISPATCH_LEVEL);
  317. PsDbgOut(DBG_INFO,
  318. DBG_PROTOCOL,
  319. ("[PSInitializeDeviceInstance]: Adapter %08X, InitializeDeviceInstance with %ws \n",
  320. Adapter,
  321. Adapter->UpperBinding.Buffer));
  322. Status = NdisIMInitializeDeviceInstanceEx(LmDriverHandle,
  323. &Adapter->UpperBinding,
  324. Adapter);
  325. if (Status != NDIS_STATUS_SUCCESS)
  326. {
  327. PsDbgOut(DBG_FAILURE,
  328. DBG_PROTOCOL,
  329. ("[PsInitializeDeviceInstance]: Adapter %08X, can't init PS device (%08X)\n",
  330. Adapter,
  331. Status));
  332. PsAdapterWriteEventLog(
  333. EVENT_PS_INIT_DEVICE_FAILED,
  334. 0,
  335. &Adapter->MpDeviceName,
  336. sizeof(Status),
  337. &Status);
  338. }
  339. return Status;
  340. }
  341. VOID
  342. PsDeleteDevice()
  343. {
  344. //
  345. // The first Adapter will create the DeviceObject which will enable us to receive
  346. // irps and become a WMI data provider. The last DeviceObject will unregister from
  347. // WMI and delete the DeviceObject. In order to prevent a race condition we prevent
  348. // any mpinitialize threads from looking at the AdapterCount. This is achieved by
  349. // re-setting the WMIAddEvent. It is not sufficient just to do this based on
  350. // interlocked operations on AdapterCount.
  351. //
  352. MUX_ACQUIRE_MUTEX( &CreateDeviceMutex );
  353. --AdapterCount;
  354. if(AdapterCount == 0)
  355. {
  356. //
  357. // Delete the DeviceObject, since this is the last Adapter.
  358. //
  359. if(PsDeviceObject)
  360. {
  361. IoWMIRegistrationControl(PsDeviceObject, WMIREG_ACTION_DEREGISTER);
  362. NdisMDeregisterDevice(PsDeviceHandle);
  363. PsDeviceHandle = PsDeviceObject = 0;
  364. }
  365. }
  366. MUX_RELEASE_MUTEX( &CreateDeviceMutex);
  367. }
  368. // No of retries to query the frame size
  369. #define MAX_GET_FRAME_SIZE_RETRY_COUNT 3
  370. #define WAIT_TIME_FOR_GET_FRAME_SIZE 3
  371. VOID
  372. ClBindToLowerMp(
  373. OUT PNDIS_STATUS Status,
  374. IN NDIS_HANDLE BindContext,
  375. IN PNDIS_STRING MpDeviceName,
  376. IN PVOID SystemSpecific1,
  377. IN PVOID SystemSpecific2
  378. )
  379. /*++
  380. Routine Description:
  381. Bind to the underlying MP. Allocate space for an adapter structure,
  382. initializing its fields. Try to open the adapter indicated in MpDeviceName.
  383. Arguments:
  384. Status : Placeholder for the driver to return a Status to NDIS.
  385. BindContext : Handle represents NDIS's context for the bind request.
  386. This has to be saved and returned when we call
  387. NdisCompleteBindAdapter
  388. SystemSpecific1 : Points to a registy path for the driver to obtain adapter
  389. specific configuration.
  390. MpDeviceName : DeviceName can refer to a NIC managed by an underlying NIC
  391. driver, or it can be the name of a virtual NIC exported by
  392. an intermediate NDIS driver that is layered between the
  393. called intermediate driver and the NIC driver managing the
  394. adapter to which transmit requests are directed.
  395. SystemSpecific2 : Unused, reserved for future use.
  396. Return Values:
  397. None
  398. --*/
  399. {
  400. PADAPTER Adapter;
  401. NDIS_STATUS OpenAdapterStatus;
  402. NDIS_STATUS OpenErrorStatus;
  403. NDIS_STATUS LocalStatus;
  404. UINT MediaIndex;
  405. NDIS_MEDIUM MediumArray[] = {
  406. NdisMediumFddi,
  407. NdisMedium802_5,
  408. NdisMedium802_3,
  409. NdisMediumWan
  410. };
  411. UINT MediumArraySize = sizeof(MediumArray)/sizeof(NDIS_MEDIUM);
  412. UINT GetFrameSizeRetryCount = 0;
  413. PsDbgOut(DBG_INFO,
  414. DBG_PROTOCOL | DBG_INIT,
  415. ("[ClBindToLowerMp]: MpDeviceName %ws\n", MpDeviceName->Buffer));
  416. PS_LOCK(&DriverUnloadLock);
  417. //
  418. // (a) The driver can get unloaded before we complete the bind thread.
  419. // (b) we can get bound as the driver is getting unloaded.
  420. //
  421. // if (a) happens, we block the driver unload and unblock when we finish the bind.
  422. // if (b) happens, we fail the bind call.
  423. if(gDriverState != DriverStateLoaded) {
  424. *Status = NDIS_STATUS_FAILURE;
  425. PS_UNLOCK(&DriverUnloadLock);
  426. PsDbgOut(DBG_FAILURE, DBG_PROTOCOL|DBG_INIT,
  427. ("[ClBindToLowerMp]: Driver is being unloaded \n"));
  428. return;
  429. }
  430. DRIVER_COUNTED_BLOCK;
  431. PS_UNLOCK(&DriverUnloadLock);
  432. //
  433. // Get a new adapter context struct and initialize it with configuration
  434. // data from the registry.
  435. //
  436. PsAllocatePool(Adapter, sizeof(ADAPTER), AdapterTag);
  437. if(Adapter == NULL) {
  438. PsAdapterWriteEventLog(
  439. (ULONG)EVENT_PS_RESOURCE_POOL,
  440. 0,
  441. MpDeviceName,
  442. 0,
  443. NULL);
  444. *Status = NDIS_STATUS_RESOURCES;
  445. DRIVER_COUNTED_UNBLOCK;
  446. return;
  447. }
  448. //
  449. // Initialize the adapter.
  450. //
  451. *Status = InitializeAdapter(Adapter, BindContext, MpDeviceName, SystemSpecific1);
  452. Adapter->ShutdownMask |= SHUTDOWN_BIND_CALLED;
  453. if(*Status != NDIS_STATUS_SUCCESS) {
  454. PsDeleteDevice();
  455. REFDEL(&Adapter->RefCount, FALSE, 'NDOP');
  456. DRIVER_COUNTED_UNBLOCK;
  457. return;
  458. }
  459. NdisOpenAdapter(&OpenAdapterStatus,
  460. &OpenErrorStatus,
  461. &Adapter->LowerMpHandle,
  462. &MediaIndex,
  463. MediumArray,
  464. MediumArraySize,
  465. ClientProtocolHandle,
  466. Adapter,
  467. MpDeviceName,
  468. 0,
  469. NULL);
  470. if(OpenAdapterStatus == NDIS_STATUS_PENDING)
  471. {
  472. NdisWaitEvent(&Adapter->BlockingEvent, 0);
  473. NdisResetEvent(&Adapter->BlockingEvent);
  474. }
  475. else
  476. {
  477. Adapter->FinalStatus = OpenAdapterStatus;
  478. }
  479. if(Adapter->FinalStatus == NDIS_STATUS_SUCCESS)
  480. {
  481. Adapter->MediaType = MediumArray[MediaIndex];
  482. //
  483. // Take a ref for the open
  484. //
  485. REFADD(&Adapter->RefCount, 'NDOP');
  486. }
  487. else
  488. {
  489. PsDbgOut(DBG_FAILURE,
  490. DBG_PROTOCOL,
  491. ("[ClBindToLowerMp]: Adapter %08X, binding failed (Status = %08X) \n",
  492. Adapter,
  493. Status));
  494. *Status = Adapter->FinalStatus;
  495. PsAdapterWriteEventLog(
  496. EVENT_PS_BINDING_FAILED,
  497. 0,
  498. &Adapter->MpDeviceName,
  499. sizeof(Adapter->FinalStatus),
  500. &Adapter->FinalStatus);
  501. PsDeleteDevice();
  502. REFDEL(&Adapter->RefCount, FALSE, 'NDOP');
  503. DRIVER_COUNTED_UNBLOCK;
  504. return;
  505. }
  506. //
  507. // Get the information pertaining to the miniport below us.
  508. //
  509. while(1)
  510. {
  511. *Status = GetFrameSize(Adapter);
  512. if(*Status != NDIS_STATUS_SUCCESS)
  513. {
  514. if( GetFrameSizeRetryCount == MAX_GET_FRAME_SIZE_RETRY_COUNT)
  515. {
  516. goto ErrorCloseOpen;
  517. }
  518. else
  519. {
  520. GetFrameSizeRetryCount++;
  521. NdisMSleep( WAIT_TIME_FOR_GET_FRAME_SIZE * 1000 * 1000);
  522. }
  523. }
  524. else
  525. {
  526. break;
  527. }
  528. }
  529. Adapter->RawLinkSpeed = (ULONG)UNSPECIFIED_RATE;
  530. *Status = UpdateAdapterBandwidthParameters(Adapter);
  531. if(*Status != NDIS_STATUS_SUCCESS)
  532. {
  533. if(*Status != NDIS_STATUS_ADAPTER_NOT_READY)
  534. {
  535. PsDbgOut(DBG_FAILURE,
  536. DBG_PROTOCOL |
  537. DBG_INIT,
  538. ("[ClBindToLowerMp]: Adapter %08X, couldn't add pipe %08X\n",
  539. Adapter,
  540. Status));
  541. goto ErrorCloseOpen;
  542. }
  543. else
  544. {
  545. // The scheduling components have not registered. Let's not call NdisIMInitializeDeviceInstance.
  546. //
  547. *Status = NDIS_STATUS_SUCCESS;
  548. Adapter->PsMpState = AdapterStateWaiting;
  549. }
  550. }
  551. // Let's move the creation of IM device here, to see what happens.
  552. *Status = PsInitializeDeviceInstance(Adapter);
  553. if(*Status != NDIS_STATUS_SUCCESS)
  554. {
  555. goto ErrorCloseOpen;
  556. }
  557. // Ignore the status
  558. PsReadMiniportOIDs(Adapter);
  559. PsUpdateLinkSpeed(Adapter, Adapter->RawLinkSpeed,
  560. &Adapter->RemainingBandWidth,
  561. &Adapter->LinkSpeed,
  562. &Adapter->NonBestEffortLimit,
  563. &Adapter->Lock);
  564. // This will repro the NetReady bug anywhere, anytime.
  565. // NdisMSleep( 5 * 1000 * 1000 );
  566. REFDEL(&Adapter->RefCount, FALSE, 'NDOP');
  567. DRIVER_COUNTED_UNBLOCK;
  568. return;
  569. ErrorCloseOpen:
  570. //
  571. // if we have opened an underlying call manager, close it now.
  572. //
  573. if(Adapter->MediaType == NdisMediumWan) {
  574. PS_LOCK(&Adapter->Lock);
  575. if(Adapter->ShutdownMask & SHUTDOWN_CLOSE_WAN_ADDR_FAMILY){
  576. Adapter->ShutdownMask &= ~SHUTDOWN_CLOSE_WAN_ADDR_FAMILY;
  577. PS_UNLOCK(&Adapter->Lock);
  578. PsDbgOut(DBG_TRACE, DBG_WAN | DBG_MINIPORT,
  579. ("[ClBindToLowerMp]: Adapter %08X Closing the WAN address family", Adapter));
  580. LocalStatus = NdisClCloseAddressFamily(Adapter->WanCmHandle);
  581. }
  582. else
  583. {
  584. PS_UNLOCK(&Adapter->Lock);
  585. }
  586. }
  587. //
  588. // Close the open since we opened it above
  589. //
  590. if(Adapter->LowerMpHandle)
  591. {
  592. NdisCloseAdapter(&LocalStatus, Adapter->LowerMpHandle);
  593. if(LocalStatus == NDIS_STATUS_PENDING)
  594. {
  595. NdisWaitEvent(&Adapter->BlockingEvent, 0);
  596. NdisResetEvent(&Adapter->BlockingEvent);
  597. }
  598. REFDEL(&Adapter->RefCount, FALSE, 'NDOP');
  599. }
  600. PsDeleteDevice();
  601. REFDEL(&Adapter->RefCount, FALSE, 'NDOP');
  602. DRIVER_COUNTED_UNBLOCK;
  603. return;
  604. } // ClBindToLowerMp
  605. VOID
  606. LinkSpeedQueryComplete(
  607. PADAPTER Adapter,
  608. NDIS_STATUS Status
  609. )
  610. /*++
  611. Routine Description:
  612. Completion routine for link speed query during a status indication. Notify
  613. the scheduling alg. that we have a new adapter
  614. Arguments:
  615. the usual...
  616. Return Value:
  617. None
  618. --*/
  619. {
  620. PsDbgOut(DBG_INFO,
  621. DBG_PROTOCOL,
  622. ("[LinkSpeedQueryComplete]: Adapter %08X, Status %x, Link speed %d\n",
  623. Adapter, Status,
  624. Adapter->LinkSpeed*100));
  625. if ( !NT_SUCCESS( Status ))
  626. {
  627. Adapter->RawLinkSpeed = (ULONG)UNSPECIFIED_RATE;
  628. PsAdapterWriteEventLog(
  629. EVENT_PS_QUERY_OID_GEN_LINK_SPEED,
  630. 0,
  631. &Adapter->MpDeviceName,
  632. sizeof(Status),
  633. &Status);
  634. }
  635. UpdateAdapterBandwidthParameters(Adapter);
  636. }
  637. VOID
  638. PsGetLinkSpeed (
  639. IN PADAPTER Adapter
  640. )
  641. {
  642. NDIS_STATUS Status;
  643. Status = MakeLocalNdisRequest(Adapter,
  644. NULL,
  645. NdisRequestLocalQueryInfo,
  646. OID_GEN_LINK_SPEED,
  647. &Adapter->RawLinkSpeed,
  648. sizeof(Adapter->RawLinkSpeed),
  649. LinkSpeedQueryComplete);
  650. if (Status != NDIS_STATUS_PENDING)
  651. {
  652. LinkSpeedQueryComplete(Adapter, Status);
  653. }
  654. }
  655. NDIS_STATUS
  656. PsReadMiniportOIDs(
  657. IN PADAPTER Adapter
  658. )
  659. /*++
  660. Routine Description:
  661. Complete the binding on the lower miniport. Initialize the
  662. adapter structure, query the MP for certain funtionality and
  663. initialize the associated PS miniport device
  664. Arguments:
  665. see the DDK
  666. Return Values:
  667. None
  668. --*/
  669. {
  670. NDIS_STATUS Status;
  671. PWSTR SecondaryName;
  672. NDIS_HARDWARE_STATUS HwStatus;
  673. NDIS_MEDIA_STATE MediaState = 0xFFFFFFFF;
  674. NDIS_STRING PsDevName;
  675. ULONG MacOptions;
  676. ULONG LinkSpeed;
  677. PsDbgOut(DBG_TRACE,
  678. DBG_PROTOCOL,
  679. ("[PsReadMiniportOIDs]: Adapter %08X \n", Adapter));
  680. Status = MakeLocalNdisRequest(Adapter,
  681. NULL,
  682. NdisRequestLocalQueryInfo,
  683. OID_GEN_MEDIA_CONNECT_STATUS,
  684. &MediaState,
  685. sizeof( MediaState ),
  686. NULL);
  687. PsAssert(Status != NDIS_STATUS_INVALID_OID || Status != NDIS_STATUS_NOT_SUPPORTED);
  688. if(Status == NDIS_STATUS_SUCCESS && MediaState == NdisMediaStateConnected){
  689. Status = MakeLocalNdisRequest(Adapter,
  690. NULL,
  691. NdisRequestLocalQueryInfo,
  692. OID_GEN_LINK_SPEED,
  693. &Adapter->RawLinkSpeed,
  694. sizeof(LinkSpeed),
  695. NULL);
  696. if(Status != NDIS_STATUS_SUCCESS){
  697. PsDbgOut(DBG_INFO,
  698. DBG_PROTOCOL,
  699. ("[PsReadMiniportOIDs]: Adapter %08X, Can't get link "
  700. "speed - Status %08X\n", Adapter, Status));
  701. Adapter->RawLinkSpeed = (ULONG)UNSPECIFIED_RATE;
  702. PsAdapterWriteEventLog(
  703. EVENT_PS_QUERY_OID_GEN_LINK_SPEED,
  704. 0,
  705. &Adapter->MpDeviceName,
  706. sizeof(Status),
  707. &Status);
  708. }
  709. PsDbgOut(DBG_INFO,
  710. DBG_PROTOCOL,
  711. ("[PsReadMiniportOIDs] Adapter %08X, Link speed %d\n",
  712. Adapter,
  713. Adapter->RawLinkSpeed*100));
  714. }
  715. else{
  716. //
  717. // We can continue, even though we don't yet have the
  718. // link speed. We'll update it later.
  719. //
  720. Adapter->RawLinkSpeed = (ULONG)UNSPECIFIED_RATE;
  721. PsDbgOut(DBG_INFO,
  722. DBG_PROTOCOL,
  723. ("[PsReadMiniportOIDs]: Adapter %08X, Media not connected\n",
  724. Adapter));
  725. }
  726. return Status;
  727. } // PsReadMiniportOIDs
  728. VOID
  729. PsUpdateLinkSpeed(
  730. PADAPTER Adapter,
  731. ULONG RawLinkSpeed,
  732. PULONG RemainingBandWidth,
  733. PULONG LinkSpeed,
  734. PULONG NonBestEffortLimit,
  735. PPS_SPIN_LOCK Lock
  736. )
  737. {
  738. ULONG NewNonBestEffortLimit;
  739. PS_LOCK(Lock);
  740. if(RawLinkSpeed == UNSPECIFIED_RATE)
  741. {
  742. //
  743. // It is legit to have an unspecified rate - We pend
  744. // all finite rate flows till we know the link speed.
  745. // Indefinite rate flows will be admitted.
  746. //
  747. *LinkSpeed = UNSPECIFIED_RATE;
  748. Adapter->PipeHasResources = FALSE;
  749. }
  750. else
  751. {
  752. //
  753. // RawLinkSpeed is in 100 bps units. Convert it to 100 Bytes per second
  754. // and then into Bytes Per Second.
  755. //
  756. *LinkSpeed = RawLinkSpeed / 8;
  757. *LinkSpeed = (ULONG)(*LinkSpeed * 100);
  758. PsDbgOut(DBG_TRACE, DBG_PROTOCOL,
  759. ("[PsUpdateLinkSpeed]: Adapter %08X, Link Speed %d \n",
  760. Adapter, *LinkSpeed));
  761. Adapter->PipeHasResources = TRUE;
  762. //
  763. // The NBE is a % of the link speed. If the link speed changes, we need to
  764. // change this value.
  765. //
  766. NewNonBestEffortLimit = Adapter->ReservationLimitValue * (*LinkSpeed / 100);
  767. PsDbgOut(DBG_INFO, DBG_PROTOCOL,
  768. ("[PsUpdateLinkSpeed]: Adapter %08X, LinkSpeed %d, NBE %d, "
  769. " Remaining b/w = %d, New NBE = %d \n",
  770. Adapter, *LinkSpeed, *NonBestEffortLimit,
  771. *RemainingBandWidth, NewNonBestEffortLimit));
  772. if(NewNonBestEffortLimit >= *NonBestEffortLimit) {
  773. //
  774. // The bandwidth has increased - we need not do anything with
  775. // the flows that have already been created. Also, if RemainingBandWidth <
  776. // NonBestEffortLimit, then some of the resources have been allocated to flows
  777. // that were already created - We need to subtract this from the new
  778. // RemainingBandWidth.
  779. //
  780. *RemainingBandWidth = NewNonBestEffortLimit - (*NonBestEffortLimit - *RemainingBandWidth);
  781. *NonBestEffortLimit = NewNonBestEffortLimit;
  782. }
  783. else {
  784. //
  785. // Sigh. The bandwidth has decreased. We may need to delete some of the flows
  786. //
  787. if(*RemainingBandWidth == *NonBestEffortLimit)
  788. {
  789. //
  790. // No flows were created as yet - Just update the 2 values
  791. //
  792. *NonBestEffortLimit = *RemainingBandWidth = NewNonBestEffortLimit;
  793. }
  794. else {
  795. if((*NonBestEffortLimit - *RemainingBandWidth) <= (NewNonBestEffortLimit)) {
  796. //
  797. // The flows that were created are under the new limit.
  798. //
  799. *RemainingBandWidth = NewNonBestEffortLimit - (*NonBestEffortLimit - *RemainingBandWidth);
  800. *NonBestEffortLimit = NewNonBestEffortLimit;
  801. }
  802. else
  803. {
  804. *RemainingBandWidth = NewNonBestEffortLimit - (*NonBestEffortLimit - *RemainingBandWidth);
  805. *NonBestEffortLimit = NewNonBestEffortLimit;
  806. PsAdapterWriteEventLog(
  807. EVENT_PS_ADMISSIONCONTROL_OVERFLOW,
  808. 0,
  809. &Adapter->MpDeviceName,
  810. 0,
  811. NULL);
  812. }
  813. }
  814. }
  815. }
  816. PS_UNLOCK(Lock);
  817. }
  818. NDIS_STATUS
  819. UpdateAdapterBandwidthParameters(
  820. PADAPTER Adapter
  821. )
  822. {
  823. PsUpdateLinkSpeed(Adapter, Adapter->RawLinkSpeed,
  824. &Adapter->RemainingBandWidth,
  825. &Adapter->LinkSpeed,
  826. &Adapter->NonBestEffortLimit,
  827. &Adapter->Lock);
  828. return UpdateSchedulingPipe(Adapter);
  829. }
  830. VOID
  831. ClLowerMpOpenAdapterComplete(
  832. IN PADAPTER Adapter,
  833. IN NDIS_STATUS Status,
  834. IN NDIS_STATUS OpenErrorStatus
  835. )
  836. /*++
  837. Routine Description:
  838. Signal that the binding on the lower miniport is complete
  839. Arguments:
  840. see the DDK
  841. Return Values:
  842. None
  843. --*/
  844. {
  845. PsDbgOut(DBG_TRACE, DBG_PROTOCOL, ("[ClLowerMpOpenAdapterComplete]: Adapter %08X\n",
  846. Adapter));
  847. //
  848. // stuff the final status in the Adapter block and signal
  849. // the bind handler to continue
  850. //
  851. Adapter->FinalStatus = Status;
  852. NdisSetEvent( &Adapter->BlockingEvent );
  853. } // ClLowerMpOpenAdapterComplete
  854. NDIS_STATUS
  855. GetFrameSize(
  856. PADAPTER Adapter
  857. )
  858. /*++
  859. Routine Description:
  860. This routine queries the underlying adapter to derive the total
  861. frame size and the header size. (Total = Frame + Header)
  862. Arguments:
  863. Adapter - pointer to adapter context block
  864. Return Value:
  865. None
  866. --*/
  867. {
  868. NDIS_STATUS Status;
  869. ULONG i;
  870. ULONG FrameSize; // doesn't include the header
  871. //
  872. // max amount of data w/o the MAC header
  873. //
  874. Status = MakeLocalNdisRequest(Adapter,
  875. NULL,
  876. NdisRequestLocalQueryInfo,
  877. OID_GEN_MAXIMUM_FRAME_SIZE,
  878. &FrameSize,
  879. sizeof(FrameSize),
  880. NULL);
  881. if(Status != NDIS_STATUS_SUCCESS){
  882. PsDbgOut(DBG_FAILURE,
  883. DBG_PROTOCOL,
  884. ("[GetFrameSize]: Adapter %08X, Can't get frame size - Status %08X\n",
  885. Adapter,
  886. Status));
  887. PsAdapterWriteEventLog(
  888. EVENT_PS_QUERY_OID_GEN_MAXIMUM_FRAME_SIZE,
  889. 0,
  890. &Adapter->MpDeviceName,
  891. sizeof(Status),
  892. &Status);
  893. return Status;
  894. }
  895. //
  896. // this one includes the header
  897. //
  898. Status = MakeLocalNdisRequest(Adapter,
  899. NULL,
  900. NdisRequestLocalQueryInfo,
  901. OID_GEN_MAXIMUM_TOTAL_SIZE,
  902. &Adapter->TotalSize,
  903. sizeof(Adapter->TotalSize),
  904. NULL);
  905. if(Status != NDIS_STATUS_SUCCESS){
  906. PsDbgOut(DBG_FAILURE,
  907. DBG_PROTOCOL,
  908. ("(%08X) GetFrameSize: Can't get total size - Status %08X\n",
  909. Adapter,
  910. Status));
  911. PsAdapterWriteEventLog(
  912. EVENT_PS_QUERY_OID_GEN_MAXIMUM_TOTAL_SIZE,
  913. 0,
  914. &Adapter->MpDeviceName,
  915. sizeof(Status),
  916. &Status);
  917. return Status;
  918. }
  919. //
  920. // figure the real header size
  921. //
  922. if (Adapter->TotalSize <= FrameSize)
  923. Status = NDIS_STATUS_FAILURE;
  924. else
  925. Adapter->HeaderSize = Adapter->TotalSize - FrameSize;
  926. return Status;
  927. } // GetFrameSize
  928. NDIS_STATUS
  929. GetSchedulerPipeContext(
  930. PADAPTER Adapter,
  931. PPS_PIPE_CONTEXT *AdapterPipeContext,
  932. PPSI_INFO *AdapterPsComponent,
  933. PULONG ShutdownMask
  934. )
  935. /*++
  936. Routine Description:
  937. Allocate the pipe context area for the scheduler.
  938. Arguments:
  939. Adapter - pointer to adapter context struct
  940. Return Value:
  941. NDIS_STATUS_SUCCESS, otherwise appropriate error value
  942. --*/
  943. {
  944. ULONG Index = 0;
  945. PPS_PROFILE ProfileConfig;
  946. PPSI_INFO PsComponent;
  947. ULONG ContextLength = 0;
  948. ULONG FlowContextLength = 0;
  949. ULONG ClassMapContextLength = 0;
  950. PPS_PIPE_CONTEXT PipeContext, PrevContext;
  951. ULONG PacketReservedLength = sizeof(PS_SEND_PACKET_CONTEXT);
  952. PVOID PipeCxt;
  953. ProfileConfig = &DefaultSchedulerConfig;
  954. for (Index = 0; Index < ProfileConfig->ComponentCnt; Index++)
  955. {
  956. ContextLength +=
  957. ProfileConfig->ComponentList[Index]->PipeContextLength;
  958. FlowContextLength +=
  959. ProfileConfig->ComponentList[Index]->FlowContextLength;
  960. ClassMapContextLength +=
  961. ProfileConfig->ComponentList[Index]->ClassMapContextLength;
  962. PacketReservedLength += ProfileConfig->ComponentList[Index]->PacketReservedLength;
  963. }
  964. Adapter->FlowContextLength = FlowContextLength;
  965. Adapter->ClassMapContextLength = ClassMapContextLength;
  966. Adapter->PacketContextLength = PacketReservedLength;
  967. if(AdapterPipeContext)
  968. {
  969. PacketReservedLength = sizeof(PS_SEND_PACKET_CONTEXT);
  970. PsAllocatePool( PipeContext, ContextLength, PipeContextTag );
  971. *AdapterPipeContext = PipeContext;
  972. if ( *AdapterPipeContext == NULL ) {
  973. return NDIS_STATUS_RESOURCES;
  974. }
  975. *ShutdownMask |= SHUTDOWN_FREE_PS_CONTEXT;
  976. // Set up the context buffer
  977. PrevContext = NULL;
  978. for (Index = 0; Index < ProfileConfig->ComponentCnt; Index++)
  979. {
  980. PsComponent = ProfileConfig->ComponentList[Index];
  981. PipeContext->NextComponentContext = (PPS_PIPE_CONTEXT)
  982. ((UINT_PTR)PipeContext + PsComponent->PipeContextLength);
  983. PipeContext->PrevComponentContext = PrevContext;
  984. if(Index+1 == ProfileConfig->ComponentCnt)
  985. {
  986. PipeContext->NextComponent = 0;
  987. }
  988. else
  989. {
  990. PipeContext->NextComponent =
  991. ProfileConfig->ComponentList[Index + 1];
  992. }
  993. if (PsComponent->PacketReservedLength > 0)
  994. {
  995. PipeContext->PacketReservedOffset = PacketReservedLength;
  996. PacketReservedLength +=
  997. PsComponent->PacketReservedLength;
  998. } else
  999. {
  1000. PipeContext->PacketReservedOffset = 0;
  1001. }
  1002. PrevContext = PipeContext;
  1003. PipeContext = PipeContext->NextComponentContext;
  1004. }
  1005. *AdapterPsComponent = ProfileConfig->ComponentList[0];
  1006. }
  1007. return NDIS_STATUS_SUCCESS;
  1008. } // GetSchedulerPipeContext
  1009. NDIS_STATUS
  1010. UpdateWanSchedulingPipe(PPS_WAN_LINK WanLink)
  1011. {
  1012. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  1013. PS_PIPE_PARAMETERS PipeParameters;
  1014. PADAPTER Adapter = WanLink->Adapter;
  1015. //
  1016. // Initialize pipe parameters.
  1017. // UNSPECIFIED_RATE indicates that the link speed is currently
  1018. // unknown. This is a legitimate initialization value.
  1019. //
  1020. PS_LOCK(&Adapter->Lock);
  1021. PS_LOCK_DPC(&WanLink->Lock);
  1022. PipeParameters.Bandwidth = WanLink->LinkSpeed;
  1023. PipeParameters.MTUSize = Adapter->TotalSize;
  1024. PipeParameters.HeaderSize = Adapter->HeaderSize;
  1025. PipeParameters.Flags = Adapter->PipeFlags;
  1026. PipeParameters.MaxOutstandingSends = Adapter->MaxOutstandingSends;
  1027. PipeParameters.SDModeControlledLoad = Adapter->SDModeControlledLoad;
  1028. PipeParameters.SDModeGuaranteed = Adapter->SDModeGuaranteed;
  1029. PipeParameters.SDModeNetworkControl = Adapter->SDModeNetworkControl;
  1030. PipeParameters.SDModeQualitative = Adapter->SDModeQualitative;
  1031. PipeParameters.RegistryPath = &Adapter->RegistryPath;
  1032. PS_UNLOCK_DPC(&WanLink->Lock);
  1033. PS_UNLOCK(&Adapter->Lock);
  1034. //
  1035. // Initialize the pipe for only the first time
  1036. //
  1037. if ( !(WanLink->ShutdownMask & SHUTDOWN_DELETE_PIPE )) {
  1038. //
  1039. // Allocate and initialize the context buffer for the scheduler.
  1040. //
  1041. Status = GetSchedulerPipeContext( Adapter,
  1042. &WanLink->PsPipeContext,
  1043. &WanLink->PsComponent,
  1044. &WanLink->ShutdownMask );
  1045. if ( !NT_SUCCESS( Status ))
  1046. {
  1047. return Status;
  1048. }
  1049. WanLink->BestEffortVc.PsPipeContext = WanLink->PsPipeContext;
  1050. WanLink->BestEffortVc.PsComponent = WanLink->PsComponent;
  1051. // Need to set the pipe's media type here.. //
  1052. PipeParameters.MediaType = NdisMediumWan;
  1053. Status = (*WanLink->PsComponent->InitializePipe)(
  1054. Adapter,
  1055. &PipeParameters,
  1056. WanLink->PsPipeContext,
  1057. &PsProcs,
  1058. NULL);
  1059. if (NT_SUCCESS(Status))
  1060. {
  1061. WanLink->ShutdownMask |= SHUTDOWN_DELETE_PIPE;
  1062. }
  1063. }
  1064. else{
  1065. // Pipe's already been initialized. This is a modify
  1066. Status = (*WanLink->PsComponent->ModifyPipe)(
  1067. WanLink->PsPipeContext,
  1068. &PipeParameters);
  1069. }
  1070. return Status;
  1071. }
  1072. NDIS_STATUS
  1073. UpdateSchedulingPipe(
  1074. PADAPTER Adapter
  1075. )
  1076. /*++
  1077. Routine Description:
  1078. Initialize a scheduling pipe on the adapter. Always called with a LOCK
  1079. held.
  1080. Arguments:
  1081. Adapter - pointer to adapter context struct
  1082. Return Value:
  1083. NDIS_STATUS_SUCCESS, otherwise appropriate error value
  1084. --*/
  1085. {
  1086. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  1087. PS_PIPE_PARAMETERS PipeParameters;
  1088. //
  1089. // Initialize pipe parameters.
  1090. // UNSPECIFIED_RATE indicates that the link speed is currently
  1091. // unknown. This is a legitimate initialization value.
  1092. //
  1093. PS_LOCK(&Adapter->Lock);
  1094. PipeParameters.Bandwidth = Adapter->LinkSpeed;
  1095. PipeParameters.MTUSize = Adapter->TotalSize;
  1096. PipeParameters.HeaderSize = Adapter->HeaderSize;
  1097. PipeParameters.Flags = Adapter->PipeFlags;
  1098. PipeParameters.MaxOutstandingSends = Adapter->MaxOutstandingSends;
  1099. PipeParameters.SDModeControlledLoad = Adapter->SDModeControlledLoad;
  1100. PipeParameters.SDModeGuaranteed = Adapter->SDModeGuaranteed;
  1101. PipeParameters.SDModeNetworkControl = Adapter->SDModeNetworkControl;
  1102. PipeParameters.SDModeQualitative = Adapter->SDModeQualitative;
  1103. PipeParameters.RegistryPath = &Adapter->RegistryPath;
  1104. PS_UNLOCK(&Adapter->Lock);
  1105. //
  1106. // Initialize the pipe for only the first time
  1107. //
  1108. if ( !(Adapter->ShutdownMask & SHUTDOWN_DELETE_PIPE ))
  1109. {
  1110. //
  1111. // We don't run the scheduling components on the Adapter structure for NDISWAN.
  1112. // Each wanlink has its own set of scheduling components. But, we still need to compute the
  1113. // PacketPool Length and allocate the Packet Pool - Hence we have to call GetSchedulerPipeContext
  1114. //
  1115. if(Adapter->MediaType == NdisMediumWan)
  1116. {
  1117. //
  1118. // Allocate and initialize the context buffer for the scheduler.
  1119. //
  1120. Status = GetSchedulerPipeContext( Adapter,
  1121. NULL,
  1122. NULL,
  1123. NULL);
  1124. }
  1125. else
  1126. {
  1127. Status = GetSchedulerPipeContext( Adapter,
  1128. &Adapter->PsPipeContext,
  1129. &Adapter->PsComponent,
  1130. &Adapter->ShutdownMask);
  1131. }
  1132. if ( !NT_SUCCESS( Status ))
  1133. {
  1134. return Status;
  1135. }
  1136. if(Adapter->MediaType == NdisMediumWan)
  1137. {
  1138. Adapter->ShutdownMask |= SHUTDOWN_DELETE_PIPE;
  1139. PsAssert(!(Adapter->ShutdownMask & SHUTDOWN_FREE_PS_CONTEXT));
  1140. PsAssert(!Adapter->PsPipeContext);
  1141. PsAssert(!Adapter->PsComponent);
  1142. }
  1143. else
  1144. {
  1145. // Need to set the pipe's media type here.. //
  1146. PipeParameters.MediaType = Adapter->MediaType;
  1147. Status = (*Adapter->PsComponent->InitializePipe)(
  1148. Adapter,
  1149. &PipeParameters,
  1150. Adapter->PsPipeContext,
  1151. &PsProcs,
  1152. NULL);
  1153. if (NT_SUCCESS(Status)) {
  1154. Adapter->ShutdownMask |= SHUTDOWN_DELETE_PIPE;
  1155. }
  1156. else
  1157. {
  1158. return Status;
  1159. }
  1160. }
  1161. }
  1162. else
  1163. {
  1164. // Pipe's already been initialized. This is a modify
  1165. if(Adapter->MediaType != NdisMediumWan)
  1166. {
  1167. Status = (*Adapter->PsComponent->ModifyPipe)(
  1168. Adapter->PsPipeContext,
  1169. &PipeParameters);
  1170. }
  1171. }
  1172. return Status;
  1173. } // UpdateSchedulingPipe
  1174. NDIS_STATUS
  1175. MpInitialize(
  1176. OUT PNDIS_STATUS OpenErrorStatus,
  1177. OUT PUINT SelectedMediumIndex,
  1178. IN PNDIS_MEDIUM MediumArray,
  1179. IN UINT MediumArraySize,
  1180. IN NDIS_HANDLE MiniportAdapterHandle,
  1181. IN NDIS_HANDLE WrapperConfigurationContext
  1182. )
  1183. /*++
  1184. Routine Description:
  1185. Packet scheduler's device initialization routine. The list of media types is
  1186. checked to be sure it is one that we support. If so, match up the name of
  1187. the device being opened with one of the adapters to which we've bound.
  1188. Arguments:
  1189. See the DDK...
  1190. Return Values:
  1191. None
  1192. --*/
  1193. {
  1194. PADAPTER Adapter;
  1195. NDIS_STATUS Status;
  1196. BOOLEAN FakingIt = FALSE;
  1197. NDIS_STRING MpDeviceName;
  1198. //
  1199. // We're being called to initialize one of our miniport
  1200. // device instances. We triggered this by calling
  1201. // NdisIMInitializeDeviceInstance when we were asked to
  1202. // bind to the adapter below us. We provided a pointer
  1203. // to the ADAPTER struct corresponding to the actual
  1204. // adapter we opened. We can get that back now, with the
  1205. // following call.
  1206. //
  1207. Adapter = NdisIMGetDeviceContext(MiniportAdapterHandle);
  1208. PsStructAssert(Adapter);
  1209. PsDbgOut(DBG_TRACE, DBG_MINIPORT | DBG_INIT, ("[MpInitialize]: Adapter %08X \n", Adapter));
  1210. Adapter->ShutdownMask |= SHUTDOWN_MPINIT_CALLED;
  1211. //
  1212. // We assume that the faster packet APIs will be used, and initialize our per-packet pool. If we don't get a packet-stack,
  1213. // we'll initialize the NDIS packet pool and free the per-packet pool (since the NDIS packet pool will have space for a per-packet
  1214. // pool).
  1215. //
  1216. // We cannot know about the old or new packet stack API at bind time (because even if we did know our position in the packet stack, and
  1217. // initialized the old APIs, we could get a newly allocated packet from an IM above us which will have room for a packet stack).
  1218. //
  1219. Adapter->SendBlockPool = NdisCreateBlockPool((USHORT)Adapter->PacketContextLength,
  1220. FIELD_OFFSET(PS_SEND_PACKET_CONTEXT, FreeList),
  1221. NDIS_PACKET_POOL_TAG_FOR_PSCHED,
  1222. NULL);
  1223. if(!Adapter->SendBlockPool)
  1224. {
  1225. PsDbgOut(DBG_CRITICAL_ERROR,
  1226. DBG_MINIPORT | DBG_INIT,
  1227. ("[MpInitialize]: Adapter %08X, Can't allocate packet pool \n",
  1228. Adapter));
  1229. Status = NDIS_STATUS_RESOURCES;
  1230. PsAdapterWriteEventLog(
  1231. EVENT_PS_RESOURCE_POOL,
  1232. 0,
  1233. &Adapter->MpDeviceName,
  1234. 0,
  1235. NULL);
  1236. goto MpInitializeError;
  1237. }
  1238. //
  1239. // We can also get the instance name for the corresponding
  1240. // adapter. This is the name which WMI will be using to
  1241. // refer to this instance of us.
  1242. //
  1243. Status = NdisMQueryAdapterInstanceName(&Adapter->WMIInstanceName, MiniportAdapterHandle);
  1244. if(Status != NDIS_STATUS_SUCCESS)
  1245. {
  1246. PsDbgOut(DBG_CRITICAL_ERROR,
  1247. DBG_MINIPORT | DBG_INIT,
  1248. ("[MpInitialize]: Adapter %08X, Failed to get WMI instance name.\n",
  1249. Adapter,
  1250. Status));
  1251. PsAdapterWriteEventLog(
  1252. EVENT_PS_WMI_INSTANCE_NAME_FAILED,
  1253. 0,
  1254. &Adapter->MpDeviceName,
  1255. sizeof(Status),
  1256. &Status);
  1257. goto MpInitializeError;
  1258. }
  1259. //
  1260. // lookup our media type in the supplied media array
  1261. //
  1262. // if we're NdisMediumWan, then we have to fake out the
  1263. // protocol and pretend that we're NdisMedium802_3, so
  1264. // fake it for now.
  1265. //
  1266. if(Adapter->MediaType == NdisMediumWan){
  1267. FakingIt = TRUE;
  1268. Adapter->MediaType = NdisMedium802_3;
  1269. }
  1270. if (MediumArray != 0) {
  1271. for(--MediumArraySize ; MediumArraySize > 0;) {
  1272. if(MediumArray[ MediumArraySize ] == Adapter->MediaType){
  1273. break;
  1274. }
  1275. if(MediumArraySize == 0){
  1276. break;
  1277. }
  1278. --MediumArraySize;
  1279. }
  1280. }
  1281. if(MediumArraySize == 0 && MediumArray[ 0 ] != Adapter->MediaType){
  1282. if(FakingIt)
  1283. {
  1284. FakingIt = FALSE;
  1285. Adapter->MediaType = NdisMediumWan;
  1286. }
  1287. PsDbgOut(DBG_CRITICAL_ERROR,
  1288. DBG_MINIPORT | DBG_INIT,
  1289. ("[MpInitialize]: Adapter %08X, Unsupported Media \n",
  1290. Adapter));
  1291. Status = NDIS_STATUS_UNSUPPORTED_MEDIA;
  1292. goto MpInitializeError;
  1293. }
  1294. if(FakingIt){
  1295. FakingIt = FALSE;
  1296. Adapter->MediaType = NdisMediumWan;
  1297. }
  1298. *SelectedMediumIndex = MediumArraySize;
  1299. //
  1300. // finish the initialization process by set our attributes
  1301. //
  1302. NdisMSetAttributesEx(MiniportAdapterHandle,
  1303. Adapter,
  1304. 0xFFFF,
  1305. NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT |
  1306. NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT |
  1307. NDIS_ATTRIBUTE_DESERIALIZE |
  1308. NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER |
  1309. NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND,
  1310. 0);
  1311. //
  1312. // Set the default value for the device state flag as PM capable (for both miniport
  1313. // and protocol). Device is ON by default
  1314. //
  1315. Adapter->MPDeviceState = NdisDeviceStateD0;
  1316. Adapter->PTDeviceState = NdisDeviceStateD0;
  1317. Adapter->PsNdisHandle = MiniportAdapterHandle;
  1318. //
  1319. // We create the b/e VC here (rather than the bind handler) because
  1320. // this will be called only after all scheduling components have registered.
  1321. //
  1322. if(Adapter->MediaType != NdisMediumWan) {
  1323. Status = CreateBestEffortVc(Adapter,
  1324. &Adapter->BestEffortVc,
  1325. 0);
  1326. if(Status != NDIS_STATUS_SUCCESS)
  1327. {
  1328. PsDbgOut(DBG_CRITICAL_ERROR, DBG_MINIPORT | DBG_INIT,
  1329. ("[MpInitialize]: Adapter %08X, cannot create b/e VC ! \n",
  1330. Adapter));
  1331. goto MpInitializeError;
  1332. }
  1333. }
  1334. Adapter->PsMpState = AdapterStateRunning;
  1335. //
  1336. // This is for mpinitialize, will be deref'd on mphalt.
  1337. //
  1338. REFADD(&Adapter->RefCount, 'NDHT');
  1339. PS_LOCK(&AdapterListLock);
  1340. if(WMIInitialized && !Adapter->IfcNotification)
  1341. {
  1342. //
  1343. // WMI has been initialized correctly. i.e we can post events
  1344. // at this point.
  1345. //
  1346. Adapter->IfcNotification = TRUE;
  1347. PS_UNLOCK(&AdapterListLock);
  1348. TcIndicateInterfaceChange(Adapter, 0, NDIS_STATUS_INTERFACE_UP);
  1349. }
  1350. else
  1351. {
  1352. //
  1353. // WMI has not been initialized. Since this adapter is already on the
  1354. // list, the interface up event will be posted when IRP_MN_REGINFO
  1355. // completes.
  1356. //
  1357. PS_UNLOCK(&AdapterListLock);
  1358. }
  1359. NdisSetEvent(&Adapter->MpInitializeEvent);
  1360. return NDIS_STATUS_SUCCESS;
  1361. MpInitializeError:
  1362. Adapter->PsNdisHandle = 0;
  1363. NdisSetEvent(&Adapter->MpInitializeEvent);
  1364. return Status;
  1365. } // MpInitialize
  1366. PADAPTER
  1367. FindAdapterById(
  1368. ULONG InterfaceId,
  1369. ULONG LinkId,
  1370. PPS_WAN_LINK *PsWanLink
  1371. )
  1372. {
  1373. PLIST_ENTRY NextAdapter;
  1374. PLIST_ENTRY NextLink;
  1375. PPS_WAN_LINK WanLink;
  1376. PADAPTER AdapterInList;
  1377. *PsWanLink = NULL;
  1378. PS_LOCK(&AdapterListLock);
  1379. NextAdapter = AdapterList.Flink;
  1380. while(NextAdapter != &AdapterList){
  1381. AdapterInList = CONTAINING_RECORD(NextAdapter, ADAPTER, Linkage);
  1382. PS_LOCK_DPC(&AdapterInList->Lock);
  1383. //
  1384. // If it's closing, blow right by it.
  1385. //
  1386. if(AdapterInList->PsMpState != AdapterStateRunning)
  1387. {
  1388. PS_UNLOCK_DPC(&AdapterInList->Lock);
  1389. NextAdapter = NextAdapter->Flink;
  1390. continue;
  1391. }
  1392. if(AdapterInList->MediaType != NdisMediumWan)
  1393. {
  1394. if(AdapterInList->InterfaceID.InterfaceId != InterfaceId)
  1395. {
  1396. PS_UNLOCK_DPC(&AdapterInList->Lock);
  1397. NextAdapter = NextAdapter->Flink;
  1398. continue;
  1399. }
  1400. REFADD(&AdapterInList->RefCount, 'ADVC');
  1401. PS_UNLOCK_DPC(&AdapterInList->Lock);
  1402. PS_UNLOCK(&AdapterListLock);
  1403. return(AdapterInList);
  1404. }
  1405. else
  1406. {
  1407. if(AdapterInList->WanBindingState & WAN_ADDR_FAMILY_OPEN)
  1408. {
  1409. //
  1410. // Wan adapters are searched by the name stored with
  1411. // their links.
  1412. //
  1413. NextLink = AdapterInList->WanLinkList.Flink;
  1414. while(NextLink != &AdapterInList->WanLinkList){
  1415. WanLink = CONTAINING_RECORD(NextLink, PS_WAN_LINK, Linkage);
  1416. if((WanLink->State == WanStateOpen) &&
  1417. (LinkId == WanLink->InterfaceID.LinkId) &&
  1418. (InterfaceId == WanLink->InterfaceID.InterfaceId)) {
  1419. REFADD(&AdapterInList->RefCount, 'ADVC');
  1420. REFADD(&WanLink->RefCount, 'WANV');
  1421. PS_UNLOCK_DPC(&AdapterInList->Lock);
  1422. PS_UNLOCK(&AdapterListLock);
  1423. *PsWanLink = WanLink;
  1424. return(AdapterInList);
  1425. }
  1426. NextLink = NextLink->Flink;
  1427. }
  1428. }
  1429. }
  1430. PS_UNLOCK_DPC(&AdapterInList->Lock);
  1431. NextAdapter = NextAdapter->Flink;
  1432. }
  1433. PS_UNLOCK(&AdapterListLock);
  1434. return NULL;
  1435. } // FindAdapterByWmiInstanceName
  1436. PADAPTER
  1437. FindAdapterByWmiInstanceName(
  1438. USHORT StringLength,
  1439. PWSTR StringStart,
  1440. PPS_WAN_LINK *PsWanLink
  1441. )
  1442. /*++
  1443. Routine Description:
  1444. Find the miniport instance that matches the instance name passed in.
  1445. Arguments:
  1446. StringLength - Number of bytes / 2
  1447. StringStart - pointer to a buffer containing a wide string
  1448. PsWanLink - if this is an interface search, then the WAN link
  1449. representing the interface will be returned in this location.
  1450. If it is not an interface search or no matching WanLink is
  1451. found, NULL will be returned.
  1452. InterfaceSearch - if TRUE, this is a search for an interface. For
  1453. LAN adapters, an interface is equivalent to an adapter. For WAN
  1454. adapters, interfaces are links. Otherwise, it's a search for an
  1455. adapter.
  1456. Return Value:
  1457. pointer to ADAPTER struct, otherwise NULL
  1458. --*/
  1459. {
  1460. PLIST_ENTRY NextAdapter;
  1461. PLIST_ENTRY NextLink;
  1462. PPS_WAN_LINK WanLink;
  1463. PADAPTER AdapterInList;
  1464. *PsWanLink = NULL;
  1465. PS_LOCK(&AdapterListLock);
  1466. NextAdapter = AdapterList.Flink;
  1467. while(NextAdapter != &AdapterList){
  1468. AdapterInList = CONTAINING_RECORD(NextAdapter, ADAPTER, Linkage);
  1469. PS_LOCK_DPC(&AdapterInList->Lock);
  1470. //
  1471. // If it's closing, blow right by it.
  1472. //
  1473. if(AdapterInList->PsMpState != AdapterStateRunning)
  1474. {
  1475. PS_UNLOCK_DPC(&AdapterInList->Lock);
  1476. NextAdapter = NextAdapter->Flink;
  1477. continue;
  1478. }
  1479. if(AdapterInList->MediaType != NdisMediumWan)
  1480. {
  1481. if(StringLength == AdapterInList->WMIInstanceName.Length){
  1482. //
  1483. // At least they are of equal length.
  1484. //
  1485. if(NdisEqualMemory(StringStart,
  1486. AdapterInList->WMIInstanceName.Buffer,
  1487. StringLength)){
  1488. REFADD(&AdapterInList->RefCount, 'ADVC');
  1489. PS_UNLOCK_DPC(&AdapterInList->Lock);
  1490. PS_UNLOCK(&AdapterListLock);
  1491. return(AdapterInList);
  1492. }
  1493. }
  1494. }
  1495. else
  1496. {
  1497. if(AdapterInList->WanBindingState & WAN_ADDR_FAMILY_OPEN)
  1498. {
  1499. //
  1500. // Wan adapters are searched by the name stored with
  1501. // their links.
  1502. //
  1503. NextLink = AdapterInList->WanLinkList.Flink;
  1504. while(NextLink != &AdapterInList->WanLinkList){
  1505. WanLink = CONTAINING_RECORD(NextLink, PS_WAN_LINK, Linkage);
  1506. if(WanLink->State == WanStateOpen)
  1507. {
  1508. if(StringLength == WanLink->InstanceName.Length){
  1509. //
  1510. // At least they are of equal length.
  1511. //
  1512. if(NdisEqualMemory(StringStart,
  1513. WanLink->InstanceName.Buffer,
  1514. StringLength)){
  1515. REFADD(&AdapterInList->RefCount, 'ADVC');
  1516. REFADD(&WanLink->RefCount, 'WANV');
  1517. PS_UNLOCK_DPC(&AdapterInList->Lock);
  1518. PS_UNLOCK(&AdapterListLock);
  1519. *PsWanLink = WanLink;
  1520. return(AdapterInList);
  1521. }
  1522. }
  1523. }
  1524. NextLink = NextLink->Flink;
  1525. }
  1526. }
  1527. }
  1528. PS_UNLOCK_DPC(&AdapterInList->Lock);
  1529. NextAdapter = NextAdapter->Flink;
  1530. }
  1531. PS_UNLOCK(&AdapterListLock);
  1532. return NULL;
  1533. } // FindAdapterByWmiInstanceName
  1534. VOID
  1535. CleanUpAdapter(
  1536. IN PADAPTER Adapter)
  1537. {
  1538. NDIS_STATUS Status;
  1539. PsAssert(KeGetCurrentIrql() < DISPATCH_LEVEL);
  1540. TcIndicateInterfaceChange(Adapter, 0, NDIS_STATUS_INTERFACE_DOWN);
  1541. //
  1542. // Close all the VCs
  1543. //
  1544. CloseAllGpcVcs(Adapter);
  1545. //
  1546. // if we have opened an underlying call manager, close it now.
  1547. //
  1548. if(Adapter->MediaType == NdisMediumWan) {
  1549. PS_LOCK(&Adapter->Lock);
  1550. if(Adapter->ShutdownMask & SHUTDOWN_CLOSE_WAN_ADDR_FAMILY){
  1551. Adapter->ShutdownMask &= ~SHUTDOWN_CLOSE_WAN_ADDR_FAMILY;
  1552. PS_UNLOCK(&Adapter->Lock);
  1553. PsDbgOut(DBG_TRACE, DBG_WAN | DBG_MINIPORT,
  1554. ("[CleanupAdapter]: Adapter %08X Closing the WAN address family", Adapter));
  1555. Status = NdisClCloseAddressFamily(Adapter->WanCmHandle);
  1556. }
  1557. else
  1558. {
  1559. PS_UNLOCK(&Adapter->Lock);
  1560. }
  1561. }
  1562. }
  1563. VOID
  1564. ClUnbindFromLowerMp(
  1565. OUT PNDIS_STATUS Status,
  1566. IN NDIS_HANDLE ProtocolBindingContext,
  1567. IN NDIS_HANDLE UnbindContext
  1568. )
  1569. /*++
  1570. Routine Description:
  1571. Called by NDIS to indicate that an adapter is going away.
  1572. Since this is an integrated call manager/miniport, we will
  1573. have to close the call manager with the adapter. To do so,
  1574. we must first ask the clients of our call manager part to
  1575. close us. We will have to pend until then.
  1576. Release our reference
  1577. on the adapter and set the closing flag to true to prevent any further
  1578. references from being obtained.
  1579. Arguments:
  1580. See the DDK...
  1581. Return Values:
  1582. None
  1583. --*/
  1584. {
  1585. PADAPTER Adapter = (PADAPTER)ProtocolBindingContext;
  1586. NDIS_STATUS LocalStatus;
  1587. BOOLEAN VirtualMp;
  1588. ULONG ShutdownMask;
  1589. PsDbgOut(DBG_INFO,
  1590. DBG_PROTOCOL | DBG_INIT,
  1591. ("[ClUnbindFromLowerMp]: Adapter %08X, %ws, UnbindContext %x \n",
  1592. Adapter,
  1593. Adapter->MpDeviceName.Buffer,
  1594. UnbindContext));
  1595. PsStructAssert( Adapter );
  1596. PsAssert(!(Adapter->ShutdownMask & SHUTDOWN_UNBIND_CALLED));
  1597. //
  1598. // If the unbind is not happening from the context of the unload, we need to Make sure that
  1599. // unload waits for this unbind to complete. We do that by setting the DriverUnloadEvent.
  1600. //
  1601. PS_LOCK(&DriverUnloadLock);
  1602. DRIVER_COUNTED_BLOCK;
  1603. PS_UNLOCK(&DriverUnloadLock);
  1604. PS_LOCK(&Adapter->Lock);
  1605. if(Adapter->PsMpState == AdapterStateWaiting)
  1606. {
  1607. VirtualMp = FALSE;
  1608. }
  1609. else
  1610. {
  1611. VirtualMp = TRUE;
  1612. }
  1613. Adapter->PsMpState = AdapterStateClosing;
  1614. Adapter->ShutdownMask |= SHUTDOWN_UNBIND_CALLED;
  1615. PsAssert(!(Adapter->ShutdownMask & SHUTDOWN_CLEANUP_ADAPTER));
  1616. if (Adapter->PendedNdisRequest) {
  1617. PNDIS_REQUEST PendedRequest = (PNDIS_REQUEST)Adapter->PendedNdisRequest;
  1618. Adapter->PendedNdisRequest = NULL;
  1619. ClRequestComplete(Adapter, PendedRequest, NDIS_STATUS_FAILURE);
  1620. }
  1621. ShutdownMask = Adapter->ShutdownMask;
  1622. Adapter->ShutdownMask |= SHUTDOWN_CLEANUP_ADAPTER;
  1623. PS_UNLOCK(&Adapter->Lock);
  1624. if ( !(ShutdownMask & SHUTDOWN_CLEANUP_ADAPTER))
  1625. CleanUpAdapter(Adapter);
  1626. //
  1627. // DeInitialize the device instance if we have been called in the MpInitialize handler.
  1628. //
  1629. if(Adapter->PsNdisHandle)
  1630. {
  1631. //
  1632. // Either the mpinitialize has happened or its in progress. If it is in progress,
  1633. // we need to Wait till it completes.
  1634. //
  1635. NdisWaitEvent(&Adapter->MpInitializeEvent, 0);
  1636. //
  1637. // The MpInitialize (that we could have been waiting for in the above step) could have failed :
  1638. // So we need to check this handle again.
  1639. //
  1640. if(Adapter->PsNdisHandle)
  1641. {
  1642. *Status = NdisIMDeInitializeDeviceInstance(Adapter->PsNdisHandle);
  1643. PsDbgOut(DBG_INFO,
  1644. DBG_PROTOCOL | DBG_INIT,
  1645. ("[ClUnbindFromLowerMp]: Adapter %08X, deiniting device, "
  1646. "status %x\n", Adapter, *Status));
  1647. goto Done;
  1648. }
  1649. }
  1650. else
  1651. {
  1652. if(VirtualMp)
  1653. {
  1654. //
  1655. // We have never been called in MpInitialize. Try to cancel the NdisIMInitializeDeviceInstance
  1656. // call.
  1657. //
  1658. PsDbgOut(DBG_INFO,
  1659. DBG_PROTOCOL | DBG_INIT,
  1660. ("[ClUnbindFromLowerMp]: Adapter %08X, calling NdisIMCancelDeviceInstance with %ws \n",
  1661. Adapter, Adapter->UpperBinding.Buffer));
  1662. *Status = NdisIMCancelInitializeDeviceInstance(LmDriverHandle, &Adapter->UpperBinding);
  1663. if(*Status != NDIS_STATUS_SUCCESS)
  1664. {
  1665. //
  1666. // An mpinitialize is in progress or is going to happen soon. Let's wait for it to
  1667. // complete.
  1668. //
  1669. PsDbgOut(DBG_INFO,
  1670. DBG_PROTOCOL | DBG_INIT,
  1671. ("[ClUnbindFromLowerMp]: Adapter %08X, Waiting for MpInitialize to "
  1672. "finish (NdisIMCancelDeviceInstance failed) \n", Adapter));
  1673. NdisWaitEvent(&Adapter->MpInitializeEvent, 0);
  1674. //
  1675. // The MpInitialize (that we could have been waiting for in the above step) could have failed :
  1676. // So we need to check this handle again.
  1677. //
  1678. if(Adapter->PsNdisHandle)
  1679. {
  1680. *Status = NdisIMDeInitializeDeviceInstance(Adapter->PsNdisHandle);
  1681. PsDbgOut(DBG_INFO,
  1682. DBG_PROTOCOL | DBG_INIT,
  1683. ("[ClUnbindFromLowerMp]: Adapter %08X, deiniting device, "
  1684. "status %x\n", Adapter, *Status));
  1685. goto Done;
  1686. }
  1687. }
  1688. else
  1689. {
  1690. //
  1691. // Great. We can be assured that we will never get called in the MpInitializeHandler anymore.
  1692. // Proceed to close the binding below.
  1693. //
  1694. }
  1695. }
  1696. }
  1697. //
  1698. // Close the open. We have to do this only if we don't call NdisIMDeInitializeDeviceInstance. If
  1699. // we ever call NdisIMDeInitializeDeviceInstance, then we close the open in the MpHalt handler.
  1700. //
  1701. if(Adapter->LowerMpHandle)
  1702. {
  1703. NdisCloseAdapter(Status, Adapter->LowerMpHandle);
  1704. PsDbgOut(DBG_INFO,
  1705. DBG_PROTOCOL | DBG_INIT,
  1706. ("[ClUnbindFromLowerMp]: Adapter %08X, closing adapter, "
  1707. "status %x\n", Adapter, *Status));
  1708. if (*Status == NDIS_STATUS_PENDING)
  1709. {
  1710. NdisWaitEvent(&Adapter->BlockingEvent, 0);
  1711. NdisResetEvent(&Adapter->BlockingEvent);
  1712. *Status = Adapter->FinalStatus;
  1713. }
  1714. REFDEL(&Adapter->RefCount, FALSE, 'NDOP');
  1715. }
  1716. else
  1717. {
  1718. PsDbgOut(DBG_CRITICAL_ERROR,
  1719. DBG_PROTOCOL | DBG_INIT,
  1720. ("[ClUnbindFromLowerMp]: Adapter %08X, unbind cannot deinit/close adpater \n",
  1721. Adapter));
  1722. *Status = NDIS_STATUS_FAILURE;
  1723. PsAssert(0);
  1724. }
  1725. Done:
  1726. PsDbgOut(DBG_INFO,
  1727. DBG_PROTOCOL | DBG_INIT,
  1728. ("[ClUnbindFromLowerMp]: Exiting with Status = %08X \n", *Status));
  1729. DRIVER_COUNTED_UNBLOCK;
  1730. } // UnbindAdapter
  1731. VOID
  1732. DeleteAdapter(
  1733. PVOID Handle,
  1734. BOOLEAN AdapterListLocked
  1735. )
  1736. /*++
  1737. Routine Description:
  1738. Decrement the ref counter associated with this structure. When it goes to
  1739. zero, close the adapter, and delete the memory associated with the struct
  1740. Arguments:
  1741. Adapter - pointer to adapter context block
  1742. Return Value:
  1743. number of references remaining associated with this structure
  1744. --*/
  1745. {
  1746. PADAPTER Adapter = (PADAPTER) Handle;
  1747. Adapter->PsMpState = AdapterStateClosed;
  1748. //
  1749. // if we initialized the pipe, tell the scheduler that this pipe is going away
  1750. //
  1751. if ( Adapter->MediaType != NdisMediumWan && Adapter->ShutdownMask & SHUTDOWN_DELETE_PIPE ) {
  1752. (*Adapter->PsComponent->DeletePipe)( Adapter->PsPipeContext );
  1753. }
  1754. if ( Adapter->ShutdownMask & SHUTDOWN_FREE_PS_CONTEXT ) {
  1755. PsFreePool(Adapter->PsPipeContext);
  1756. }
  1757. if(Adapter->pDiffServMapping)
  1758. {
  1759. PsFreePool(Adapter->pDiffServMapping);
  1760. }
  1761. //
  1762. // return packet pool resources
  1763. //
  1764. if(Adapter->SendPacketPool != 0)
  1765. {
  1766. NdisFreePacketPool(Adapter->SendPacketPool);
  1767. }
  1768. if(Adapter->RecvPacketPool != 0)
  1769. {
  1770. NdisFreePacketPool(Adapter->RecvPacketPool);
  1771. }
  1772. if(Adapter->SendBlockPool)
  1773. {
  1774. NdisDestroyBlockPool(Adapter->SendBlockPool);
  1775. }
  1776. //
  1777. // free adapter lock from dispatcher DB
  1778. //
  1779. NdisFreeSpinLock(&Adapter->Lock);
  1780. //
  1781. // Free various allocations for the adapter, then the adapter
  1782. //
  1783. if(Adapter->IpNetAddressList){
  1784. PsFreePool(Adapter->IpNetAddressList);
  1785. }
  1786. if(Adapter->IpxNetAddressList){
  1787. PsFreePool(Adapter->IpxNetAddressList);
  1788. }
  1789. if(Adapter->MpDeviceName.Buffer) {
  1790. PsFreePool(Adapter->MpDeviceName.Buffer);
  1791. }
  1792. if(Adapter->UpperBinding.Buffer) {
  1793. PsFreePool(Adapter->UpperBinding.Buffer);
  1794. }
  1795. if(Adapter->RegistryPath.Buffer) {
  1796. PsFreePool(Adapter->RegistryPath.Buffer);
  1797. }
  1798. if(Adapter->WMIInstanceName.Buffer) {
  1799. //
  1800. // We should not call PsFreePool since this memory is allocated by NDIS
  1801. //
  1802. ExFreePool(Adapter->WMIInstanceName.Buffer);
  1803. }
  1804. if(Adapter->ProfileName.Buffer) {
  1805. PsFreePool(Adapter->ProfileName.Buffer);
  1806. }
  1807. if(!AdapterListLocked)
  1808. {
  1809. PS_LOCK(&AdapterListLock);
  1810. RemoveEntryList(&Adapter->Linkage);
  1811. PS_UNLOCK(&AdapterListLock);
  1812. }
  1813. else
  1814. {
  1815. RemoveEntryList(&Adapter->Linkage);
  1816. }
  1817. NdisSetEvent(&Adapter->RefEvent);
  1818. PsFreePool(Adapter);
  1819. }
  1820. VOID
  1821. ClLowerMpCloseAdapterComplete(
  1822. IN NDIS_HANDLE ProtocolBindingContext,
  1823. IN NDIS_STATUS Status
  1824. )
  1825. /*++
  1826. Routine Description:
  1827. Completion routine for NdisCloseAdapter. All that should be left is to free
  1828. the pool associated with the structure
  1829. Arguments:
  1830. See the DDK...
  1831. Return Values:
  1832. None
  1833. --*/
  1834. {
  1835. PADAPTER Adapter = (PADAPTER)ProtocolBindingContext;
  1836. PsDbgOut(DBG_TRACE,
  1837. DBG_PROTOCOL,
  1838. ("[ClLowerMpCloseAdapterComplete]: Adapter %08X \n", Adapter));
  1839. PsStructAssert( Adapter );
  1840. PsAssert(Status == NDIS_STATUS_SUCCESS);
  1841. Adapter->FinalStatus = Status;
  1842. Adapter->LowerMpHandle = 0;
  1843. //
  1844. // Clean up WanLinks. This cannot be done (in CleanUpAdapter) before we call NdisCloseAdapter, because
  1845. // NDIS can unbind us in the middle of an ClStatusIndication, and can cause a race condition. Also, we
  1846. // can all PsDeleteDevice only after this (because we might want to send some status indications.
  1847. //
  1848. AskWanLinksToClose(Adapter);
  1849. PsDeleteDevice();
  1850. NdisSetEvent(&Adapter->BlockingEvent);
  1851. } // LowerMpCloseAdapterComplete
  1852. VOID
  1853. ClUnloadProtocol(
  1854. VOID
  1855. )
  1856. /*++
  1857. Routine Description:
  1858. Arguments:
  1859. None
  1860. Return Value:
  1861. None
  1862. --*/
  1863. {
  1864. }
  1865. VOID
  1866. MpHalt(
  1867. IN NDIS_HANDLE MiniportAdapterContext
  1868. )
  1869. /*++
  1870. Routine Description:
  1871. This handler is called on Memphis. It indicates that the PS MP is no more
  1872. and we should avoid calling NdisIMDeInitializeDeviceInstance...
  1873. Arguments:
  1874. See the DDK...
  1875. Return Values:
  1876. None
  1877. --*/
  1878. {
  1879. PADAPTER Adapter = (PADAPTER)MiniportAdapterContext;
  1880. ULONG Status;
  1881. PsDbgOut(DBG_TRACE, DBG_MINIPORT, ("[MpHalt]: Adapter %08X\n", Adapter));
  1882. PsStructAssert(Adapter);
  1883. PsAssert(!(Adapter->ShutdownMask & SHUTDOWN_MPHALT_CALLED));
  1884. PsAssert(!(Adapter->ShutdownMask & SHUTDOWN_PROTOCOL_UNLOAD));
  1885. PS_LOCK(&Adapter->Lock);
  1886. //
  1887. // If we ever get called in our unbind handler, we should not call
  1888. // NdisImDeInitializeDeviceInstance.
  1889. //
  1890. Adapter->ShutdownMask |= SHUTDOWN_MPHALT_CALLED;
  1891. Adapter->PsMpState = AdapterStateClosing;
  1892. if(!(Adapter->ShutdownMask & SHUTDOWN_CLEANUP_ADAPTER))
  1893. {
  1894. Adapter->ShutdownMask |= SHUTDOWN_CLEANUP_ADAPTER;
  1895. PS_UNLOCK(&Adapter->Lock);
  1896. CleanUpAdapter(Adapter);
  1897. }
  1898. else
  1899. {
  1900. PS_UNLOCK(&Adapter->Lock);
  1901. }
  1902. //
  1903. // Close the b/e VC in the mphalt call. This prevents us from taking a lock
  1904. // in the send path. We are assured that we will not get any sends after we
  1905. // get called in the mphalt handler.
  1906. //
  1907. if(Adapter->MediaType != NdisMediumWan)
  1908. {
  1909. PS_LOCK(&Adapter->Lock);
  1910. PS_LOCK_DPC(&Adapter->BestEffortVc.Lock);
  1911. InternalCloseCall(&Adapter->BestEffortVc);
  1912. }
  1913. if(Adapter->LowerMpHandle) {
  1914. NdisCloseAdapter(&Status, Adapter->LowerMpHandle);
  1915. if(Status == NDIS_STATUS_PENDING) {
  1916. NdisWaitEvent(&Adapter->BlockingEvent, 0);
  1917. NdisResetEvent(&Adapter->BlockingEvent);
  1918. Status = Adapter->FinalStatus;
  1919. }
  1920. REFDEL(&Adapter->RefCount, FALSE, 'NDOP');
  1921. }
  1922. //
  1923. // Deref for the MpInitialize
  1924. //
  1925. REFDEL(&Adapter->RefCount, FALSE, 'NDHT');
  1926. }
  1927. HANDLE
  1928. GetNdisPipeHandle (
  1929. IN HANDLE PsPipeContext
  1930. )
  1931. /*++
  1932. Routine Description:
  1933. Return the NDIS handle for the adapter to the requesting scheduling component.
  1934. Arguments:
  1935. PsPipeContext - Pipe context
  1936. Return Values:
  1937. Adapter NDIS handle.
  1938. --*/
  1939. {
  1940. return ((PADAPTER)PsPipeContext)->PsNdisHandle;
  1941. } // GetNdisPipeHandle
  1942. STATIC NDIS_STATUS
  1943. FindProfile(
  1944. PNDIS_STRING ProfileName,
  1945. PPS_PROFILE *Profile
  1946. )
  1947. /*++
  1948. Routine Description:
  1949. Find the named profile in the list of profiles
  1950. Arguments
  1951. ProfileName - Name of the profile to look for.
  1952. Return Value:
  1953. NDIS_STATUS_SUCCESS if everything worked ok
  1954. e--*/
  1955. {
  1956. NDIS_STATUS Status;
  1957. PLIST_ENTRY NextComponent;
  1958. PPS_PROFILE PsiInfo;
  1959. //
  1960. // compare names until we find the right one
  1961. //
  1962. NextComponent = PsProfileList.Flink;
  1963. while ( NextComponent != &PsProfileList ) {
  1964. PsiInfo = CONTAINING_RECORD( NextComponent, PS_PROFILE, Links );
  1965. if ( ProfileName->Length == PsiInfo->ProfileName.Length ) {
  1966. if ( NdisEqualMemory(
  1967. ProfileName->Buffer,
  1968. PsiInfo->ProfileName.Buffer,
  1969. ProfileName->Length )) {
  1970. break;
  1971. }
  1972. }
  1973. NextComponent = NextComponent->Flink;
  1974. }
  1975. if ( NextComponent != &PsProfileList ) {
  1976. *Profile = PsiInfo;
  1977. Status = NDIS_STATUS_SUCCESS;
  1978. } else {
  1979. Status = NDIS_STATUS_FAILURE;
  1980. }
  1981. return Status;
  1982. } // FindProfile
  1983. NDIS_STATUS
  1984. InitializeAdapter(
  1985. PADAPTER Adapter,
  1986. PVOID BindContext,
  1987. PNDIS_STRING MpDeviceName,
  1988. PVOID SystemSpecific1)
  1989. {
  1990. NDIS_STATUS LocalStatus;
  1991. PNDIS_STRING PsParamsKey = (PNDIS_STRING) SystemSpecific1;
  1992. NdisZeroMemory(Adapter, sizeof(ADAPTER));
  1993. PS_INIT_SPIN_LOCK(&Adapter->Lock);
  1994. REFINIT(&Adapter->RefCount, Adapter, DeleteAdapter);
  1995. REFADD(&Adapter->RefCount, 'NDOP');
  1996. Adapter->PsMpState = AdapterStateInitializing;
  1997. Adapter->BindContext = BindContext;
  1998. Adapter->ShutdownMask = 0;
  1999. NdisInitializeEvent(&Adapter->BlockingEvent);
  2000. NdisResetEvent(&Adapter->BlockingEvent);
  2001. NdisInitializeEvent(&Adapter->RefEvent);
  2002. NdisResetEvent(&Adapter->RefEvent);
  2003. NdisInitializeEvent(&Adapter->LocalRequestEvent);
  2004. NdisResetEvent(&Adapter->LocalRequestEvent);
  2005. NdisInitializeEvent(&Adapter->MpInitializeEvent);
  2006. NdisResetEvent(&Adapter->MpInitializeEvent);
  2007. //
  2008. // Initialize the Lists that we are maintaining
  2009. //
  2010. InitializeListHead(&Adapter->WanLinkList);
  2011. InitializeListHead(&Adapter->GpcClientVcList);
  2012. //
  2013. // By default, Adapter comes in RSVP mode
  2014. //
  2015. Adapter->AdapterMode = AdapterModeRsvpFlow;
  2016. //
  2017. // add adapter on list of known adapters
  2018. //
  2019. NdisInterlockedInsertTailList(&AdapterList,
  2020. &Adapter->Linkage,
  2021. &AdapterListLock.Lock );
  2022. PsAddDevice();
  2023. //
  2024. // We maintain a list of network addresses enabled on
  2025. // each adapter, for IP and for IPX, separately.
  2026. //
  2027. PsAllocatePool(Adapter->IpNetAddressList,
  2028. sizeof(NETWORK_ADDRESS_LIST),
  2029. PsMiscTag);
  2030. if(!Adapter->IpNetAddressList)
  2031. {
  2032. goto ERROR_RESOURCES;
  2033. }
  2034. Adapter->IpNetAddressList->AddressCount = 0;
  2035. PsAllocatePool(Adapter->IpxNetAddressList,
  2036. sizeof(NETWORK_ADDRESS_LIST),
  2037. PsMiscTag);
  2038. if(!Adapter->IpxNetAddressList)
  2039. {
  2040. goto ERROR_RESOURCES;
  2041. }
  2042. Adapter->IpxNetAddressList->AddressCount = 0;
  2043. //
  2044. // Allocate a buffer to hold the name of the underlying
  2045. // adpater.
  2046. //
  2047. Adapter->MpDeviceName.Length = MpDeviceName->Length;
  2048. Adapter->MpDeviceName.MaximumLength = MpDeviceName->MaximumLength;
  2049. PsAllocatePool(Adapter->MpDeviceName.Buffer,
  2050. MpDeviceName->MaximumLength,
  2051. PsMiscTag);
  2052. if(Adapter->MpDeviceName.Buffer == NULL)
  2053. {
  2054. goto ERROR_RESOURCES;
  2055. }
  2056. else
  2057. {
  2058. NdisZeroMemory(
  2059. Adapter->MpDeviceName.Buffer,
  2060. Adapter->MpDeviceName.MaximumLength);
  2061. NdisMoveMemory(
  2062. Adapter->MpDeviceName.Buffer,
  2063. MpDeviceName->Buffer,
  2064. MpDeviceName->Length);
  2065. }
  2066. //
  2067. // Allocate a buffer to hold PsParams Key. This will be
  2068. // used by the adapter to read external scheduling component
  2069. // specific interface parameters when they register.
  2070. //
  2071. Adapter->RegistryPath.Length = PsParamsKey->Length;
  2072. Adapter->RegistryPath.MaximumLength = PsParamsKey->MaximumLength;
  2073. PsAllocatePool(Adapter->RegistryPath.Buffer,
  2074. Adapter->RegistryPath.MaximumLength,
  2075. PsMiscTag);
  2076. if(Adapter->RegistryPath.Buffer == NULL)
  2077. {
  2078. goto ERROR_RESOURCES;
  2079. }
  2080. else
  2081. {
  2082. NdisMoveMemory(
  2083. Adapter->RegistryPath.Buffer,
  2084. PsParamsKey->Buffer,
  2085. PsParamsKey->MaximumLength);
  2086. }
  2087. //
  2088. // Read the per adapter registry info
  2089. //
  2090. LocalStatus = PsReadAdapterRegistryDataInit(Adapter,
  2091. (PNDIS_STRING)SystemSpecific1);
  2092. if(LocalStatus != NDIS_STATUS_SUCCESS)
  2093. {
  2094. PsDbgOut(DBG_FAILURE,
  2095. DBG_PROTOCOL | DBG_INIT,
  2096. ("[InitializeAdapter]: Couldn't get registry data %ws (Status = %08X) \n",
  2097. MpDeviceName->Buffer, LocalStatus));
  2098. return LocalStatus;
  2099. }
  2100. LocalStatus = PsReadAdapterRegistryData(Adapter,
  2101. &MachineRegistryKey,
  2102. (PNDIS_STRING)SystemSpecific1);
  2103. if(LocalStatus != NDIS_STATUS_SUCCESS)
  2104. {
  2105. PsDbgOut(DBG_FAILURE,
  2106. DBG_PROTOCOL | DBG_INIT,
  2107. ("[InitializeAdapter]: Couldn't get registry data %ws (Status = %08X) \n",
  2108. MpDeviceName->Buffer, LocalStatus));
  2109. }
  2110. return LocalStatus;
  2111. ERROR_RESOURCES:
  2112. PsAdapterWriteEventLog(
  2113. (ULONG)EVENT_PS_RESOURCE_POOL,
  2114. 0,
  2115. MpDeviceName,
  2116. 0,
  2117. NULL);
  2118. return NDIS_STATUS_RESOURCES;
  2119. }
  2120. NDIS_STATUS
  2121. FindSchedulingComponent(
  2122. PNDIS_STRING ComponentName,
  2123. PPSI_INFO *Component
  2124. )
  2125. /*++
  2126. Routine Description:
  2127. Find the named component in the list of external scheduling components
  2128. Arguments:
  2129. ComponentName - name of component to look for
  2130. Return Value:
  2131. NDIS_STATUS_SUCCESS if everything worked ok
  2132. --*/
  2133. {
  2134. NDIS_STATUS Status;
  2135. PLIST_ENTRY NextComponent;
  2136. PPSI_INFO PsiInfo;
  2137. //
  2138. // get the list lock and compare names until we find the right one
  2139. //
  2140. NextComponent = PsComponentList.Flink;
  2141. while ( NextComponent != &PsComponentList ) {
  2142. PsiInfo = CONTAINING_RECORD( NextComponent, PSI_INFO, Links );
  2143. if ( ComponentName->Length == PsiInfo->ComponentName.Length ) {
  2144. if ( NdisEqualMemory(
  2145. ComponentName->Buffer,
  2146. PsiInfo->ComponentName.Buffer,
  2147. ComponentName->Length )) {
  2148. break;
  2149. }
  2150. }
  2151. NextComponent = NextComponent->Flink;
  2152. }
  2153. if ( NextComponent != &PsComponentList ) {
  2154. *Component = PsiInfo;
  2155. Status = NDIS_STATUS_SUCCESS;
  2156. } else {
  2157. Status = NDIS_STATUS_FAILURE;
  2158. }
  2159. return Status;
  2160. } // FindSchedulingComponent
  2161. VOID
  2162. CloseAllGpcVcs(
  2163. PADAPTER Adapter
  2164. )
  2165. /*++
  2166. Routine Description:
  2167. Close all the VCs associated with an adapter
  2168. Return Value:
  2169. None
  2170. --*/
  2171. {
  2172. PGPC_CLIENT_VC Vc;
  2173. PLIST_ENTRY NextVc;
  2174. //
  2175. // Close all the GPC client VCs.
  2176. //
  2177. PS_LOCK(&Adapter->Lock);
  2178. NextVc = Adapter->GpcClientVcList.Flink;
  2179. while(NextVc != &Adapter->GpcClientVcList)
  2180. {
  2181. Vc = CONTAINING_RECORD(NextVc, GPC_CLIENT_VC, Linkage);
  2182. PsAssert(Vc);
  2183. PS_LOCK_DPC(&Vc->Lock);
  2184. if(Vc->ClVcState == CL_INTERNAL_CLOSE_PENDING || Vc->Flags & INTERNAL_CLOSE_REQUESTED)
  2185. {
  2186. PS_UNLOCK_DPC(&Vc->Lock);
  2187. NextVc = NextVc->Flink;
  2188. }
  2189. else
  2190. {
  2191. InternalCloseCall(Vc);
  2192. PS_LOCK(&Adapter->Lock);
  2193. //
  2194. // Sigh. We can't really get hold to the NextVc in a reliable manner. When we call
  2195. // InternalCloseCall on the Vc, it releases the Adapter Lock (since it might have to
  2196. // make calls into NDIS). Now, in this window, the next Vc could go away, and we
  2197. // could point to a stale Vc. So, we start at the head of the list.
  2198. // Note that this can never lead to a infinite loop, since we don't process the
  2199. // internal close'd VCs repeatedly.
  2200. //
  2201. NextVc = Adapter->GpcClientVcList.Flink;
  2202. }
  2203. }
  2204. PS_UNLOCK(&Adapter->Lock);
  2205. } // CloseAllGpcVcs
  2206. VOID
  2207. PsAdapterWriteEventLog(
  2208. IN NDIS_STATUS EventCode,
  2209. IN ULONG UniqueEventValue,
  2210. IN PNDIS_STRING DeviceName,
  2211. IN ULONG DataSize,
  2212. IN PVOID Data OPTIONAL
  2213. )
  2214. {
  2215. //
  2216. // The String List is the device name, and it has a \Device against it.
  2217. //
  2218. PWCHAR StringList[1];
  2219. NDIS_STRING Prefix = NDIS_STRING_CONST("\\Device\\");
  2220. if(DeviceName->Length > Prefix.Length)
  2221. {
  2222. StringList[0] = (PWCHAR) ((PUCHAR) DeviceName->Buffer + Prefix.Length);
  2223. NdisWriteEventLogEntry(PsDriverObject,
  2224. EventCode,
  2225. UniqueEventValue,
  2226. 1,
  2227. &StringList,
  2228. DataSize,
  2229. Data);
  2230. }
  2231. }
  2232. /* end adapter.c */