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.

1321 lines
33 KiB

  1. /*++
  2. Copyright (c) 1997-2000 Microsoft Corporation
  3. Module Name:
  4. fdo.c
  5. Abstract:
  6. This module provides the functions which answer IRPs to functional devices.
  7. Author:
  8. Andy Thornton (andrewth) 20-Oct-97
  9. Revision History:
  10. --*/
  11. #include "mfp.h"
  12. /*++
  13. The majority of functions in this file are called based on their presence
  14. in Pnp and Po dispatch tables. In the interests of brevity the arguments
  15. to all those functions will be described below:
  16. NTSTATUS
  17. MfXxxFdo(
  18. IN PIRP Irp,
  19. IN PMF_PARENT_EXTENSION Parent,
  20. IN PIO_STACK_LOCATION IrpStack
  21. )
  22. Routine Description:
  23. This function handles the Xxx requests for multifunction FDO's
  24. Arguments:
  25. Irp - Points to the IRP associated with this request.
  26. Parent - Points to the parent FDO's device extension.
  27. IrpStack - Points to the current stack location for this request.
  28. Return Value:
  29. Status code that indicates whether or not the function was successful.
  30. STATUS_NOT_SUPPORTED indicates that the IRP should be passed down without
  31. changing the Irp->IoStatus.Status field otherwise it is updated with this
  32. status.
  33. --*/
  34. NTSTATUS
  35. MfDeferProcessingFdo(
  36. IN PMF_PARENT_EXTENSION Parent,
  37. IN OUT PIRP Irp
  38. );
  39. NTSTATUS
  40. MfStartFdo(
  41. IN PIRP Irp,
  42. IN PMF_PARENT_EXTENSION Parent,
  43. IN PIO_STACK_LOCATION IrpStack
  44. );
  45. NTSTATUS
  46. MfStartFdoCompletion(
  47. IN PDEVICE_OBJECT DeviceObject,
  48. IN PIRP Irp,
  49. IN PVOID Context
  50. );
  51. NTSTATUS
  52. MfStartFdoInitializeArbiters(
  53. IN PMF_PARENT_EXTENSION Parent,
  54. IN PCM_RESOURCE_LIST ResList,
  55. IN PCM_RESOURCE_LIST TranslatedResList
  56. );
  57. NTSTATUS
  58. MfQueryStopFdo(
  59. IN PIRP Irp,
  60. IN PMF_PARENT_EXTENSION Parent,
  61. IN PIO_STACK_LOCATION IrpStack
  62. );
  63. NTSTATUS
  64. MfCancelStopFdo(
  65. IN PIRP Irp,
  66. IN PMF_PARENT_EXTENSION Parent,
  67. IN PIO_STACK_LOCATION IrpStack
  68. );
  69. NTSTATUS
  70. MfQueryRemoveFdo(
  71. IN PIRP Irp,
  72. IN PMF_PARENT_EXTENSION Parent,
  73. IN PIO_STACK_LOCATION IrpStack
  74. );
  75. NTSTATUS
  76. MfRemoveFdo(
  77. IN PIRP Irp,
  78. IN PMF_PARENT_EXTENSION Parent,
  79. IN PIO_STACK_LOCATION IrpStack
  80. );
  81. NTSTATUS
  82. MfSurpriseRemoveFdo(
  83. IN PIRP Irp,
  84. IN PMF_PARENT_EXTENSION Parent,
  85. IN PIO_STACK_LOCATION IrpStack
  86. );
  87. NTSTATUS
  88. MfCancelRemoveFdo(
  89. IN PIRP Irp,
  90. IN PMF_PARENT_EXTENSION Parent,
  91. IN PIO_STACK_LOCATION IrpStack
  92. );
  93. NTSTATUS
  94. MfQueryDeviceRelationsFdo(
  95. IN PIRP Irp,
  96. IN PMF_PARENT_EXTENSION Parent,
  97. IN PIO_STACK_LOCATION IrpStack
  98. );
  99. NTSTATUS
  100. MfQueryInterfaceFdo(
  101. IN PIRP Irp,
  102. IN PMF_PARENT_EXTENSION Parent,
  103. IN PIO_STACK_LOCATION IrpStack
  104. );
  105. NTSTATUS
  106. MfQueryCapabilitiesFdo(
  107. IN PIRP Irp,
  108. IN PMF_PARENT_EXTENSION Parent,
  109. IN PIO_STACK_LOCATION IrpStack
  110. );
  111. NTSTATUS
  112. MfQueryPowerFdo(
  113. IN PIRP Irp,
  114. IN PMF_PARENT_EXTENSION Parent,
  115. IN PIO_STACK_LOCATION IrpStack
  116. );
  117. NTSTATUS
  118. MfSetPowerFdo(
  119. IN PIRP Irp,
  120. IN PMF_PARENT_EXTENSION Parent,
  121. IN PIO_STACK_LOCATION IrpStack
  122. );
  123. NTSTATUS
  124. MfPassIrp(
  125. IN PIRP Irp,
  126. IN PMF_PARENT_EXTENSION Parent,
  127. IN PIO_STACK_LOCATION IrpStack
  128. );
  129. #ifdef ALLOC_PRAGMA
  130. #pragma alloc_text(PAGE, MfCancelRemoveFdo)
  131. #pragma alloc_text(PAGE, MfCancelStopFdo)
  132. #pragma alloc_text(PAGE, MfCreateFdo)
  133. #pragma alloc_text(PAGE, MfDeferProcessingFdo)
  134. #pragma alloc_text(PAGE, MfDispatchPnpFdo)
  135. #pragma alloc_text(PAGE, MfPassIrp)
  136. #pragma alloc_text(PAGE, MfQueryCapabilitiesFdo)
  137. #pragma alloc_text(PAGE, MfQueryDeviceRelationsFdo)
  138. #pragma alloc_text(PAGE, MfQueryInterfaceFdo)
  139. #pragma alloc_text(PAGE, MfQueryRemoveFdo)
  140. #pragma alloc_text(PAGE, MfQueryStopFdo)
  141. #pragma alloc_text(PAGE, MfRemoveFdo)
  142. #pragma alloc_text(PAGE, MfStartFdo)
  143. #pragma alloc_text(PAGE, MfStartFdoInitializeArbiters)
  144. #pragma alloc_text(PAGE, MfSurpriseRemoveFdo)
  145. #endif
  146. PMF_DISPATCH MfPnpDispatchTableFdo[] = {
  147. MfStartFdo, // IRP_MN_START_DEVICE
  148. MfQueryRemoveFdo, // IRP_MN_QUERY_REMOVE_DEVICE
  149. MfRemoveFdo, // IRP_MN_REMOVE_DEVICE
  150. MfCancelRemoveFdo, // IRP_MN_CANCEL_REMOVE_DEVICE
  151. MfPassIrp, // IRP_MN_STOP_DEVICE
  152. MfQueryStopFdo, // IRP_MN_QUERY_STOP_DEVICE
  153. MfCancelStopFdo, // IRP_MN_CANCEL_STOP_DEVICE
  154. MfQueryDeviceRelationsFdo, // IRP_MN_QUERY_DEVICE_RELATIONS
  155. MfQueryInterfaceFdo, // IRP_MN_QUERY_INTERFACE
  156. MfQueryCapabilitiesFdo, // IRP_MN_QUERY_CAPABILITIES
  157. MfPassIrp, // IRP_MN_QUERY_RESOURCES
  158. MfPassIrp, // IRP_MN_QUERY_RESOURCE_REQUIREMENTS
  159. MfPassIrp, // IRP_MN_QUERY_DEVICE_TEXT
  160. MfPassIrp, // IRP_MN_FILTER_RESOURCE_REQUIREMENTS
  161. MfPassIrp, // Unused
  162. MfPassIrp, // IRP_MN_READ_CONFIG
  163. MfPassIrp, // IRP_MN_WRITE_CONFIG
  164. MfPassIrp, // IRP_MN_EJECT
  165. MfPassIrp, // IRP_MN_SET_LOCK
  166. MfPassIrp, // IRP_MN_QUERY_ID
  167. MfPassIrp, // IRP_MN_QUERY_PNP_DEVICE_STATE
  168. MfPassIrp, // IRP_MN_QUERY_BUS_INFORMATION
  169. MfDeviceUsageNotificationCommon,// IRP_MN_DEVICE_USAGE_NOTIFICATION
  170. MfSurpriseRemoveFdo, // IRP_MN_SURPRISE_REMOVAL
  171. MfPassIrp // IRP_MN_QUERY_LEGACY_BUS_INFORMATION
  172. };
  173. PMF_DISPATCH MfPoDispatchTableFdo[] = {
  174. NULL, // IRP_MN_WAIT_WAKE
  175. NULL, // IRP_MN_POWER_SEQUENCE
  176. MfSetPowerFdo, // IRP_MN_SET_POWER
  177. MfQueryPowerFdo // IRP_MN_QUERY_POWER
  178. };
  179. NTSTATUS
  180. MfCreateFdo(
  181. OUT PDEVICE_OBJECT *Fdo
  182. )
  183. /*++
  184. Routine Description:
  185. This function creates a new FDO and initializes it.
  186. Arguments:
  187. Fdo - Pointer to where the FDO should be returned
  188. Return Value:
  189. Status code that indicates whether or not the function was successful.
  190. --*/
  191. {
  192. NTSTATUS status;
  193. PMF_PARENT_EXTENSION extension;
  194. PAGED_CODE();
  195. ASSERT((sizeof(MfPnpDispatchTableFdo) / sizeof(PMF_DISPATCH)) - 1
  196. == IRP_MN_PNP_MAXIMUM_FUNCTION);
  197. ASSERT((sizeof(MfPoDispatchTableFdo) / sizeof(PMF_DISPATCH)) -1
  198. == IRP_MN_PO_MAXIMUM_FUNCTION);
  199. *Fdo = NULL;
  200. status = IoCreateDevice(MfDriverObject,
  201. sizeof(MF_PARENT_EXTENSION),
  202. NULL,
  203. FILE_DEVICE_BUS_EXTENDER,
  204. FILE_DEVICE_SECURE_OPEN,
  205. FALSE,
  206. Fdo
  207. );
  208. if (!NT_SUCCESS(status)) {
  209. goto cleanup;
  210. }
  211. //
  212. // Initialize the extension
  213. //
  214. extension = (PMF_PARENT_EXTENSION) (*Fdo)->DeviceExtension;
  215. MfInitCommonExtension(&extension->Common, MfFunctionalDeviceObject);
  216. extension->Self = *Fdo;
  217. InitializeListHead(&extension->Arbiters);
  218. InitializeListHead(&extension->Children);
  219. KeInitializeEvent(&extension->ChildrenLock, SynchronizationEvent, TRUE);
  220. KeInitializeSpinLock(&extension->PowerLock);
  221. IoInitializeRemoveLock(&extension->RemoveLock, MF_POOL_TAG, 1, 20);
  222. extension->Common.PowerState = PowerDeviceD3;
  223. DEBUG_MSG(1, ("Created FDO @ 0x%08x\n", *Fdo));
  224. return status;
  225. cleanup:
  226. if (*Fdo) {
  227. IoDeleteDevice(*Fdo);
  228. }
  229. return status;
  230. }
  231. VOID
  232. MfAcquireChildrenLock(
  233. IN PMF_PARENT_EXTENSION Parent
  234. )
  235. {
  236. KeWaitForSingleObject(&Parent->ChildrenLock,
  237. Executive,
  238. KernelMode,
  239. FALSE,
  240. NULL);
  241. }
  242. VOID
  243. MfReleaseChildrenLock(
  244. IN PMF_PARENT_EXTENSION Parent
  245. )
  246. {
  247. KeSetEvent(&Parent->ChildrenLock, 0, FALSE);
  248. }
  249. VOID
  250. MfDeleteFdo(
  251. IN PDEVICE_OBJECT Fdo
  252. )
  253. {
  254. PMF_PARENT_EXTENSION parent = Fdo->DeviceExtension;
  255. PMF_ARBITER current, next;
  256. if (parent->Common.DeviceState & MF_DEVICE_DELETED) {
  257. //
  258. // Trying to delete twice
  259. //
  260. ASSERT(!(parent->Common.DeviceState & MF_DEVICE_DELETED));
  261. return;
  262. }
  263. parent->Common.DeviceState = MF_DEVICE_DELETED;
  264. //
  265. // Free up any memory we have allocated
  266. //
  267. if (parent->ResourceList) {
  268. ExFreePool(parent->ResourceList);
  269. parent->ResourceList = NULL;
  270. }
  271. if (parent->TranslatedResourceList) {
  272. ExFreePool(parent->TranslatedResourceList);
  273. parent->TranslatedResourceList = NULL;
  274. }
  275. if (parent->DeviceID.Buffer) {
  276. RtlFreeUnicodeString(&parent->DeviceID);
  277. }
  278. if (parent->InstanceID.Buffer) {
  279. RtlFreeUnicodeString(&parent->InstanceID);
  280. }
  281. FOR_ALL_IN_LIST_SAFE(MF_ARBITER, &parent->Arbiters, current, next) {
  282. RemoveEntryList(&current->ListEntry);
  283. ArbDeleteArbiterInstance(&current->Instance);
  284. ExFreePool(current);
  285. }
  286. ASSERT(IsListEmpty(&parent->Children));
  287. IoDeleteDevice(Fdo);
  288. DEBUG_MSG(1, ("Deleted FDO @ 0x%08x\n", Fdo));
  289. }
  290. NTSTATUS
  291. MfPassIrp(
  292. IN PIRP Irp,
  293. IN PMF_PARENT_EXTENSION Parent,
  294. IN PIO_STACK_LOCATION IrpStack
  295. )
  296. {
  297. PAGED_CODE();
  298. IoSkipCurrentIrpStackLocation(Irp);
  299. return IoCallDriver(Parent->AttachedDevice, Irp);
  300. }
  301. NTSTATUS
  302. MfDispatchPnpFdo(
  303. IN PDEVICE_OBJECT DeviceObject,
  304. IN PMF_PARENT_EXTENSION Parent,
  305. IN PIO_STACK_LOCATION IrpStack,
  306. IN OUT PIRP Irp
  307. )
  308. /*++
  309. Routine Description:
  310. This routine handles IRP_MJ_PNP IRPs for FDOs.
  311. Arguments:
  312. DeviceObject - Pointer to the FDO for which this IRP applies.
  313. Parent - FDO extension
  314. IrpStack - Current stack location
  315. Irp - Pointer to the IRP_MJ_PNP IRP to dispatch.
  316. Return Value:
  317. NT status.
  318. --*/
  319. {
  320. NTSTATUS status;
  321. BOOLEAN isRemoveDevice;
  322. PAGED_CODE();
  323. //
  324. // Get a pointer to our stack location and take appropriate action based
  325. // on the minor function.
  326. //
  327. IoAcquireRemoveLock(&Parent->RemoveLock, (PVOID) Irp);
  328. isRemoveDevice = IrpStack->MinorFunction == IRP_MN_REMOVE_DEVICE;
  329. if (IrpStack->MinorFunction > IRP_MN_PNP_MAXIMUM_FUNCTION) {
  330. status = MfPassIrp(Irp, Parent, IrpStack);
  331. } else {
  332. status =
  333. MfPnpDispatchTableFdo[IrpStack->MinorFunction](Irp,
  334. Parent,
  335. IrpStack
  336. );
  337. }
  338. if (!isRemoveDevice) {
  339. IoReleaseRemoveLock(&Parent->RemoveLock, (PVOID) Irp);
  340. }
  341. return status;
  342. }
  343. NTSTATUS
  344. MfPnPFdoCompletion(
  345. IN PDEVICE_OBJECT DeviceObject,
  346. IN PIRP Irp,
  347. IN PVOID Context
  348. )
  349. /*++
  350. Routine Description:
  351. This routine is used to defer processing of an IRP until drivers
  352. lower in the stack including the bus driver have done their
  353. processing.
  354. This routine triggers the event to indicate that processing of the
  355. irp can now continue.
  356. Arguments:
  357. DeviceObject - Pointer to the FDO for which this IRP applies.
  358. Irp - Pointer to the IRP_MJ_PNP IRP to dispatch.
  359. Return Value:
  360. NT status.
  361. --*/
  362. {
  363. KeSetEvent((PKEVENT) Context, EVENT_INCREMENT, FALSE);
  364. return STATUS_MORE_PROCESSING_REQUIRED;
  365. }
  366. NTSTATUS
  367. MfDeferProcessingFdo(
  368. IN PMF_PARENT_EXTENSION Parent,
  369. IN OUT PIRP Irp
  370. )
  371. /*++
  372. Routine Description:
  373. This routine is used to defer processing of an IRP until drivers
  374. lower in the stack including the bus driver have done their
  375. processing.
  376. This routine uses an IoCompletion routine along with an event to
  377. wait until the lower level drivers have completed processing of
  378. the irp.
  379. Arguments:
  380. Parent - FDO extension for the FDO devobj in question
  381. Irp - Pointer to the IRP_MJ_PNP IRP to defer
  382. Return Value:
  383. NT status.
  384. --*/
  385. {
  386. KEVENT event;
  387. NTSTATUS status;
  388. PAGED_CODE();
  389. KeInitializeEvent(&event, NotificationEvent, FALSE);
  390. //
  391. // Set our completion routine
  392. //
  393. IoCopyCurrentIrpStackLocationToNext(Irp);
  394. IoSetCompletionRoutine(Irp,
  395. MfPnPFdoCompletion,
  396. &event,
  397. TRUE,
  398. TRUE,
  399. TRUE
  400. );
  401. status = IoCallDriver(Parent->AttachedDevice, Irp);
  402. if (status == STATUS_PENDING) {
  403. KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
  404. status = Irp->IoStatus.Status;
  405. }
  406. return status;
  407. }
  408. NTSTATUS
  409. MfStartFdoInitializeArbiters(
  410. IN PMF_PARENT_EXTENSION Parent,
  411. IN PCM_RESOURCE_LIST ResList,
  412. IN PCM_RESOURCE_LIST TranslatedResList
  413. )
  414. {
  415. NTSTATUS status;
  416. ULONG size;
  417. ULONG count;
  418. PAGED_CODE();
  419. DEBUG_MSG(1, ("Start Fdo arbiters intiialization\n"));
  420. //
  421. // If we were started with any resources then remember them
  422. //
  423. if (ResList && TranslatedResList) {
  424. #if DBG
  425. MfDbgPrintCmResList(1, ResList);
  426. #endif
  427. //
  428. // We only deal with resources on a single bus - which is all we
  429. // should see in a start irp.
  430. //
  431. ASSERT(ResList->Count == 1);
  432. ASSERT(TranslatedResList->Count == 1);
  433. //
  434. // Both lists should have the same number of descriptors
  435. //
  436. ASSERT(ResList->List[0].PartialResourceList.Count == TranslatedResList->List[0].PartialResourceList.Count);
  437. if (ResList->List[0].PartialResourceList.Count != TranslatedResList->List[0].PartialResourceList.Count) {
  438. return STATUS_INVALID_PARAMETER;
  439. }
  440. //
  441. // Calculate the size of the resouceList
  442. //
  443. size = sizeof(CM_RESOURCE_LIST) +
  444. ((ResList->List[0].PartialResourceList.Count - 1) *
  445. sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
  446. //
  447. // Allocate a buffer and copy the data
  448. //
  449. Parent->ResourceList = ExAllocatePoolWithTag(NonPagedPool,
  450. size,
  451. MF_PARENTS_RESOURCE_TAG
  452. );
  453. if (!Parent->ResourceList) {
  454. status = STATUS_INSUFFICIENT_RESOURCES;
  455. goto cleanup;
  456. }
  457. RtlCopyMemory(Parent->ResourceList, ResList, size);
  458. //
  459. // do the same for the TranslatedResList.
  460. //
  461. Parent->TranslatedResourceList = ExAllocatePoolWithTag(NonPagedPool,
  462. size,
  463. MF_PARENTS_RESOURCE_TAG
  464. );
  465. if (!Parent->TranslatedResourceList) {
  466. status = STATUS_INSUFFICIENT_RESOURCES;
  467. goto cleanup;
  468. }
  469. RtlCopyMemory(Parent->TranslatedResourceList, TranslatedResList, size);
  470. //
  471. // As we have resources we are going to need some arbiters
  472. //
  473. status = MfInitializeArbiters(Parent);
  474. if (!NT_SUCCESS(status)) {
  475. goto cleanup;
  476. }
  477. } else {
  478. DEBUG_MSG(1, ("Parent started with no resources\n"));
  479. }
  480. return STATUS_SUCCESS;
  481. cleanup:
  482. if (Parent->ResourceList) {
  483. ExFreePool(Parent->ResourceList);
  484. Parent->ResourceList = NULL;
  485. }
  486. if (Parent->TranslatedResourceList) {
  487. ExFreePool(Parent->TranslatedResourceList);
  488. Parent->TranslatedResourceList = NULL;
  489. }
  490. return status;
  491. }
  492. // REBALANCE
  493. //
  494. // FUTURE DESIGN NOTE:
  495. // If rebalance was actually supported by this component i.e arbiters
  496. // become stoppable, then there are various issues raised by the start
  497. // code. It performs a number of operations assuming that the device
  498. // has never been started before including the query ids, resource
  499. // list storage, etc. There are also issues in redistributing these
  500. // new resources to the children. The current requirements given to
  501. // the children are absolute. Relative requirements have some other
  502. // issues.
  503. //
  504. NTSTATUS
  505. MfStartFdo(
  506. IN PIRP Irp,
  507. IN PMF_PARENT_EXTENSION Parent,
  508. IN PIO_STACK_LOCATION IrpStack
  509. )
  510. {
  511. NTSTATUS status;
  512. IO_STACK_LOCATION location;
  513. PWSTR string;
  514. PAGED_CODE();
  515. status = MfDeferProcessingFdo(Parent, Irp);
  516. if (!NT_SUCCESS(status)) {
  517. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  518. return status;
  519. }
  520. Parent->Common.PowerState = PowerDeviceD0;
  521. //
  522. // We need to find out some information about our parent
  523. //
  524. Parent->DeviceID.Buffer = NULL;
  525. Parent->InstanceID.Buffer = NULL;
  526. RtlZeroMemory(&location, sizeof(IO_STACK_LOCATION));
  527. location.MajorFunction = IRP_MJ_PNP;
  528. location.MinorFunction = IRP_MN_QUERY_ID;
  529. //
  530. // ...DeviceID...
  531. //
  532. location.Parameters.QueryId.IdType = BusQueryDeviceID;
  533. status = MfSendPnpIrp(Parent->PhysicalDeviceObject,
  534. &location,
  535. (PULONG_PTR)&string
  536. );
  537. if (!NT_SUCCESS(status)) {
  538. goto cleanup;
  539. }
  540. RtlInitUnicodeString(&Parent->DeviceID, string);
  541. DEBUG_MSG(1, ("Parent DeviceID: %wZ\n", &Parent->DeviceID));
  542. //
  543. // ...InstanceID
  544. //
  545. location.Parameters.QueryId.IdType = BusQueryInstanceID;
  546. status = MfSendPnpIrp(Parent->PhysicalDeviceObject,
  547. &location,
  548. (PULONG_PTR)&string
  549. );
  550. if (!NT_SUCCESS(status)) {
  551. goto cleanup;
  552. }
  553. RtlInitUnicodeString(&Parent->InstanceID, string);
  554. DEBUG_MSG(1, ("Parent InstanceID: %wZ\n", &Parent->InstanceID));
  555. status = MfStartFdoInitializeArbiters(
  556. Parent,
  557. IrpStack->Parameters.StartDevice.AllocatedResources,
  558. IrpStack->Parameters.StartDevice.AllocatedResourcesTranslated
  559. );
  560. cleanup:
  561. Irp->IoStatus.Status = status;
  562. if (!NT_SUCCESS(status)) {
  563. if (Parent->DeviceID.Buffer) {
  564. ExFreePool(Parent->DeviceID.Buffer);
  565. Parent->DeviceID.Buffer = NULL;
  566. }
  567. if (Parent->InstanceID.Buffer) {
  568. ExFreePool(Parent->InstanceID.Buffer);
  569. Parent->InstanceID.Buffer = NULL;
  570. }
  571. } else {
  572. //
  573. // We are now started!
  574. //
  575. }
  576. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  577. return status;
  578. }
  579. NTSTATUS
  580. MfQueryStopFdo(
  581. IN PIRP Irp,
  582. IN PMF_PARENT_EXTENSION Parent,
  583. IN PIO_STACK_LOCATION IrpStack
  584. )
  585. {
  586. PAGED_CODE();
  587. Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
  588. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  589. return STATUS_UNSUCCESSFUL;
  590. }
  591. NTSTATUS
  592. MfCancelStopFdo(
  593. IN PIRP Irp,
  594. IN PMF_PARENT_EXTENSION Parent,
  595. IN PIO_STACK_LOCATION IrpStack
  596. )
  597. {
  598. NTSTATUS status;
  599. PAGED_CODE();
  600. status = MfDeferProcessingFdo(Parent, Irp);
  601. // NTRAID#53498
  602. // ASSERT(status == STATUS_SUCCESS);
  603. // Uncomment after PCI state machine is fixed to not fail bogus stops
  604. Irp->IoStatus.Status = STATUS_SUCCESS;
  605. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  606. return STATUS_SUCCESS;
  607. }
  608. NTSTATUS
  609. MfQueryRemoveFdo(
  610. IN PIRP Irp,
  611. IN PMF_PARENT_EXTENSION Parent,
  612. IN PIO_STACK_LOCATION IrpStack
  613. )
  614. {
  615. PAGED_CODE();
  616. Irp->IoStatus.Status = STATUS_SUCCESS;
  617. return MfPassIrp(Irp, Parent, IrpStack);
  618. }
  619. NTSTATUS
  620. MfRemoveFdo(
  621. IN PIRP Irp,
  622. IN PMF_PARENT_EXTENSION Parent,
  623. IN PIO_STACK_LOCATION IrpStack
  624. )
  625. {
  626. PMF_CHILD_EXTENSION current;
  627. PLIST_ENTRY currentEntry;
  628. NTSTATUS status;
  629. //
  630. // If we have any children then make sure they are removed and
  631. // delete them.
  632. //
  633. MfAcquireChildrenLock(Parent);
  634. while (!IsListEmpty(&Parent->Children)) {
  635. currentEntry = RemoveHeadList(&Parent->Children);
  636. ASSERT(currentEntry);
  637. current = CONTAINING_RECORD(currentEntry, MF_CHILD_EXTENSION,
  638. ListEntry);
  639. //
  640. // * If this child has been surprise removed, and hasn't
  641. // received the subsequent remove, then leave
  642. // the PDO intact but mark it 'missing'.
  643. //
  644. // * If this child has handled a previous remove (this is
  645. // fundamentally the case if we've gotten to the point of
  646. // removing the parent) and hasn't subsequently received a
  647. // surprise remove, then delete the pdo.
  648. //
  649. if (current->Common.DeviceState & MF_DEVICE_SURPRISE_REMOVED) {
  650. //
  651. // Mark as 'missing' and unlink dangerous reference to parent
  652. //
  653. current->Parent = NULL;
  654. current->Common.DeviceState &= ~MF_DEVICE_ENUMERATED;
  655. } else {
  656. MfDeletePdo(current);
  657. }
  658. }
  659. MfReleaseChildrenLock(Parent);
  660. Parent->Common.PowerState = PowerDeviceD3;
  661. Irp->IoStatus.Status = STATUS_SUCCESS;
  662. status = MfPassIrp(Irp, Parent, IrpStack);
  663. ASSERT(NT_SUCCESS(status));
  664. IoReleaseRemoveLockAndWait(&Parent->RemoveLock, (PVOID) Irp);
  665. //
  666. // Detach and delete myself
  667. //
  668. IoDetachDevice(Parent->AttachedDevice);
  669. Parent->AttachedDevice = NULL;
  670. MfDeleteFdo(Parent->Self);
  671. return status;
  672. }
  673. NTSTATUS
  674. MfSurpriseRemoveFdo(
  675. IN PIRP Irp,
  676. IN PMF_PARENT_EXTENSION Parent,
  677. IN PIO_STACK_LOCATION IrpStack
  678. )
  679. {
  680. PLIST_ENTRY currentEntry;
  681. PMF_CHILD_EXTENSION current;
  682. PAGED_CODE();
  683. Parent->Common.DeviceState |= MF_DEVICE_SURPRISE_REMOVED;
  684. MfAcquireChildrenLock(Parent);
  685. for (currentEntry = Parent->Children.Flink;
  686. currentEntry != &Parent->Children;
  687. currentEntry = currentEntry->Flink) {
  688. current = CONTAINING_RECORD(currentEntry,
  689. MF_CHILD_EXTENSION,
  690. ListEntry);
  691. current->Common.DeviceState &= ~MF_DEVICE_ENUMERATED;
  692. }
  693. MfReleaseChildrenLock(Parent);
  694. Irp->IoStatus.Status = STATUS_SUCCESS;
  695. return MfPassIrp(Irp, Parent, IrpStack);
  696. }
  697. NTSTATUS
  698. MfCancelRemoveFdo(
  699. IN PIRP Irp,
  700. IN PMF_PARENT_EXTENSION Parent,
  701. IN PIO_STACK_LOCATION IrpStack
  702. )
  703. {
  704. NTSTATUS status;
  705. PAGED_CODE();
  706. status = MfDeferProcessingFdo(Parent, Irp);
  707. // NTRAID#53498
  708. // ASSERT(status == STATUS_SUCCESS);
  709. // Uncomment after PCI state machine is fixed to not fail bogus stops
  710. Irp->IoStatus.Status = STATUS_SUCCESS;
  711. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  712. return STATUS_SUCCESS;
  713. }
  714. NTSTATUS
  715. MfQueryDeviceRelationsFdo(
  716. IN PIRP Irp,
  717. IN PMF_PARENT_EXTENSION Parent,
  718. IN PIO_STACK_LOCATION IrpStack
  719. )
  720. {
  721. NTSTATUS status;
  722. PDEVICE_RELATIONS relations = NULL;
  723. ULONG relationsSize, childrenCount, i;
  724. PDEVICE_OBJECT *currentRelation;
  725. PMF_CHILD_EXTENSION currentChild;
  726. PLIST_ENTRY currentEntry;
  727. PAGED_CODE();
  728. DEBUG_MSG(1,
  729. ("%s\n",
  730. RELATION_STRING(IrpStack->Parameters.QueryDeviceRelations.Type)
  731. ));
  732. switch (IrpStack->Parameters.QueryDeviceRelations.Type) {
  733. case BusRelations:
  734. MfAcquireChildrenLock(Parent);
  735. status = MfEnumerate(Parent);
  736. if (!NT_SUCCESS(status)) {
  737. MfReleaseChildrenLock(Parent);
  738. Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
  739. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  740. return STATUS_UNSUCCESSFUL;
  741. }
  742. childrenCount = 0;
  743. FOR_ALL_IN_LIST(MF_CHILD_EXTENSION, &Parent->Children, currentChild) {
  744. if (currentChild->Common.DeviceState & MF_DEVICE_ENUMERATED) {
  745. childrenCount++;
  746. }
  747. }
  748. if (childrenCount == 0) {
  749. relationsSize = sizeof(DEVICE_RELATIONS);
  750. } else {
  751. relationsSize = sizeof(DEVICE_RELATIONS) +
  752. (childrenCount-1) * sizeof(PDEVICE_OBJECT);
  753. }
  754. relations = ExAllocatePoolWithTag(PagedPool,
  755. relationsSize,
  756. MF_BUS_RELATIONS_TAG
  757. );
  758. if (!relations) {
  759. MfReleaseChildrenLock(Parent);
  760. Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
  761. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  762. return STATUS_INSUFFICIENT_RESOURCES;
  763. }
  764. RtlZeroMemory(relations, relationsSize);
  765. //
  766. // Iterate through the list of children in the parent and build the
  767. // relations structure
  768. //
  769. currentRelation = relations->Objects;
  770. relations->Count = childrenCount;
  771. FOR_ALL_IN_LIST(MF_CHILD_EXTENSION, &Parent->Children, currentChild) {
  772. if (currentChild->Common.DeviceState & MF_DEVICE_ENUMERATED) {
  773. ObReferenceObject(currentChild->Self);
  774. *currentRelation = currentChild->Self;
  775. #if DBG
  776. DEBUG_MSG(1, ("\tPDO Enumerated @ 0x%08x\n", currentChild));
  777. DEBUG_MSG(1, ("\tName: %wZ\n", &currentChild->Info.Name));
  778. DEBUG_MSG(1, ("\tHardwareID: "));
  779. MfDbgPrintMultiSz(1, currentChild->Info.HardwareID.Buffer);
  780. DEBUG_MSG(1, ("\tCompatibleID: "));
  781. MfDbgPrintMultiSz(1, currentChild->Info.CompatibleID.Buffer);
  782. DEBUG_MSG(1, ("\tResourceMap: "));
  783. MfDbgPrintResourceMap(1, currentChild->Info.ResourceMap);
  784. DEBUG_MSG(1, ("\tVaryingMap: "));
  785. MfDbgPrintVaryingResourceMap(1, currentChild->Info.VaryingResourceMap);
  786. DEBUG_MSG(1, ("\tFlags: 0x%08x\n", currentChild->Info.MfFlags));
  787. #endif
  788. }
  789. currentRelation++;
  790. }
  791. MfReleaseChildrenLock(Parent);
  792. //
  793. // Hand back the relations
  794. //
  795. Irp->IoStatus.Information = (ULONG_PTR) relations;
  796. Irp->IoStatus.Status = STATUS_SUCCESS;
  797. break;
  798. //
  799. // For the rest of the relations just pass down the irp untouched.
  800. //
  801. default:
  802. break;
  803. }
  804. return MfPassIrp(Irp, Parent, IrpStack);
  805. }
  806. VOID
  807. MfArbiterReference(
  808. PVOID Context
  809. )
  810. {
  811. }
  812. VOID
  813. MfArbiterDereference(
  814. PVOID Context
  815. )
  816. {
  817. }
  818. NTSTATUS
  819. MfQueryInterfaceFdo(
  820. IN PIRP Irp,
  821. IN PMF_PARENT_EXTENSION Parent,
  822. IN PIO_STACK_LOCATION IrpStack
  823. )
  824. {
  825. PMF_ARBITER current;
  826. PARBITER_INTERFACE interface = (PARBITER_INTERFACE) IrpStack->Parameters.QueryInterface.Interface;
  827. PAGED_CODE();
  828. //
  829. // We only provide arbiters
  830. //
  831. if (MfCompareGuid(&GUID_ARBITER_INTERFACE_STANDARD,
  832. IrpStack->Parameters.QueryInterface.InterfaceType)) {
  833. //
  834. // We only support version 1 of the ARBITER_INTERFACE so we
  835. // don't need to bother checking version numbers, just that the
  836. // return buffer is big enough
  837. //
  838. if (IrpStack->Parameters.QueryInterface.Size < sizeof(ARBITER_INTERFACE)) {
  839. Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
  840. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  841. return STATUS_BUFFER_TOO_SMALL;
  842. }
  843. FOR_ALL_IN_LIST(MF_ARBITER, &Parent->Arbiters, current) {
  844. if (current->Type == (CM_RESOURCE_TYPE)((ULONG_PTR)
  845. IrpStack->Parameters.QueryInterface.InterfaceSpecificData)) {
  846. DEBUG_MSG(1,(" Returning Arbiter interface\n"));
  847. //
  848. // Fill in the interface
  849. //
  850. interface->Size = sizeof(ARBITER_INTERFACE);
  851. interface->Version = MF_ARBITER_INTERFACE_VERSION;
  852. interface->Context = &current->Instance;
  853. interface->InterfaceReference = MfArbiterReference;
  854. interface->InterfaceDereference = MfArbiterDereference;
  855. interface->ArbiterHandler = ArbArbiterHandler;
  856. interface->Flags = 0;
  857. Irp->IoStatus.Status = STATUS_SUCCESS;
  858. break;
  859. }
  860. }
  861. }
  862. return MfPassIrp(Irp, Parent, IrpStack);
  863. }
  864. NTSTATUS
  865. MfQueryCapabilitiesFdo(
  866. IN PIRP Irp,
  867. IN PMF_PARENT_EXTENSION Parent,
  868. IN PIO_STACK_LOCATION IrpStack
  869. )
  870. {
  871. NTSTATUS status;
  872. PAGED_CODE();
  873. status = MfDeferProcessingFdo(Parent, Irp);
  874. if (!NT_SUCCESS(status)) {
  875. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  876. return status;
  877. }
  878. if (IrpStack->Parameters.DeviceCapabilities.Capabilities->Version != 1) {
  879. Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
  880. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  881. return STATUS_INVALID_PARAMETER;
  882. }
  883. IrpStack->Parameters.DeviceCapabilities.Capabilities->WakeFromD0 =
  884. IrpStack->Parameters.DeviceCapabilities.Capabilities->WakeFromD1 =
  885. IrpStack->Parameters.DeviceCapabilities.Capabilities->WakeFromD2 =
  886. IrpStack->Parameters.DeviceCapabilities.Capabilities->WakeFromD3 = 0;
  887. IrpStack->Parameters.DeviceCapabilities.Capabilities->DeviceWake =
  888. PowerSystemUnspecified;
  889. IrpStack->Parameters.DeviceCapabilities.Capabilities->SystemWake =
  890. PowerSystemUnspecified;
  891. Irp->IoStatus.Status = STATUS_SUCCESS;
  892. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  893. return STATUS_SUCCESS;
  894. }
  895. NTSTATUS
  896. MfDispatchPowerFdo(
  897. IN PDEVICE_OBJECT DeviceObject,
  898. PMF_PARENT_EXTENSION Parent,
  899. PIO_STACK_LOCATION IrpStack,
  900. IN PIRP Irp
  901. )
  902. /*++
  903. Routine Description:
  904. This routine handles all IRP_MJ_POWER IRPs for the FDO. It dispatches
  905. to the routines described in the PoDispatchTable entry in the device object
  906. extension.
  907. This routine is NOT pageable as it can be called at DISPATCH_LEVEL
  908. Arguments:
  909. DeviceObject - Pointer to the device object for which this IRP applies.
  910. Parent - FDO Extension
  911. Irp - Pointer to the IRP_MJ_PNP IRP to dispatch.
  912. Return Value:
  913. NT status.
  914. --*/
  915. {
  916. NTSTATUS status;
  917. PMF_COMMON_EXTENSION common = (PMF_COMMON_EXTENSION) Parent;
  918. IoAcquireRemoveLock(&Parent->RemoveLock, (PVOID) Irp);
  919. //
  920. // Call the appropriate function
  921. //
  922. if ((IrpStack->MinorFunction <= IRP_MN_PO_MAXIMUM_FUNCTION) &&
  923. (MfPoDispatchTableFdo[IrpStack->MinorFunction])) {
  924. status =
  925. MfPoDispatchTableFdo[IrpStack->MinorFunction](Irp,
  926. (PVOID) common,
  927. IrpStack
  928. );
  929. } else {
  930. //
  931. // We don't know about this irp
  932. //
  933. DEBUG_MSG(0,
  934. ("Unknown POWER IRP 0x%x for FDO 0x%08x\n",
  935. IrpStack->MinorFunction,
  936. DeviceObject
  937. ));
  938. PoStartNextPowerIrp(Irp);
  939. IoSkipCurrentIrpStackLocation(Irp);
  940. status = PoCallDriver(Parent->AttachedDevice, Irp);
  941. }
  942. IoReleaseRemoveLock(&Parent->RemoveLock, (PVOID) Irp);
  943. return status;
  944. }
  945. NTSTATUS
  946. MfQueryPowerFdo(
  947. IN PIRP Irp,
  948. IN PMF_PARENT_EXTENSION Parent,
  949. IN PIO_STACK_LOCATION IrpStack
  950. )
  951. {
  952. PoStartNextPowerIrp(Irp);
  953. IoSkipCurrentIrpStackLocation(Irp);
  954. Irp->IoStatus.Status = STATUS_SUCCESS;
  955. return PoCallDriver(Parent->AttachedDevice, Irp);
  956. }
  957. NTSTATUS
  958. MfSetPowerFdoCompletion(
  959. IN PDEVICE_OBJECT DeviceObject,
  960. IN PIRP Irp,
  961. IN PVOID Context
  962. )
  963. {
  964. PMF_PARENT_EXTENSION parent = DeviceObject->DeviceExtension;
  965. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  966. //
  967. // Remember the parent's power state
  968. //
  969. if (irpStack->Parameters.Power.Type == DevicePowerState) {
  970. parent->Common.PowerState =
  971. irpStack->Parameters.Power.State.DeviceState;
  972. }
  973. return STATUS_SUCCESS;
  974. }
  975. NTSTATUS
  976. MfSetPowerFdo(
  977. IN PIRP Irp,
  978. IN PMF_PARENT_EXTENSION Parent,
  979. IN PIO_STACK_LOCATION IrpStack
  980. )
  981. {
  982. PoStartNextPowerIrp(Irp);
  983. IoCopyCurrentIrpStackLocationToNext(Irp);
  984. IoSetCompletionRoutine(Irp,
  985. MfSetPowerFdoCompletion,
  986. NULL, //Context
  987. TRUE, //InvokeOnSuccess
  988. FALSE, //InvokeOnError
  989. FALSE //InvokeOnCancel
  990. );
  991. Irp->IoStatus.Status = STATUS_SUCCESS;
  992. return PoCallDriver(Parent->AttachedDevice, Irp);
  993. }