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.

1003 lines
25 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. (Derived from MF)
  9. Revision History:
  10. --*/
  11. #include "SpSim.h"
  12. #include "spsimioct.h"
  13. /*++
  14. The majority of functions in this file are called based on their presence
  15. in Pnp and Po dispatch tables. In the interests of brevity the arguments
  16. to all those functions will be described below:
  17. NTSTATUS
  18. SpSimXxxFdo(
  19. IN PIRP Irp,
  20. IN PSPSIM_EXTENSION SpSim,
  21. IN PIO_STACK_LOCATION IrpStack
  22. )
  23. Routine Description:
  24. This function handles the Xxx requests for multifunction FDO's
  25. Arguments:
  26. Irp - Points to the IRP associated with this request.
  27. SpSim - Points to the parent FDO's device extension.
  28. IrpStack - Points to the current stack location for this request.
  29. Return Value:
  30. Status code that indicates whether or not the function was successful.
  31. STATUS_NOT_SUPPORTED indicates that the IRP should be passed down without
  32. changing the Irp->IoStatus.Status field otherwise it is updated with this
  33. status.
  34. --*/
  35. NTSTATUS
  36. SpSimDeferProcessingFdo(
  37. IN PSPSIM_EXTENSION SpSim,
  38. IN OUT PIRP Irp
  39. );
  40. NTSTATUS
  41. SpSimStartFdo(
  42. IN PIRP Irp,
  43. IN PSPSIM_EXTENSION SpSim,
  44. IN PIO_STACK_LOCATION IrpStack
  45. );
  46. NTSTATUS
  47. SpSimStartFdoCompletion(
  48. IN PDEVICE_OBJECT DeviceObject,
  49. IN PIRP Irp,
  50. IN PVOID Context
  51. );
  52. NTSTATUS
  53. SpSimQueryStopFdo(
  54. IN PIRP Irp,
  55. IN PSPSIM_EXTENSION SpSim,
  56. IN PIO_STACK_LOCATION IrpStack
  57. );
  58. NTSTATUS
  59. SpSimCancelStopFdo(
  60. IN PIRP Irp,
  61. IN PSPSIM_EXTENSION SpSim,
  62. IN PIO_STACK_LOCATION IrpStack
  63. );
  64. NTSTATUS
  65. SpSimQueryRemoveFdo(
  66. IN PIRP Irp,
  67. IN PSPSIM_EXTENSION SpSim,
  68. IN PIO_STACK_LOCATION IrpStack
  69. );
  70. NTSTATUS
  71. SpSimRemoveFdo(
  72. IN PIRP Irp,
  73. IN PSPSIM_EXTENSION SpSim,
  74. IN PIO_STACK_LOCATION IrpStack
  75. );
  76. NTSTATUS
  77. SpSimQueryCapabilitiesFdo(
  78. IN PIRP Irp,
  79. IN PSPSIM_EXTENSION SpSim,
  80. IN PIO_STACK_LOCATION IrpStack
  81. );
  82. NTSTATUS
  83. SpSimSurpriseRemoveFdo(
  84. IN PIRP Irp,
  85. IN PSPSIM_EXTENSION SpSim,
  86. IN PIO_STACK_LOCATION IrpStack
  87. );
  88. NTSTATUS
  89. SpSimCancelRemoveFdo(
  90. IN PIRP Irp,
  91. IN PSPSIM_EXTENSION SpSim,
  92. IN PIO_STACK_LOCATION IrpStack
  93. );
  94. #ifdef ALLOC_PRAGMA
  95. #pragma alloc_text(PAGE, SpSimCancelRemoveFdo)
  96. #pragma alloc_text(PAGE, SpSimCancelStopFdo)
  97. #pragma alloc_text(PAGE, SpSimCreateFdo)
  98. #pragma alloc_text(PAGE, SpSimDeferProcessingFdo)
  99. #pragma alloc_text(PAGE, SpSimDispatchPnpFdo)
  100. #pragma alloc_text(PAGE, SpSimPassIrp)
  101. #pragma alloc_text(PAGE, SpSimQueryRemoveFdo)
  102. #pragma alloc_text(PAGE, SpSimQueryStopFdo)
  103. #pragma alloc_text(PAGE, SpSimRemoveFdo)
  104. #pragma alloc_text(PAGE, SpSimStartFdo)
  105. #pragma alloc_text(PAGE, SpSimQueryCapabilitiesFdo)
  106. #pragma alloc_text(PAGE, SpSimSurpriseRemoveFdo)
  107. #endif
  108. PSPSIM_DISPATCH SpSimPnpDispatchTableFdo[] = {
  109. SpSimStartFdo, // IRP_MN_START_DEVICE
  110. SpSimQueryRemoveFdo, // IRP_MN_QUERY_REMOVE_DEVICE
  111. SpSimRemoveFdo, // IRP_MN_REMOVE_DEVICE
  112. SpSimCancelRemoveFdo, // IRP_MN_CANCEL_REMOVE_DEVICE
  113. SpSimPassIrp, // IRP_MN_STOP_DEVICE
  114. SpSimQueryStopFdo, // IRP_MN_QUERY_STOP_DEVICE
  115. SpSimCancelStopFdo, // IRP_MN_CANCEL_STOP_DEVICE
  116. SpSimPassIrp, // IRP_MN_QUERY_DEVICE_RELATIONS
  117. SpSimPassIrp, // IRP_MN_QUERY_INTERFACE
  118. SpSimQueryCapabilitiesFdo, // IRP_MN_QUERY_CAPABILITIES
  119. SpSimPassIrp, // IRP_MN_QUERY_RESOURCES
  120. SpSimPassIrp, // IRP_MN_QUERY_RESOURCE_REQUIREMENTS
  121. SpSimPassIrp, // IRP_MN_QUERY_DEVICE_TEXT
  122. SpSimPassIrp, // IRP_MN_FILTER_RESOURCE_REQUIREMENTS
  123. SpSimPassIrp, // Unused
  124. SpSimPassIrp, // IRP_MN_READ_CONFIG
  125. SpSimPassIrp, // IRP_MN_WRITE_CONFIG
  126. SpSimPassIrp, // IRP_MN_EJECT
  127. SpSimPassIrp, // IRP_MN_SET_LOCK
  128. SpSimPassIrp, // IRP_MN_QUERY_ID
  129. SpSimPassIrp, // IRP_MN_QUERY_PNP_DEVICE_STATE
  130. SpSimPassIrp, // IRP_MN_QUERY_BUS_INFORMATION
  131. SpSimPassIrp, // IRP_MN_DEVICE_USAGE_NOTIFICATION
  132. SpSimSurpriseRemoveFdo, // IRP_MN_SURPRISE_REMOVAL
  133. };
  134. NTSTATUS
  135. SpSimCreateFdo(
  136. OUT PDEVICE_OBJECT *Fdo
  137. )
  138. /*++
  139. Routine Description:
  140. This function creates a new FDO and initializes it.
  141. Arguments:
  142. Fdo - Pointer to where the FDO should be returned
  143. Return Value:
  144. Status code that indicates whether or not the function was successful.
  145. --*/
  146. {
  147. NTSTATUS status;
  148. PSPSIM_EXTENSION extension;
  149. PAGED_CODE();
  150. ASSERT((sizeof(SpSimPnpDispatchTableFdo) / sizeof(PSPSIM_DISPATCH)) - 1
  151. == IRP_MN_PNP_MAXIMUM_FUNCTION);
  152. #if 0
  153. ASSERT((sizeof(SpSimPoDispatchTableFdo) / sizeof(PSPSIM_DISPATCH)) -1
  154. == IRP_MN_PO_MAXIMUM_FUNCTION);
  155. #endif
  156. *Fdo = NULL;
  157. status = IoCreateDevice(SpSimDriverObject,
  158. sizeof(SPSIM_EXTENSION),
  159. NULL,
  160. FILE_DEVICE_BUS_EXTENDER,
  161. 0,
  162. FALSE,
  163. Fdo
  164. );
  165. if (!NT_SUCCESS(status)) {
  166. goto cleanup;
  167. }
  168. //
  169. // Initialize the extension
  170. //
  171. extension = (PSPSIM_EXTENSION) (*Fdo)->DeviceExtension;
  172. extension->Self = *Fdo;
  173. IoInitializeRemoveLock(&extension->RemoveLock, 0, 1, 20);
  174. extension->PowerState = PowerDeviceD3;
  175. DEBUG_MSG(1, ("Created FDO @ 0x%08x\n", *Fdo));
  176. return status;
  177. cleanup:
  178. if (*Fdo) {
  179. IoDeleteDevice(*Fdo);
  180. }
  181. return status;
  182. }
  183. VOID
  184. SpSimDeleteFdo(
  185. IN PDEVICE_OBJECT Fdo
  186. )
  187. {
  188. PSPSIM_EXTENSION SpSim = Fdo->DeviceExtension;
  189. if (SpSim->DeviceState & SPSIM_DEVICE_DELETED) {
  190. //
  191. // Trying to delete twice
  192. //
  193. ASSERT(!(SpSim->DeviceState & SPSIM_DEVICE_DELETED));
  194. return;
  195. }
  196. SpSim->DeviceState = SPSIM_DEVICE_DELETED;
  197. SpSimDeleteStaOpRegion(SpSim);
  198. SpSimDeleteMemOpRegion(SpSim);
  199. RtlFreeUnicodeString(&SpSim->SymbolicLinkName);
  200. //
  201. // Free up any memory we have allocated
  202. //
  203. IoDeleteDevice(Fdo);
  204. DEBUG_MSG(1, ("Deleted FDO @ 0x%08x\n", Fdo));
  205. }
  206. NTSTATUS
  207. SpSimPassIrp(
  208. IN PIRP Irp,
  209. IN PSPSIM_EXTENSION SpSim,
  210. IN PIO_STACK_LOCATION IrpStack
  211. )
  212. {
  213. PAGED_CODE();
  214. IoSkipCurrentIrpStackLocation(Irp);
  215. return IoCallDriver(SpSim->AttachedDevice, Irp);
  216. }
  217. NTSTATUS
  218. SpSimDispatchPnpFdo(
  219. IN PDEVICE_OBJECT DeviceObject,
  220. IN PSPSIM_EXTENSION SpSim,
  221. IN PIO_STACK_LOCATION IrpStack,
  222. IN OUT PIRP Irp
  223. )
  224. /*++
  225. Routine Description:
  226. This routine handles IRP_MJ_PNP IRPs for FDOs.
  227. Arguments:
  228. DeviceObject - Pointer to the FDO for which this IRP applies.
  229. SpSim - FDO extension
  230. IrpStack - Current stack location
  231. Irp - Pointer to the IRP_MJ_PNP IRP to dispatch.
  232. Return Value:
  233. NT status.
  234. --*/
  235. {
  236. NTSTATUS status;
  237. BOOLEAN isRemoveDevice;
  238. PAGED_CODE();
  239. //
  240. // Get a pointer to our stack location and take appropriate action based
  241. // on the minor function.
  242. //
  243. IoAcquireRemoveLock(&SpSim->RemoveLock, (PVOID) Irp);
  244. isRemoveDevice = IrpStack->MinorFunction == IRP_MN_REMOVE_DEVICE;
  245. if (IrpStack->MinorFunction > IRP_MN_PNP_MAXIMUM_FUNCTION) {
  246. status = SpSimPassIrp(Irp, SpSim, IrpStack);
  247. } else {
  248. status =
  249. SpSimPnpDispatchTableFdo[IrpStack->MinorFunction](Irp,
  250. SpSim,
  251. IrpStack
  252. );
  253. }
  254. if (!isRemoveDevice) {
  255. IoReleaseRemoveLock(&SpSim->RemoveLock, (PVOID) Irp);
  256. }
  257. return status;
  258. }
  259. NTSTATUS
  260. SpSimPnPFdoCompletion(
  261. IN PDEVICE_OBJECT DeviceObject,
  262. IN PIRP Irp,
  263. IN PVOID Context
  264. )
  265. /*++
  266. Routine Description:
  267. This routine is used to defer processing of an IRP until drivers
  268. lower in the stack including the bus driver have done their
  269. processing.
  270. This routine triggers the event to indicate that processing of the
  271. irp can now continue.
  272. Arguments:
  273. DeviceObject - Pointer to the FDO for which this IRP applies.
  274. Irp - Pointer to the IRP_MJ_PNP IRP to dispatch.
  275. Return Value:
  276. NT status.
  277. --*/
  278. {
  279. KeSetEvent((PKEVENT) Context, EVENT_INCREMENT, FALSE);
  280. return STATUS_MORE_PROCESSING_REQUIRED;
  281. }
  282. NTSTATUS
  283. SpSimDeferProcessingFdo(
  284. IN PSPSIM_EXTENSION SpSim,
  285. IN OUT PIRP Irp
  286. )
  287. /*++
  288. Routine Description:
  289. This routine is used to defer processing of an IRP until drivers
  290. lower in the stack including the bus driver have done their
  291. processing.
  292. This routine uses an IoCompletion routine along with an event to
  293. wait until the lower level drivers have completed processing of
  294. the irp.
  295. Arguments:
  296. SpSim - FDO extension for the FDO devobj in question
  297. Irp - Pointer to the IRP_MJ_PNP IRP to defer
  298. Return Value:
  299. NT status.
  300. --*/
  301. {
  302. KEVENT event;
  303. NTSTATUS status;
  304. PAGED_CODE();
  305. KeInitializeEvent(&event, NotificationEvent, FALSE);
  306. //
  307. // Set our completion routine
  308. //
  309. IoCopyCurrentIrpStackLocationToNext(Irp);
  310. IoSetCompletionRoutine(Irp,
  311. SpSimPnPFdoCompletion,
  312. &event,
  313. TRUE,
  314. TRUE,
  315. TRUE
  316. );
  317. status = IoCallDriver(SpSim->AttachedDevice, Irp);
  318. if (status == STATUS_PENDING) {
  319. KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
  320. status = Irp->IoStatus.Status;
  321. }
  322. return status;
  323. }
  324. NTSTATUS
  325. SpSimStartFdo(
  326. IN PIRP Irp,
  327. IN PSPSIM_EXTENSION SpSim,
  328. IN PIO_STACK_LOCATION IrpStack
  329. )
  330. {
  331. NTSTATUS status;
  332. IO_STACK_LOCATION location;
  333. POWER_STATE power;
  334. PWSTR string;
  335. PAGED_CODE();
  336. status = SpSimDeferProcessingFdo(SpSim, Irp);
  337. if (!NT_SUCCESS(status)) {
  338. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  339. return status;
  340. }
  341. power.DeviceState = PowerDeviceD0;
  342. PoSetPowerState(SpSim->Self, DevicePowerState, power);
  343. SpSim->PowerState = PowerDeviceD0;
  344. status = SpSimCreateStaOpRegion(SpSim);
  345. if (!NT_SUCCESS(status)) {
  346. goto cleanup;
  347. }
  348. status = SpSimCreateMemOpRegion(SpSim);
  349. if (!NT_SUCCESS(status)) {
  350. SpSimDeleteStaOpRegion(SpSim);
  351. goto cleanup;
  352. }
  353. status = SpSimInstallStaOpRegionHandler(SpSim);
  354. if (!NT_SUCCESS(status)) {
  355. SpSimDeleteStaOpRegion(SpSim);
  356. goto cleanup;
  357. }
  358. status = SpSimInstallMemOpRegionHandler(SpSim);
  359. if (!NT_SUCCESS(status)) {
  360. SpSimDeleteStaOpRegion(SpSim);
  361. goto cleanup;
  362. }
  363. status = IoSetDeviceInterfaceState(&SpSim->SymbolicLinkName, TRUE);
  364. cleanup:
  365. Irp->IoStatus.Status = status;
  366. if (!NT_SUCCESS(status)) {
  367. SpSimRemoveStaOpRegionHandler(SpSim);
  368. SpSimDeleteStaOpRegion(SpSim);
  369. SpSimRemoveMemOpRegionHandler(SpSim);
  370. SpSimDeleteMemOpRegion(SpSim);
  371. } else {
  372. //
  373. // We are now started!
  374. //
  375. }
  376. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  377. return status;
  378. }
  379. NTSTATUS
  380. SpSimQueryStopFdo(
  381. IN PIRP Irp,
  382. IN PSPSIM_EXTENSION SpSim,
  383. IN PIO_STACK_LOCATION IrpStack
  384. )
  385. {
  386. PAGED_CODE();
  387. Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
  388. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  389. return STATUS_UNSUCCESSFUL;
  390. }
  391. NTSTATUS
  392. SpSimCancelStopFdo(
  393. IN PIRP Irp,
  394. IN PSPSIM_EXTENSION SpSim,
  395. IN PIO_STACK_LOCATION IrpStack
  396. )
  397. {
  398. NTSTATUS status;
  399. PAGED_CODE();
  400. status = SpSimDeferProcessingFdo(SpSim, Irp);
  401. // NTRAID#53498
  402. // ASSERT(status == STATUS_SUCCESS);
  403. // Uncomment after PCI state machine is fixed to not fail bogus stops
  404. Irp->IoStatus.Status = STATUS_SUCCESS;
  405. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  406. return STATUS_SUCCESS;
  407. }
  408. NTSTATUS
  409. SpSimQueryRemoveFdo(
  410. IN PIRP Irp,
  411. IN PSPSIM_EXTENSION SpSim,
  412. IN PIO_STACK_LOCATION IrpStack
  413. )
  414. {
  415. PAGED_CODE();
  416. Irp->IoStatus.Status = STATUS_SUCCESS;
  417. return SpSimPassIrp(Irp, SpSim, IrpStack);
  418. }
  419. NTSTATUS
  420. SpSimRemoveFdo(
  421. IN PIRP Irp,
  422. IN PSPSIM_EXTENSION SpSim,
  423. IN PIO_STACK_LOCATION IrpStack
  424. )
  425. {
  426. NTSTATUS status;
  427. POWER_STATE power;
  428. power.DeviceState = PowerDeviceD3;
  429. PoSetPowerState(SpSim->Self, DevicePowerState, power);
  430. SpSim->PowerState = PowerDeviceD3;
  431. (VOID) IoSetDeviceInterfaceState(&SpSim->SymbolicLinkName, FALSE);
  432. SpSimRemoveStaOpRegionHandler(SpSim);
  433. SpSimRemoveMemOpRegionHandler(SpSim);
  434. Irp->IoStatus.Status = STATUS_SUCCESS;
  435. status = SpSimPassIrp(Irp, SpSim, IrpStack);
  436. ASSERT(status == STATUS_SUCCESS);
  437. IoReleaseRemoveLockAndWait(&SpSim->RemoveLock, (PVOID) Irp);
  438. //
  439. // Detach and delete myself
  440. //
  441. IoDetachDevice(SpSim->AttachedDevice);
  442. SpSim->AttachedDevice = NULL;
  443. SpSimDeleteFdo(SpSim->Self);
  444. return STATUS_SUCCESS;
  445. }
  446. NTSTATUS
  447. SpSimQueryCapabilitiesFdo(
  448. IN PIRP Irp,
  449. IN PSPSIM_EXTENSION SpSim,
  450. IN PIO_STACK_LOCATION IrpStack
  451. )
  452. {
  453. NTSTATUS status;
  454. ULONG i;
  455. PAGED_CODE();
  456. status = SpSimDeferProcessingFdo(SpSim, Irp);
  457. if (!NT_SUCCESS(status)) {
  458. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  459. return status;
  460. }
  461. if (IrpStack->Parameters.DeviceCapabilities.Capabilities->Version != 1) {
  462. Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
  463. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  464. return STATUS_INVALID_PARAMETER;
  465. }
  466. for (i = 0; i < PowerSystemMaximum; i++) {
  467. SpSim->DeviceStateMapping[i] =
  468. IrpStack->Parameters.DeviceCapabilities.Capabilities->DeviceState[i];
  469. }
  470. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  471. return STATUS_SUCCESS;
  472. }
  473. NTSTATUS
  474. SpSimSurpriseRemoveFdo(
  475. IN PIRP Irp,
  476. IN PSPSIM_EXTENSION SpSim,
  477. IN PIO_STACK_LOCATION IrpStack
  478. )
  479. {
  480. PAGED_CODE();
  481. SpSim->DeviceState |= SPSIM_DEVICE_SURPRISE_REMOVED;
  482. Irp->IoStatus.Status = STATUS_SUCCESS;
  483. return SpSimPassIrp(Irp, SpSim, IrpStack);
  484. }
  485. NTSTATUS
  486. SpSimCancelRemoveFdo(
  487. IN PIRP Irp,
  488. IN PSPSIM_EXTENSION SpSim,
  489. IN PIO_STACK_LOCATION IrpStack
  490. )
  491. {
  492. NTSTATUS status;
  493. PAGED_CODE();
  494. status = SpSimDeferProcessingFdo(SpSim, Irp);
  495. // NTRAID#53498
  496. // ASSERT(status == STATUS_SUCCESS);
  497. // Uncomment after PCI state machine is fixed to not fail bogus stops
  498. Irp->IoStatus.Status = STATUS_SUCCESS;
  499. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  500. return STATUS_SUCCESS;
  501. }
  502. NTSTATUS
  503. SpSimSendIoctl(
  504. IN PDEVICE_OBJECT Device,
  505. IN ULONG IoctlCode,
  506. IN PVOID InputBuffer OPTIONAL,
  507. IN ULONG InputBufferLength,
  508. IN PVOID OutputBuffer OPTIONAL,
  509. IN ULONG OutputBufferLength
  510. )
  511. /*++
  512. Description:
  513. Builds and send an IOCTL to a device and return the results
  514. Arguments:
  515. Device - a device on the device stack to receive the IOCTL - the
  516. irp is always sent to the top of the stack
  517. IoctlCode - the IOCTL to run
  518. InputBuffer - arguments to the IOCTL
  519. InputBufferLength - length in bytes of the InputBuffer
  520. OutputBuffer - data returned by the IOCTL
  521. OnputBufferLength - the size in bytes of the OutputBuffer
  522. Return Value:
  523. Status
  524. --*/
  525. {
  526. NTSTATUS status;
  527. IO_STATUS_BLOCK ioStatus;
  528. KEVENT event;
  529. PIRP irp;
  530. PDEVICE_OBJECT targetDevice = NULL;
  531. PAGED_CODE();
  532. KeInitializeEvent(&event, SynchronizationEvent, FALSE);
  533. //
  534. // Get the top of the stack to send the IRP to
  535. //
  536. targetDevice = IoGetAttachedDeviceReference(Device);
  537. if (!targetDevice) {
  538. status = STATUS_INVALID_PARAMETER;
  539. goto exit;
  540. }
  541. //
  542. // Get Io to build the IRP for us
  543. //
  544. irp = IoBuildDeviceIoControlRequest(IoctlCode,
  545. targetDevice,
  546. InputBuffer,
  547. InputBufferLength,
  548. OutputBuffer,
  549. OutputBufferLength,
  550. FALSE, // InternalDeviceIoControl
  551. &event,
  552. &ioStatus
  553. );
  554. if (!irp) {
  555. status = STATUS_INSUFFICIENT_RESOURCES;
  556. goto exit;
  557. }
  558. //
  559. // Send the IRP and wait for it to complete
  560. //
  561. status = IoCallDriver(targetDevice, irp);
  562. if (status == STATUS_PENDING) {
  563. KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
  564. status = ioStatus.Status;
  565. }
  566. exit:
  567. if (targetDevice) {
  568. ObDereferenceObject(targetDevice);
  569. }
  570. return status;
  571. }
  572. NTSTATUS
  573. SpSimDevControl(
  574. IN PDEVICE_OBJECT DeviceObject,
  575. IN PIRP Irp
  576. )
  577. /*++
  578. Routine Description:
  579. DeviceIoControl handler. It can handle both IOCTL_MEC_BIOS_OP_ACCESS and IOCTL_MEC_LOCAL_OP_ACCESS
  580. calls.
  581. For example purposes this handles running ACPI methods in the bios.
  582. Arguments:
  583. DeviceObject - Pointer to class device object.
  584. Irp - Pointer to the request packet.
  585. Return Value:
  586. ntStatus
  587. --*/
  588. {
  589. PIO_STACK_LOCATION CurrentIrpStack;
  590. PSPSIM_EXTENSION spsim = (PSPSIM_EXTENSION) DeviceObject->DeviceExtension;
  591. NTSTATUS status;
  592. if (Irp == NULL) {
  593. return STATUS_INVALID_PARAMETER_2;
  594. }
  595. if (!(CurrentIrpStack=IoGetCurrentIrpStackLocation(Irp))) {
  596. Irp->IoStatus.Status = STATUS_INVALID_PARAMETER_2;
  597. IoCompleteRequest(Irp, 0);
  598. return STATUS_INVALID_PARAMETER_2;
  599. }
  600. switch(CurrentIrpStack->Parameters.DeviceIoControl.IoControlCode) {
  601. case IOCTL_SPSIM_GET_MANAGED_DEVICES:
  602. status = SpSimGetManagedDevicesIoctl(spsim, Irp, CurrentIrpStack);
  603. break;
  604. case IOCTL_SPSIM_ACCESS_STA:
  605. status = SpSimAccessStaIoctl(spsim, Irp, CurrentIrpStack);
  606. break;
  607. case IOCTL_SPSIM_NOTIFY_DEVICE:
  608. status = SpSimNotifyDeviceIoctl(spsim, Irp, CurrentIrpStack);
  609. break;
  610. case IOCTL_SPSIM_GET_DEVICE_NAME:
  611. status = SpSimGetDeviceName(spsim, Irp, CurrentIrpStack);
  612. break;
  613. default:
  614. status = SpSimPassIrp(Irp, spsim, CurrentIrpStack);
  615. return status;
  616. }
  617. Irp->IoStatus.Status = status;
  618. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  619. return status;
  620. }
  621. VOID
  622. SpSimPowerCallback(
  623. IN PDEVICE_OBJECT DeviceObject,
  624. IN UCHAR MinorFunction,
  625. IN POWER_STATE PowerState,
  626. IN PVOID Context,
  627. IN PIO_STATUS_BLOCK IoStatus
  628. )
  629. {
  630. PSPSIM_EXTENSION deviceExtension;
  631. PIRP Irp;
  632. NTSTATUS status;
  633. Irp = Context;
  634. deviceExtension = DeviceObject->DeviceExtension;
  635. Irp->IoStatus.Status = IoStatus->Status;
  636. PoStartNextPowerIrp(Irp);
  637. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  638. IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp);
  639. }
  640. NTSTATUS
  641. SpSimPowerCompletion(
  642. IN PDEVICE_OBJECT DeviceObject,
  643. IN PIRP Irp,
  644. IN PVOID NotUsed
  645. )
  646. /*++
  647. Routine Description:
  648. The completion routine for Power
  649. Arguments:
  650. DeviceObject - pointer to a device object.
  651. Irp - pointer to an I/O Request Packet.
  652. Not used - context pointer
  653. Return Value:
  654. NT status code
  655. --*/
  656. {
  657. PIO_STACK_LOCATION irpStack;
  658. PSPSIM_EXTENSION deviceExtension;
  659. NTSTATUS status;
  660. irpStack = IoGetCurrentIrpStackLocation(Irp);
  661. deviceExtension = DeviceObject->DeviceExtension;
  662. if (irpStack->Parameters.Power.Type == SystemPowerState) {
  663. SYSTEM_POWER_STATE system =
  664. irpStack->Parameters.Power.State.SystemState;
  665. POWER_STATE power;
  666. if (NT_SUCCESS(Irp->IoStatus.Status)) {
  667. power.DeviceState = deviceExtension->DeviceStateMapping[system];
  668. PoRequestPowerIrp(DeviceObject,
  669. irpStack->MinorFunction,
  670. power,
  671. SpSimPowerCallback,
  672. Irp,
  673. NULL);
  674. return STATUS_MORE_PROCESSING_REQUIRED;
  675. } else {
  676. status = Irp->IoStatus.Status;
  677. PoStartNextPowerIrp(Irp);
  678. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  679. IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp);
  680. return STATUS_MORE_PROCESSING_REQUIRED;
  681. }
  682. } else {
  683. if (NT_SUCCESS(Irp->IoStatus.Status)) {
  684. PoSetPowerState(DeviceObject, DevicePowerState,
  685. irpStack->Parameters.Power.State);
  686. deviceExtension->PowerState =
  687. irpStack->Parameters.Power.State.DeviceState;
  688. }
  689. PoStartNextPowerIrp(Irp);
  690. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  691. return STATUS_MORE_PROCESSING_REQUIRED;
  692. }
  693. }
  694. NTSTATUS
  695. SpSimDispatchPower(
  696. IN PDEVICE_OBJECT DeviceObject,
  697. IN PIRP Irp
  698. )
  699. {
  700. PSPSIM_EXTENSION deviceExtension;
  701. PIO_STACK_LOCATION irpStack;
  702. NTSTATUS status;
  703. irpStack = IoGetCurrentIrpStackLocation(Irp);
  704. deviceExtension = DeviceObject->DeviceExtension;
  705. status = IoAcquireRemoveLock(&deviceExtension->RemoveLock, (PVOID) Irp);
  706. if (status == STATUS_DELETE_PENDING) {
  707. Irp->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
  708. PoStartNextPowerIrp(Irp);
  709. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  710. return STATUS_NO_SUCH_DEVICE;
  711. }
  712. if (irpStack->Parameters.Power.Type == SystemPowerState) {
  713. switch (irpStack->MinorFunction) {
  714. case IRP_MN_QUERY_POWER:
  715. case IRP_MN_SET_POWER:
  716. IoCopyCurrentIrpStackLocationToNext(Irp);
  717. IoSetCompletionRoutine(Irp,
  718. SpSimPowerCompletion,
  719. NULL, //Context
  720. TRUE, //InvokeOnSuccess
  721. TRUE, //InvokeOnError
  722. TRUE //InvokeOnCancel
  723. );
  724. return PoCallDriver(deviceExtension->AttachedDevice, Irp);
  725. default:
  726. PoStartNextPowerIrp(Irp);
  727. IoSkipCurrentIrpStackLocation(Irp);
  728. status = PoCallDriver(deviceExtension->AttachedDevice, Irp);
  729. IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp);
  730. return status;
  731. }
  732. } else {
  733. switch (irpStack->MinorFunction) {
  734. case IRP_MN_SET_POWER:
  735. if (irpStack->Parameters.Power.State.DeviceState >
  736. deviceExtension->PowerState) {
  737. IoCopyCurrentIrpStackLocationToNext(Irp);
  738. IoSetCompletionRoutine(Irp,
  739. SpSimPowerCompletion,
  740. NULL, //Context
  741. TRUE, //InvokeOnSuccess
  742. TRUE, //InvokeOnError
  743. TRUE //InvokeOnCancel
  744. );
  745. break;
  746. } else {
  747. PoSetPowerState(DeviceObject, DevicePowerState,
  748. irpStack->Parameters.Power.State);
  749. deviceExtension->PowerState =
  750. irpStack->Parameters.Power.State.DeviceState;
  751. //
  752. // Fall through ...
  753. //
  754. }
  755. case IRP_MN_QUERY_POWER:
  756. //
  757. // Fall through as the bus driver will mark this
  758. // STATUS_SUCCESS and complete it, if it gets that far.
  759. //
  760. default:
  761. PoStartNextPowerIrp(Irp);
  762. IoSkipCurrentIrpStackLocation(Irp);
  763. break;
  764. }
  765. status = PoCallDriver(deviceExtension->AttachedDevice, Irp);
  766. IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp);
  767. return status;
  768. }
  769. }