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.

2140 lines
52 KiB

  1. /*++
  2. Copyright (c) 2000-2001 Microsoft Corporation
  3. Module Name:
  4. dispatch.c
  5. Abstract:
  6. ACPI BIOS Simulator / Generic 3rd Party Operation Region Provider
  7. Pnp / Power handler module
  8. Author(s):
  9. Vincent Geglia
  10. Michael T. Murphy
  11. Chris Burgess
  12. Environment:
  13. Kernel mode
  14. Notes:
  15. Revision History:
  16. --*/
  17. //
  18. // General includes
  19. //
  20. #include "ntddk.h"
  21. //
  22. // Specific includes
  23. //
  24. #include "acpisim.h"
  25. #include "dispatch.h"
  26. #include "util.h"
  27. //
  28. // Private function prototypes
  29. //
  30. NTSTATUS
  31. AcpisimPnpStartDevice
  32. (
  33. IN PDEVICE_OBJECT DeviceObject,
  34. IN PIRP Irp
  35. );
  36. NTSTATUS
  37. AcpisimPnpStopDevice
  38. (
  39. IN PDEVICE_OBJECT DeviceObject,
  40. IN PIRP Irp
  41. );
  42. NTSTATUS
  43. AcpisimPnpQueryStopDevice
  44. (
  45. IN PDEVICE_OBJECT DeviceObject,
  46. IN PIRP Irp
  47. );
  48. NTSTATUS
  49. AcpisimPnpCancelStopDevice
  50. (
  51. IN PDEVICE_OBJECT DeviceObject,
  52. IN PIRP Irp
  53. );
  54. NTSTATUS
  55. AcpisimPnpRemoveDevice
  56. (
  57. IN PDEVICE_OBJECT DeviceObject,
  58. IN PIRP Irp
  59. );
  60. NTSTATUS
  61. AcpisimPnpQueryRemoveDevice
  62. (
  63. IN PDEVICE_OBJECT DeviceObject,
  64. IN PIRP Irp
  65. );
  66. NTSTATUS
  67. AcpisimPnpCancelRemoveDevice
  68. (
  69. IN PDEVICE_OBJECT DeviceObject,
  70. IN PIRP Irp
  71. );
  72. NTSTATUS
  73. AcpisimPnpSurpriseRemoval
  74. (
  75. IN PDEVICE_OBJECT DeviceObject,
  76. IN PIRP Irp
  77. );
  78. NTSTATUS
  79. AcpisimPnpQueryCapabilities
  80. (
  81. IN PDEVICE_OBJECT DeviceObject,
  82. IN PIRP Irp
  83. );
  84. NTSTATUS
  85. AcpisimPowerQueryPower
  86. (
  87. IN PDEVICE_OBJECT DeviceObject,
  88. IN PIRP Irp
  89. );
  90. NTSTATUS
  91. AcpisimPowerSetPower
  92. (
  93. IN PDEVICE_OBJECT DeviceObject,
  94. IN PIRP Irp
  95. );
  96. NTSTATUS
  97. AcpisimPowerSIrp
  98. (
  99. IN PDEVICE_OBJECT DeviceObject,
  100. IN PIRP Irp
  101. );
  102. NTSTATUS
  103. AcpisimQueryPowerDIrp
  104. (
  105. IN PDEVICE_OBJECT DeviceObject,
  106. IN PIRP Irp
  107. );
  108. NTSTATUS
  109. AcpisimSetPowerDIrp
  110. (
  111. IN PDEVICE_OBJECT DeviceObject,
  112. IN PIRP Irp
  113. );
  114. NTSTATUS
  115. AcpisimCompletionRoutine
  116. (
  117. IN PDEVICE_OBJECT DeviceObject,
  118. IN PIRP Irp,
  119. IN PVOID Context
  120. );
  121. NTSTATUS
  122. AcpisimForwardIrpAndWait
  123. (
  124. IN PDEVICE_OBJECT DeviceObject,
  125. IN PIRP Irp
  126. );
  127. NTSTATUS
  128. AcpisimIssuePowerDIrp
  129. (
  130. IN PDEVICE_OBJECT DeviceObject,
  131. IN PIRP Irp,
  132. IN PVOID Context
  133. );
  134. NTSTATUS
  135. AcpisimCompleteSIrp
  136. (
  137. IN PDEVICE_OBJECT DeviceObject,
  138. IN UCHAR MinorFunction,
  139. IN POWER_STATE PowerState,
  140. IN PVOID Context,
  141. IN PIO_STATUS_BLOCK IoStatus
  142. );
  143. NTSTATUS
  144. AcpisimD0Completion
  145. (
  146. IN PDEVICE_OBJECT DeviceObject,
  147. IN PIRP Irp,
  148. IN PVOID Context
  149. );
  150. VOID
  151. AcpisimInitDevPowerStateTable
  152. (
  153. IN PDEVICE_OBJECT DeviceObject
  154. );
  155. //
  156. // Pnp minor dispatch table
  157. //
  158. IRP_DISPATCH_TABLE PnpDispatchTable[] = {
  159. IRP_MN_START_DEVICE, "Pnp/START_DEVICE", AcpisimPnpStartDevice,
  160. IRP_MN_STOP_DEVICE, "Pnp/STOP_DEVICE", AcpisimPnpStopDevice,
  161. IRP_MN_QUERY_STOP_DEVICE, "Pnp/QUERY_STOP_DEVICE", AcpisimPnpQueryStopDevice,
  162. IRP_MN_CANCEL_STOP_DEVICE, "Pnp/CANCEL_STOP_DEVICE", AcpisimPnpCancelStopDevice,
  163. IRP_MN_REMOVE_DEVICE, "Pnp/REMOVE_DEVICE", AcpisimPnpRemoveDevice,
  164. IRP_MN_QUERY_REMOVE_DEVICE, "Pnp/QUERY_REMOVE_DEVICE", AcpisimPnpQueryRemoveDevice,
  165. IRP_MN_CANCEL_REMOVE_DEVICE,"Pnp/CANCEL_REMOVE_DEVICE", AcpisimPnpCancelRemoveDevice,
  166. IRP_MN_SURPRISE_REMOVAL, "Pnp/SURPRISE_REMOVAL", AcpisimPnpSurpriseRemoval,
  167. IRP_MN_QUERY_CAPABILITIES, "Pnp/QUERY_CAPABILITIIES", AcpisimPnpQueryCapabilities
  168. };
  169. //
  170. // Power minor dispatch table
  171. //
  172. IRP_DISPATCH_TABLE PowerDispatchTable[] = {
  173. IRP_MN_QUERY_POWER, "Power/QUERY_POWER", AcpisimPowerQueryPower,
  174. IRP_MN_SET_POWER, "Power/SET_POWER", AcpisimPowerSetPower
  175. };
  176. NTSTATUS
  177. AcpisimDispatchPnp
  178. (
  179. IN PDEVICE_OBJECT DeviceObject,
  180. IN PIRP Irp
  181. )
  182. /*++
  183. Routine Description:
  184. This is the pnp IRP handler. It checks the minor code,
  185. and passes on to the appropriate minor handler.
  186. Arguments:
  187. DeviceObject - pointer to the device object the IRP pertains to
  188. Irp - pointer to the IRP
  189. Return Value:
  190. result of IRP processing
  191. --*/
  192. {
  193. PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation (Irp);
  194. PDEVICE_EXTENSION deviceextension = AcpisimGetDeviceExtension (DeviceObject);
  195. NTSTATUS status = STATUS_UNSUCCESSFUL;
  196. ULONG count = 0;
  197. DBG_PRINT (DBG_INFO, "Entering AcpisimDispatchPnp.\n");
  198. while (count < sizeof (PnpDispatchTable) / sizeof (IRP_DISPATCH_TABLE)) {
  199. if (irpsp->MinorFunction == PnpDispatchTable[count].IrpFunction) {
  200. DBG_PRINT (DBG_INFO,
  201. "Recognized PnP IRP 0x%x '%s'.\n",
  202. irpsp->MinorFunction,
  203. PnpDispatchTable[count].IrpName);
  204. status = PnpDispatchTable[count].IrpHandler (DeviceObject, Irp);
  205. goto EndAcpisimDispatchPnp;
  206. }
  207. count ++;
  208. }
  209. DBG_PRINT (DBG_INFO, "Unrecognized PnP IRP 0x%x, pass it on.\n", irpsp->MinorFunction);
  210. IoSkipCurrentIrpStackLocation (Irp);
  211. status = IoCallDriver (deviceextension->NextDevice, Irp);
  212. EndAcpisimDispatchPnp:
  213. DBG_PRINT (DBG_INFO, "Exiting AcpisimDispatchPnp.\n");
  214. return status;
  215. }
  216. NTSTATUS
  217. AcpisimDispatchPower
  218. (
  219. IN PDEVICE_OBJECT DeviceObject,
  220. IN PIRP Irp
  221. )
  222. /*++
  223. Routine Description:
  224. This is the power IRP handler. It checks the minor code,
  225. and passes on to the appropriate minor handler.
  226. Arguments:
  227. DeviceObject - pointer to the device object the IRP pertains to
  228. Irp - pointer to the IRP
  229. Return Value:
  230. result of IRP processing
  231. --*/
  232. {
  233. PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation (Irp);
  234. PDEVICE_EXTENSION deviceextension = AcpisimGetDeviceExtension (DeviceObject);
  235. NTSTATUS status = STATUS_UNSUCCESSFUL;
  236. ULONG count = 0;
  237. DBG_PRINT (DBG_INFO, "Entering AcpisimDispatchPower.\n");
  238. while (count < sizeof (PowerDispatchTable) / sizeof (IRP_DISPATCH_TABLE)) {
  239. if (irpsp->MinorFunction == PowerDispatchTable[count].IrpFunction) {
  240. DBG_PRINT (DBG_INFO,
  241. "Recognized Power IRP 0x%x '%s'.\n",
  242. irpsp->MinorFunction,
  243. PowerDispatchTable[count].IrpName);
  244. status = PowerDispatchTable[count].IrpHandler (DeviceObject, Irp);
  245. goto EndAcpisimDispatchPower;
  246. }
  247. count ++;
  248. }
  249. DBG_PRINT (DBG_INFO, "Unrecognized Power IRP 0x%x, pass it on.\n", irpsp->MinorFunction);
  250. PoStartNextPowerIrp (Irp);
  251. IoSkipCurrentIrpStackLocation (Irp);
  252. status = PoCallDriver (deviceextension->NextDevice, Irp);
  253. EndAcpisimDispatchPower:
  254. DBG_PRINT (DBG_INFO, "Exiting AcpisimDispatchPower.\n");
  255. return status;
  256. }
  257. NTSTATUS
  258. AcpisimPnpStartDevice
  259. (
  260. IN PDEVICE_OBJECT DeviceObject,
  261. IN PIRP Irp
  262. )
  263. /*++
  264. Routine Description:
  265. This is the Pnp Start Device handler. It enables the device interface
  266. and registers the operation region handler.
  267. Arguments:
  268. DeviceObject - pointer to the device object the IRP pertains to
  269. Irp - pointer to the IRP
  270. Return Value:
  271. result of IRP_MN_START_DEVICE processing
  272. --*/
  273. {
  274. NTSTATUS status = STATUS_UNSUCCESSFUL;
  275. PDEVICE_EXTENSION deviceextension = AcpisimGetDeviceExtension (DeviceObject);
  276. KIRQL oldirql;
  277. DBG_PRINT (DBG_INFO,
  278. "Entering AcpisimPnpStartDevice.\n");
  279. //
  280. // We handle this IRP on the way back up.
  281. //
  282. status = AcpisimForwardIrpAndWait (DeviceObject, Irp);
  283. ASSERT (NT_SUCCESS (status));
  284. if ((status != STATUS_SUCCESS && status != STATUS_PENDING) || !NT_SUCCESS (Irp->IoStatus.Status)) {
  285. DBG_PRINT (DBG_ERROR,
  286. "Error processing, or lower driver failed start IRP. IoCallDriver = %lx, Irp->IoStatus.Status = %lx\n",
  287. status,
  288. Irp->IoStatus.Status);
  289. goto EndAcpisimPnpStartDevice;
  290. }
  291. //
  292. // Check to see if we are already started. If we are,
  293. // just return success since we aren't using resources
  294. // anyway.
  295. //
  296. if (deviceextension->PnpState == PNP_STATE_STARTED) {
  297. status = STATUS_SUCCESS;
  298. goto EndAcpisimPnpStartDevice;
  299. }
  300. //
  301. // Enable our device interface
  302. //
  303. status = AcpisimEnableDisableDeviceInterface (DeviceObject, TRUE);
  304. ASSERT (NT_SUCCESS (status));
  305. if (!NT_SUCCESS (status)) {
  306. DBG_PRINT (DBG_ERROR,
  307. "Error enabling device interface. Fail the start. Status = %lx.\n",
  308. status);
  309. Irp->IoStatus.Status = status;
  310. goto EndAcpisimPnpStartDevice;
  311. }
  312. AcpisimSetDevExtFlags (DeviceObject, DE_FLAG_INTERFACE_ENABLED);
  313. //
  314. // Typically, we would check the state of our hardware, and
  315. // set our internal power state to reflect the current state
  316. // of the hardware. However, in this case we are a virtual
  317. // device, and it is safe to assume we are in D0 when we
  318. // receive IRP_MN_START_DEVICE.
  319. //
  320. AcpisimUpdatePowerState (DeviceObject, POWER_STATE_WORKING);
  321. AcpisimUpdateDevicePowerState (DeviceObject, PowerDeviceD0);
  322. //
  323. // Finally, we can register our operation region handler.
  324. //
  325. status = AcpisimRegisterOpRegionHandler (DeviceObject);
  326. ASSERT (NT_SUCCESS (status));
  327. if (!NT_SUCCESS (status)) {
  328. DBG_PRINT (DBG_ERROR,
  329. "Couldn't register op region handler (%lx). Fail start IRP.\n",
  330. status);
  331. goto EndAcpisimPnpStartDevice;
  332. }
  333. AcpisimSetDevExtFlags (DeviceObject, DE_FLAG_OPREGION_REGISTERED);
  334. EndAcpisimPnpStartDevice:
  335. //
  336. // If we completed the start successfully, change our pnp state
  337. // to PNP_STARTED
  338. //
  339. if (NT_SUCCESS (status)) {
  340. AcpisimUpdatePnpState (DeviceObject, PNP_STATE_STARTED);
  341. } else {
  342. AcpisimUpdatePnpState (DeviceObject, PNP_STATE_STOPPED);
  343. }
  344. //
  345. // Because we are handling this IRP "on the way up", we need
  346. // to complete it when we are done working with it.
  347. //
  348. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  349. DBG_PRINT (DBG_INFO,
  350. "Exiting AcpisimPnpStartDevice.\n");
  351. return status;
  352. }
  353. NTSTATUS
  354. AcpisimPnpStopDevice
  355. (
  356. IN PDEVICE_OBJECT DeviceObject,
  357. IN PIRP Irp
  358. )
  359. /*++
  360. Routine Description:
  361. This is the Pnp Stop Device handler. It checks to see if
  362. there are any outstanding requests, and fails the stop IRP
  363. if there are.
  364. Arguments:
  365. DeviceObject - pointer to the device object the IRP pertains to
  366. Irp - pointer to the IRP
  367. Return Value:
  368. result of IRP_MN_STOP_DEVICE processing
  369. --*/
  370. {
  371. NTSTATUS status = STATUS_UNSUCCESSFUL;
  372. PDEVICE_EXTENSION deviceextension = AcpisimGetDeviceExtension (DeviceObject);
  373. DBG_PRINT (DBG_INFO,
  374. "Entering AcpisimPnpStopDevice.\n");
  375. //
  376. // BUGBUG - We currently don't handle the case where
  377. // there is still an outstanding request at stop
  378. // time. If we were to do things correctly, we'd
  379. // complete any outstanding requests in the driver
  380. // with an appropriate error code. In this
  381. // particular case, if a request happened to squeak
  382. // by our check at QUERY STOP time, it is likely
  383. // the request would not be completed at all.
  384. //
  385. //
  386. // Oh, and we had better not have LESS then 2 count
  387. // or we've got a bug somewhere.
  388. //
  389. if (deviceextension->OutstandingIrpCount < 2) {
  390. DBG_PRINT (DBG_WARN,
  391. "Possible internal consistency error - OutstandingIrpCount too low.\n");
  392. }
  393. ASSERT (deviceextension->OutstandingIrpCount == 2);
  394. IoSkipCurrentIrpStackLocation (Irp);
  395. Irp->IoStatus.Status = STATUS_SUCCESS;
  396. status = IoCallDriver (deviceextension->NextDevice, Irp);
  397. ASSERT (NT_SUCCESS (status));
  398. if (!NT_SUCCESS (status)) {
  399. DBG_PRINT (DBG_ERROR,
  400. "IRP_MN_STOP forwarding failed (%lx).\n",
  401. status);
  402. goto EndAcpisimPnpStopDevice;
  403. }
  404. AcpisimUpdatePnpState (DeviceObject, PNP_STATE_STOPPED);
  405. EndAcpisimPnpStopDevice:
  406. DBG_PRINT (DBG_INFO,
  407. "Exiting AcpisimPnpStopDevice.\n");
  408. return status;
  409. }
  410. NTSTATUS
  411. AcpisimPnpQueryStopDevice
  412. (
  413. IN PDEVICE_OBJECT DeviceObject,
  414. IN PIRP Irp
  415. )
  416. /*++
  417. Routine Description:
  418. This is the Pnp Query Stop Device handler. If there are any
  419. outstanding requests, it vetos the IRP.
  420. Arguments:
  421. DeviceObject - pointer to the device object the IRP pertains to
  422. Irp - pointer to the IRP
  423. Return Value:
  424. result of IRP_MN_QUERY_STOP_DEVICE processing
  425. --*/
  426. {
  427. NTSTATUS status = STATUS_UNSUCCESSFUL;
  428. PDEVICE_EXTENSION deviceextension = AcpisimGetDeviceExtension (DeviceObject);
  429. DBG_PRINT (DBG_INFO,
  430. "Entering AcpisimPnpQueryStopDevice.\n");
  431. //
  432. // Let existing IRPs in the driver complete before we say OK.
  433. // But to do this, we need to get the OutstandingIrpsCount
  434. // right. Subtract 2 since we are biased to 1, and we have an
  435. // additional 1 for the QUERY_STOP IRP.
  436. //
  437. AcpisimDecrementIrpCount (DeviceObject);
  438. AcpisimDecrementIrpCount (DeviceObject);
  439. status = KeWaitForSingleObject (&deviceextension->IrpsCompleted,
  440. Executive,
  441. KernelMode,
  442. FALSE,
  443. 0);
  444. InterlockedIncrement (&deviceextension->OutstandingIrpCount);
  445. InterlockedIncrement (&deviceextension->OutstandingIrpCount);
  446. KeResetEvent (&deviceextension->IrpsCompleted);
  447. ASSERT (NT_SUCCESS (status));
  448. if (!NT_SUCCESS (status)) {
  449. DBG_PRINT (DBG_ERROR,
  450. "KeWaitForSingleObject failed (%lx). IRP_MN_QUERY_STOP failed.\n",
  451. status);
  452. IoSkipCurrentIrpStackLocation (Irp);
  453. Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
  454. status = IoCallDriver (deviceextension->NextDevice, Irp);
  455. ASSERT (NT_SUCCESS (status));
  456. goto EndPnpQueryStopDevice;
  457. }
  458. //
  459. // We can stop - change our state to stopping, and pass it on.
  460. //
  461. IoSkipCurrentIrpStackLocation (Irp);
  462. Irp->IoStatus.Status = STATUS_SUCCESS;
  463. status = IoCallDriver (deviceextension->NextDevice, Irp);
  464. AcpisimUpdatePnpState (DeviceObject, PNP_STATE_STOP_PENDING);
  465. EndPnpQueryStopDevice:
  466. DBG_PRINT (DBG_INFO,
  467. "Exiting AcpisimPnpQueryStopDevice.\n");
  468. return status;
  469. }
  470. NTSTATUS
  471. AcpisimPnpCancelStopDevice
  472. (
  473. IN PDEVICE_OBJECT DeviceObject,
  474. IN PIRP Irp
  475. )
  476. /*++
  477. Routine Description:
  478. This is the Pnp Cancel Stop Device handler. It does nothing
  479. more then returns the pnp state to started. This is a virtual
  480. device so there is no work to do.
  481. Arguments:
  482. DeviceObject - pointer to the device object the IRP pertains to
  483. Irp - pointer to the IRP
  484. Return Value:
  485. STATUS_SUCCESS
  486. --*/
  487. {
  488. NTSTATUS status = STATUS_UNSUCCESSFUL;
  489. DBG_PRINT (DBG_INFO,
  490. "Entering AcpisimPnpCancelStopDevice.\n");
  491. status = AcpisimForwardIrpAndWait (DeviceObject, Irp);
  492. ASSERT (NT_SUCCESS (status));
  493. if (!NT_SUCCESS (status)) {
  494. DBG_PRINT (DBG_ERROR,
  495. "IRP_MN_CANCEL_STOP forwarding failed (%lx).\n",
  496. status);
  497. goto EndPnpCancelStopDevice;
  498. }
  499. status = STATUS_SUCCESS;
  500. Irp->IoStatus.Status = status;
  501. IoCompleteRequest (Irp, 0);
  502. AcpisimUpdatePnpState (DeviceObject, PNP_STATE_STARTED);
  503. EndPnpCancelStopDevice:
  504. DBG_PRINT (DBG_INFO,
  505. "Exiting AcpisimPnpCancelStopDevice.\n");
  506. return status;
  507. }
  508. NTSTATUS
  509. AcpisimPnpRemoveDevice
  510. (
  511. IN PDEVICE_OBJECT DeviceObject,
  512. IN PIRP Irp
  513. )
  514. /*++
  515. Routine Description:
  516. This is the Pnp Remove Device handler. It de-registers the
  517. operation region handler, detaches the device object, and
  518. deletes it if all goes well.
  519. Arguments:
  520. DeviceObject - pointer to the device object the IRP pertains to
  521. Irp - pointer to the IRP
  522. Return Value:
  523. status of removal operation
  524. --*/
  525. {
  526. NTSTATUS status = STATUS_UNSUCCESSFUL;
  527. PDEVICE_EXTENSION deviceextension = AcpisimGetDeviceExtension (DeviceObject);
  528. PDEVICE_OBJECT nextdevice = deviceextension->NextDevice;
  529. DBG_PRINT (DBG_INFO,
  530. "Entering AcpisimPnpRemoveDevice.\n");
  531. //
  532. // BUGBUG - We currently don't handle the case where
  533. // there is still an outstanding request at remove
  534. // time. If we were to do things correctly, we'd
  535. // complete any outstanding requests in the driver
  536. // with an appropriate error code. In this
  537. // particular case, if a request happened to squeak
  538. // by our check at QUERY REMOVE time, it is likely
  539. // the request would not be completed at all.
  540. //
  541. //
  542. // Our OutstandingIrpCount logic is biased to 1. So
  543. // if we are processing a remove IRP, and there are
  544. // no other requests in the driver, OustandingIrpCount
  545. // had better be 2.
  546. if (deviceextension->OutstandingIrpCount < 2) {
  547. DBG_PRINT (DBG_WARN,
  548. "Possible internal consistency error - OutstandingIrpCount too low.\n");
  549. }
  550. ASSERT (deviceextension->OutstandingIrpCount == 2);
  551. //
  552. // Ok, we are ready to remove the device. Shut down the
  553. // interface, deregister the opregion handler, and
  554. // delete the device object.
  555. //
  556. status = AcpisimEnableDisableDeviceInterface (DeviceObject, FALSE);
  557. ASSERT (NT_SUCCESS (status));
  558. if (NT_SUCCESS (status)) {
  559. AcpisimClearDevExtFlags (DeviceObject, DE_FLAG_INTERFACE_ENABLED);
  560. }
  561. status = AcpisimUnRegisterOpRegionHandler (DeviceObject);
  562. ASSERT (NT_SUCCESS (status));
  563. if (NT_SUCCESS (status)) {
  564. AcpisimClearDevExtFlags (DeviceObject, DE_FLAG_OPREGION_REGISTERED);
  565. }
  566. RtlFreeUnicodeString (&deviceextension->InterfaceString);
  567. IoDetachDevice (deviceextension->NextDevice);
  568. IoDeleteDevice (DeviceObject);
  569. //
  570. // Now, pass it on...
  571. //
  572. IoSkipCurrentIrpStackLocation (Irp);
  573. Irp->IoStatus.Status = STATUS_SUCCESS;
  574. status = IoCallDriver (nextdevice, Irp);
  575. ASSERT (NT_SUCCESS (status));
  576. if (!NT_SUCCESS (status)) {
  577. DBG_PRINT (DBG_ERROR,
  578. "Passing remove IRP onto next driver failed for some reason (%lx).\n",
  579. status);
  580. }
  581. DBG_PRINT (DBG_INFO,
  582. "Exiting AcpisimPnpRemoveDevice.\n");
  583. return status;
  584. }
  585. NTSTATUS
  586. AcpisimPnpQueryRemoveDevice
  587. (
  588. IN PDEVICE_OBJECT DeviceObject,
  589. IN PIRP Irp
  590. )
  591. /*++
  592. Routine Description:
  593. This is the Pnp Query Remove Device handler. It waits for
  594. existing requests in the driver to finish, and then completes
  595. the IRP successfully.
  596. Arguments:
  597. DeviceObject - pointer to the device object the IRP pertains to
  598. Irp - pointer to the IRP
  599. Return Value:
  600. Status of query remove device operation
  601. --*/
  602. {
  603. NTSTATUS status = STATUS_UNSUCCESSFUL;
  604. PDEVICE_EXTENSION deviceextension = AcpisimGetDeviceExtension (DeviceObject);
  605. DBG_PRINT (DBG_INFO,
  606. "Entering AcpisimPnpQueryRemoveDevice.\n");
  607. //
  608. // Make sure our state is correct
  609. //
  610. ASSERT (deviceextension->OutstandingIrpCount >= 2);
  611. //
  612. // Let existing IRPs in the driver complete before we say OK.
  613. // But to do this, we need to get the OutstandingIrpsCount
  614. // right. Subtract 2 since we are biased to 1, and we have an
  615. // additional 1 for the QUERY_STOP IRP.
  616. //
  617. AcpisimDecrementIrpCount (DeviceObject);
  618. AcpisimDecrementIrpCount (DeviceObject);
  619. status = KeWaitForSingleObject (&deviceextension->IrpsCompleted,
  620. Executive,
  621. KernelMode,
  622. FALSE,
  623. 0);
  624. InterlockedIncrement (&deviceextension->OutstandingIrpCount);
  625. InterlockedIncrement (&deviceextension->OutstandingIrpCount);
  626. KeResetEvent (&deviceextension->IrpsCompleted);
  627. ASSERT (NT_SUCCESS (status));
  628. if (!NT_SUCCESS (status)) {
  629. DBG_PRINT (DBG_ERROR,
  630. "KeWaitForSingleObject failed (%lx). IRP_MN_QUERY_REMOVE failed.\n",
  631. status);
  632. IoSkipCurrentIrpStackLocation (Irp);
  633. Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
  634. status = IoCallDriver (deviceextension->NextDevice, Irp);
  635. ASSERT (NT_SUCCESS (status));
  636. goto EndPnpQueryRemoveDevice;
  637. }
  638. //
  639. // We can remove - change our state to remove pending, and pass it on.
  640. //
  641. IoSkipCurrentIrpStackLocation (Irp);
  642. Irp->IoStatus.Status = STATUS_SUCCESS;
  643. status = IoCallDriver (deviceextension->NextDevice, Irp);
  644. AcpisimUpdatePnpState (DeviceObject, PNP_STATE_REMOVE_PENDING);
  645. EndPnpQueryRemoveDevice:
  646. DBG_PRINT (DBG_INFO,
  647. "Exiting AcpisimPnpQueryRemoveDevice.\n");
  648. return status;
  649. }
  650. NTSTATUS
  651. AcpisimPnpCancelRemoveDevice
  652. (
  653. IN PDEVICE_OBJECT DeviceObject,
  654. IN PIRP Irp
  655. )
  656. /*++
  657. Routine Description:
  658. This is the Pnp Cancel Remove Device handler. It does nothing
  659. more then returns the pnp state to started. This is a virtual
  660. device so there is no work to do.
  661. Arguments:
  662. DeviceObject - pointer to the device object the IRP pertains to
  663. Irp - pointer to the IRP
  664. Return Value:
  665. STATUS_SUCCESS
  666. --*/
  667. {
  668. NTSTATUS status = STATUS_UNSUCCESSFUL;
  669. DBG_PRINT (DBG_INFO,
  670. "Entering AcpisimPnpCancelRemoveDevice.\n");
  671. status = AcpisimForwardIrpAndWait (DeviceObject, Irp);
  672. ASSERT (NT_SUCCESS (status));
  673. if (!NT_SUCCESS (status)) {
  674. DBG_PRINT (DBG_ERROR,
  675. "IRP_MN_CANCEL_REMOVE forwarding failed (%lx).\n",
  676. status);
  677. goto EndPnpCancelRemoveDevice;
  678. }
  679. status = STATUS_SUCCESS;
  680. Irp->IoStatus.Status = status;
  681. IoCompleteRequest (Irp, 0);
  682. AcpisimUpdatePnpState (DeviceObject, PNP_STATE_STARTED);
  683. EndPnpCancelRemoveDevice:
  684. DBG_PRINT (DBG_INFO,
  685. "Exiting AcpisimPnpCancelRemoveDevice.\n");
  686. return status;
  687. }
  688. NTSTATUS
  689. AcpisimPnpSurpriseRemoval
  690. (
  691. IN PDEVICE_OBJECT DeviceObject,
  692. IN PIRP Irp
  693. )
  694. /*++
  695. Routine Description:
  696. This is the Pnp Surprise Remove handler. It basically updates
  697. the state, and passes the IRP on.
  698. Arguments:
  699. DeviceObject - pointer to the device object the IRP pertains to
  700. Irp - pointer to the IRP
  701. Return Value:
  702. STATUS_SUCCESS
  703. --*/
  704. {
  705. NTSTATUS status = STATUS_UNSUCCESSFUL;
  706. PDEVICE_EXTENSION deviceextension = AcpisimGetDeviceExtension (DeviceObject);
  707. DBG_PRINT (DBG_INFO,
  708. "Entering AcpisimPnpSurpriseRemoval.\n");
  709. //
  710. // Again, because we are a virtual device, handling
  711. // surprise remove is really a no-op. Just update
  712. // our state, and succeed the IRP.
  713. //
  714. AcpisimUpdatePnpState (DeviceObject, PNP_STATE_SURPRISE_REMOVAL);
  715. IoSkipCurrentIrpStackLocation (Irp);
  716. Irp->IoStatus.Status = STATUS_SUCCESS;
  717. status = IoCallDriver (deviceextension->NextDevice, Irp);
  718. ASSERT (NT_SUCCESS (status));
  719. DBG_PRINT (DBG_INFO,
  720. "Exiting AcpisimPnpSurpriseRemoval.\n");
  721. return status;
  722. }
  723. NTSTATUS
  724. AcpisimPnpQueryCapabilities
  725. (
  726. IN PDEVICE_OBJECT DeviceObject,
  727. IN PIRP Irp
  728. )
  729. /*++
  730. Routine Description:
  731. This routine handles IRP_MN_QUERY_CAPABILITIES. We need this
  732. information to build our power state table correctly. All
  733. we do here is set a completion routine, as we need to gather this
  734. data after the PDO has filled out DeviceState.
  735. Arguments:
  736. DeviceObject - pointer to the device object the IRP pertains to
  737. Irp - pointer to the IRP
  738. Return Value:
  739. Status of operation
  740. --*/
  741. {
  742. NTSTATUS status = STATUS_UNSUCCESSFUL;
  743. PDEVICE_EXTENSION deviceextension = AcpisimGetDeviceExtension (DeviceObject);
  744. PIO_STACK_LOCATION irpsp;
  745. UCHAR count = 0;
  746. DBG_PRINT (DBG_INFO,
  747. "Entering AcpisimPnpQueryCapabilities.\n");
  748. //
  749. // Fill out the power mapping table with a default
  750. //
  751. AcpisimInitDevPowerStateTable (DeviceObject);
  752. //
  753. // Handle this IRP after the PDO has filled out the structure
  754. //
  755. status = AcpisimForwardIrpAndWait (DeviceObject, Irp);
  756. if (!NT_SUCCESS (status)) {
  757. DBG_PRINT (DBG_ERROR, "Somebody failed the QUERY_CAPABILITIES IRP...\n");
  758. goto EndAcpisimPnpQueryCapabilities;
  759. }
  760. irpsp = IoGetCurrentIrpStackLocation (Irp);
  761. //
  762. // Update our power mappings with what we found in the device
  763. // capabilities structure. We only use valid mappings, e.g.
  764. // PowerDeviceUnspecified is ignored.
  765. //
  766. DBG_PRINT (DBG_INFO, "Device mappings:\n");
  767. for (count = 0; count < 6; count ++) {
  768. if (irpsp->Parameters.DeviceCapabilities.Capabilities->DeviceState[count + 1] != PowerDeviceUnspecified) {
  769. deviceextension->PowerMappings[count] = irpsp->Parameters.DeviceCapabilities.Capabilities->DeviceState [count + 1];
  770. }
  771. DBG_PRINT (DBG_INFO, "S%d --> D%d\n", count, deviceextension->PowerMappings[count] - 1);
  772. }
  773. status = STATUS_SUCCESS;
  774. Irp->IoStatus.Status = status;
  775. EndAcpisimPnpQueryCapabilities:
  776. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  777. DBG_PRINT (DBG_INFO,
  778. "Exiting AcpisimPnpQueryCapabilities.\n");
  779. return status;
  780. }
  781. NTSTATUS
  782. AcpisimPowerQueryPower
  783. (
  784. IN PDEVICE_OBJECT DeviceObject,
  785. IN PIRP Irp
  786. )
  787. /*++
  788. Routine Description:
  789. This is the QUERY Power handler. It determines if the power
  790. IRP is an S or D IRP, and passes it on to the proper handler.
  791. Arguments:
  792. DeviceObject - pointer to the device object the IRP pertains to
  793. Irp - pointer to the IRP
  794. Return Value:
  795. Status returned from power handler
  796. --*/
  797. {
  798. PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation (Irp);
  799. PDEVICE_EXTENSION deviceextension = AcpisimGetDeviceExtension (DeviceObject);
  800. NTSTATUS status = STATUS_UNSUCCESSFUL;
  801. DBG_PRINT (DBG_INFO,
  802. "Entering AcpisimPowerQueryPower.\n");
  803. switch (irpsp->Parameters.Power.Type) {
  804. case SystemPowerState:
  805. status = AcpisimPowerSIrp (DeviceObject, Irp);
  806. break;
  807. case DevicePowerState:
  808. status = AcpisimQueryPowerDIrp (DeviceObject, Irp);
  809. break;
  810. default:
  811. DBG_PRINT (DBG_ERROR,
  812. "Undefined QUERY Power IRP type. Ignoring.\n");
  813. IoSkipCurrentIrpStackLocation (Irp);
  814. status = IoCallDriver (deviceextension->NextDevice, Irp);
  815. }
  816. DBG_PRINT (DBG_INFO,
  817. "Exiting AcpisimPowerQueryPower.\n");
  818. return status;
  819. }
  820. NTSTATUS
  821. AcpisimPowerSetPower
  822. (
  823. IN PDEVICE_OBJECT DeviceObject,
  824. IN PIRP Irp
  825. )
  826. /*++
  827. Routine Description:
  828. This is the SET Power handler. It determines if the power
  829. IRP is an S or D IRP, and passes it on to the proper handler.
  830. Arguments:
  831. DeviceObject - pointer to the device object the IRP pertains to
  832. Irp - pointer to the IRP
  833. Return Value:
  834. Status returned from power handler
  835. --*/
  836. {
  837. PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation (Irp);
  838. PDEVICE_EXTENSION deviceextension = AcpisimGetDeviceExtension (DeviceObject);
  839. NTSTATUS status = STATUS_UNSUCCESSFUL;
  840. DBG_PRINT (DBG_INFO,
  841. "Entering AcpisimPowerSetPower.\n");
  842. switch (irpsp->Parameters.Power.Type) {
  843. case SystemPowerState:
  844. status = AcpisimPowerSIrp (DeviceObject, Irp);
  845. break;
  846. case DevicePowerState:
  847. status = AcpisimSetPowerDIrp (DeviceObject, Irp);
  848. break;
  849. default:
  850. DBG_PRINT (DBG_ERROR,
  851. "Undefined SET Power IRP type. Ignoring.\n");
  852. IoSkipCurrentIrpStackLocation (Irp);
  853. status = IoCallDriver (deviceextension->NextDevice, Irp);
  854. }
  855. DBG_PRINT (DBG_INFO,
  856. "Exiting AcpisimPowerSetPower.\n");
  857. return status;
  858. }
  859. NTSTATUS
  860. AcpisimPowerSIrp
  861. (
  862. IN PDEVICE_OBJECT DeviceObject,
  863. IN PIRP Irp
  864. )
  865. /*++
  866. Routine Description:
  867. This is the power handler for S IRPs. It sets a
  868. completion routine, which will queue a D IRP. We don't
  869. do anything unless it is a D IRP.
  870. Arguments:
  871. DeviceObject - pointer to the device object the IRP pertains to
  872. Irp - pointer to the IRP
  873. Return Value:
  874. Status returned from power handler
  875. --*/
  876. {
  877. PDEVICE_EXTENSION deviceextension = AcpisimGetDeviceExtension (DeviceObject);
  878. DBG_PRINT (DBG_INFO,
  879. "Entering AcpisimPowerSIrp.\n");
  880. IoMarkIrpPending (Irp);
  881. IoCopyCurrentIrpStackLocationToNext (Irp);
  882. IoSetCompletionRoutine (Irp,
  883. AcpisimIssuePowerDIrp,
  884. 0,
  885. TRUE,
  886. TRUE,
  887. TRUE);
  888. PoCallDriver (deviceextension->NextDevice, Irp);
  889. DBG_PRINT (DBG_INFO,
  890. "Exiting AcpisimPowerSIrp.\n");
  891. return STATUS_PENDING;
  892. }
  893. NTSTATUS
  894. AcpisimQueryPowerDIrp
  895. (
  896. IN PDEVICE_OBJECT DeviceObject,
  897. IN PIRP Irp
  898. )
  899. /*++
  900. Routine Description:
  901. This is the QUERY Power DIrp handler. Validate the state, and
  902. say yes.
  903. Arguments:
  904. DeviceObject - pointer to the device object the IRP pertains to
  905. Irp - pointer to the IRP
  906. Return Value:
  907. Status returned from power handler
  908. --*/
  909. {
  910. NTSTATUS status = STATUS_UNSUCCESSFUL;
  911. PDEVICE_EXTENSION deviceextension = AcpisimGetDeviceExtension (DeviceObject);
  912. PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation (Irp);
  913. DBG_PRINT (DBG_INFO,
  914. "Entering AcpisimQueryPowerDIrp.\n");
  915. //
  916. // Here, we are supposed to figure out if we can go to the
  917. // power state specified by the IRP. Since we are a virtual
  918. // device, we don't have a good reason to not go to a different
  919. // power state. Update our state, and wait to complete requests.
  920. //
  921. AcpisimDecrementIrpCount (DeviceObject);
  922. AcpisimDecrementIrpCount (DeviceObject);
  923. AcpisimDecrementIrpCount (DeviceObject);
  924. status = KeWaitForSingleObject (&deviceextension->IrpsCompleted,
  925. Executive,
  926. KernelMode,
  927. FALSE,
  928. 0);
  929. InterlockedIncrement (&deviceextension->OutstandingIrpCount);
  930. InterlockedIncrement (&deviceextension->OutstandingIrpCount);
  931. KeResetEvent (&deviceextension->IrpsCompleted);
  932. ASSERT (NT_SUCCESS (status));
  933. //
  934. // Validate the D IRP
  935. //
  936. switch (irpsp->Parameters.Power.State.DeviceState) {
  937. case PowerDeviceD0:
  938. case PowerDeviceD1:
  939. case PowerDeviceD2:
  940. case PowerDeviceD3:
  941. AcpisimUpdatePowerState (DeviceObject, POWER_STATE_POWER_PENDING);
  942. status = STATUS_SUCCESS;
  943. break;
  944. default:
  945. ASSERT (0);
  946. DBG_PRINT (DBG_ERROR,
  947. "AcpisimQueryPowerDIrp: Illegal or unknown PowerDeviceState. Failing.\n");
  948. status = STATUS_INVALID_DEVICE_REQUEST;
  949. }
  950. PoStartNextPowerIrp (Irp);
  951. IoSkipCurrentIrpStackLocation (Irp);
  952. Irp->IoStatus.Status = status;
  953. status = PoCallDriver (deviceextension->NextDevice, Irp);
  954. ASSERT (NT_SUCCESS (status));
  955. DBG_PRINT (DBG_INFO,
  956. "Leaving AcpisimQueryPowerDIrp.\n");
  957. return status;
  958. }
  959. NTSTATUS
  960. AcpisimSetPowerDIrp
  961. (
  962. IN PDEVICE_OBJECT DeviceObject,
  963. IN PIRP Irp
  964. )
  965. {
  966. NTSTATUS status = STATUS_UNSUCCESSFUL;
  967. PDEVICE_EXTENSION deviceextension = AcpisimGetDeviceExtension (DeviceObject);
  968. PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation (Irp);
  969. POWER_STATE powerstate;
  970. DBG_PRINT (DBG_INFO,
  971. "Entering AcpisimSetPowerDIrp.\n");
  972. //
  973. // Validate the D IRP
  974. //
  975. switch (irpsp->Parameters.Power.State.DeviceState) {
  976. //
  977. // For D0, if we are powered down, we need to pass the IRP down, and
  978. // set a completion routine. We need the PDO to succeed the power
  979. // up before we do.
  980. //
  981. case PowerDeviceD0:
  982. if (deviceextension->PowerState != POWER_STATE_WORKING) {
  983. IoCopyCurrentIrpStackLocationToNext (Irp);
  984. IoSetCompletionRoutine (Irp,
  985. AcpisimD0Completion,
  986. 0,
  987. TRUE,
  988. TRUE,
  989. TRUE);
  990. IoMarkIrpPending (Irp);
  991. PoCallDriver (deviceextension->NextDevice, Irp);
  992. status = STATUS_PENDING;
  993. goto EndAcpisimSetPowerDIrp;
  994. }
  995. break;
  996. case PowerDeviceD1:
  997. powerstate.DeviceState = PowerDeviceD1;
  998. PoSetPowerState (DeviceObject, DevicePowerState, powerstate);
  999. AcpisimUpdatePowerState (DeviceObject, POWER_STATE_POWERED_DOWN);
  1000. AcpisimUpdateDevicePowerState (DeviceObject, irpsp->Parameters.Power.State.DeviceState);
  1001. status = STATUS_SUCCESS;
  1002. break;
  1003. case PowerDeviceD2:
  1004. powerstate.DeviceState = PowerDeviceD2;
  1005. PoSetPowerState (DeviceObject, DevicePowerState, powerstate);
  1006. AcpisimUpdatePowerState (DeviceObject, POWER_STATE_POWERED_DOWN);
  1007. AcpisimUpdateDevicePowerState (DeviceObject, irpsp->Parameters.Power.State.DeviceState);
  1008. status = STATUS_SUCCESS;
  1009. break;
  1010. case PowerDeviceD3:
  1011. powerstate.DeviceState = PowerDeviceD3;
  1012. PoSetPowerState (DeviceObject, DevicePowerState, powerstate);
  1013. AcpisimUpdatePowerState (DeviceObject, POWER_STATE_POWERED_DOWN);
  1014. AcpisimUpdateDevicePowerState (DeviceObject, irpsp->Parameters.Power.State.DeviceState);
  1015. status = STATUS_SUCCESS;
  1016. break;
  1017. default:
  1018. ASSERT (0);
  1019. DBG_PRINT (DBG_ERROR,
  1020. "AcpisimSetPowerDIrp: Illegal or unknown PowerDeviceState. Failing.\n");
  1021. status = STATUS_INVALID_DEVICE_REQUEST;
  1022. }
  1023. PoStartNextPowerIrp (Irp);
  1024. IoSkipCurrentIrpStackLocation (Irp);
  1025. Irp->IoStatus.Status = status;
  1026. status = PoCallDriver (deviceextension->NextDevice, Irp);
  1027. ASSERT (NT_SUCCESS (status));
  1028. EndAcpisimSetPowerDIrp:
  1029. DBG_PRINT (DBG_INFO,
  1030. "Leaving AcpisimSetPowerDIrp.\n");
  1031. return status;
  1032. }
  1033. NTSTATUS
  1034. AcpisimCompletionRoutine
  1035. (
  1036. IN PDEVICE_OBJECT DeviceObject,
  1037. IN PIRP Irp,
  1038. IN PVOID Context
  1039. )
  1040. /*++
  1041. Routine Description:
  1042. This is the generic Irp completion routine for when we
  1043. want to wait for an IRP to be completed by the PDO and
  1044. do post-completion work.
  1045. Arguments:
  1046. DeviceObject - pointer to the device object the IRP pertains to
  1047. Irp - pointer to the IRP
  1048. Context - Context passed in by IoSetCompletionRoutine.
  1049. Return Value:
  1050. STATUS_MORE_PROCESSING_REQUIRED
  1051. --*/
  1052. {
  1053. DBG_PRINT (DBG_INFO,
  1054. "Entering AcpisimCompletionRoutine.\n");
  1055. KeSetEvent (Context, 0, FALSE);
  1056. DBG_PRINT (DBG_INFO,
  1057. "Exiting AcpisimCompletionRoutine.\n");
  1058. return STATUS_MORE_PROCESSING_REQUIRED;
  1059. }
  1060. NTSTATUS
  1061. AcpisimForwardIrpAndWait
  1062. (
  1063. IN PDEVICE_OBJECT DeviceObject,
  1064. IN PIRP Irp
  1065. )
  1066. /*++
  1067. Routine Description:
  1068. This forwards the IRP down the device stack, sets
  1069. a completion routine, and waits on the completion
  1070. event. Useful for doing IRP post-completion, based
  1071. on the result of the completion.
  1072. Arguments:
  1073. DeviceObject - pointer to the device object the IRP pertains to
  1074. Irp - pointer to the IRP
  1075. Return Value:
  1076. The status set in the IRP when the IRP was completed.
  1077. --*/
  1078. {
  1079. KEVENT context;
  1080. NTSTATUS status = STATUS_UNSUCCESSFUL;
  1081. PDEVICE_EXTENSION deviceextension = AcpisimGetDeviceExtension (DeviceObject);
  1082. DBG_PRINT (DBG_INFO,
  1083. "Entering AcpisimForwardIrpAndWait.\n");
  1084. KeInitializeEvent (&context, SynchronizationEvent, FALSE);
  1085. IoCopyCurrentIrpStackLocationToNext (Irp);
  1086. IoSetCompletionRoutine (Irp,
  1087. AcpisimCompletionRoutine,
  1088. &context,
  1089. TRUE,
  1090. TRUE,
  1091. TRUE);
  1092. status = IoCallDriver (deviceextension->NextDevice, Irp);
  1093. if (status == STATUS_PENDING) {
  1094. KeWaitForSingleObject (&context,
  1095. Executive,
  1096. KernelMode,
  1097. FALSE,
  1098. NULL);
  1099. status = Irp->IoStatus.Status;
  1100. }
  1101. DBG_PRINT (DBG_INFO,
  1102. "Exiting AcpisimForwardIrpAndWait.\n");
  1103. return status;
  1104. }
  1105. NTSTATUS
  1106. AcpisimIssuePowerDIrp
  1107. (
  1108. IN PDEVICE_OBJECT DeviceObject,
  1109. IN PIRP Irp,
  1110. IN PVOID Context
  1111. )
  1112. /*++
  1113. Routine Description:
  1114. This is the S-IRP completion routine. It examines the completed
  1115. IRP, and if there are no problems, asks the power manager to
  1116. send us the appropriate D-IRP.
  1117. Arguments:
  1118. DeviceObject - pointer to the device object the IRP pertains to
  1119. Irp - pointer to the IRP
  1120. Context - Context passed into IoSetCompletionRoutine
  1121. Return Value:
  1122. Status of requesting D-IRP operation.
  1123. --*/
  1124. {
  1125. NTSTATUS status = STATUS_UNSUCCESSFUL;
  1126. PDEVICE_EXTENSION deviceextension = AcpisimGetDeviceExtension (DeviceObject);
  1127. PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation (Irp);
  1128. POWER_STATE powerstate;
  1129. PPOWER_CONTEXT context = NULL;
  1130. DBG_PRINT (DBG_INFO,
  1131. "Entering AcpisimIssuePowerDIrp.\n");
  1132. powerstate.DeviceState = PowerDeviceUnspecified;
  1133. //
  1134. // Make sure this IRP wasn't failed by the PDO or Lower FFDO
  1135. //
  1136. if (!NT_SUCCESS (Irp->IoStatus.Status)) {
  1137. DBG_PRINT (DBG_INFO,
  1138. "AcpisimIssuePowerDIrp: Lower FFDO, BFDO, or PDO failed this IRP (%lx).\n",
  1139. status);
  1140. status = Irp->IoStatus.Status;
  1141. goto EndAcpisimIssuePowerDIrp;
  1142. }
  1143. if (NT_SUCCESS (Irp->IoStatus.Status)) {
  1144. //
  1145. // Ok, everybody is agreeing to this S state. Send ourselves
  1146. // the appropriate D IRP.
  1147. //
  1148. //
  1149. // Make sure this is an S Irp
  1150. //
  1151. ASSERT (irpsp->Parameters.Power.Type == SystemPowerState);
  1152. if (irpsp->Parameters.Power.Type != SystemPowerState) {
  1153. DBG_PRINT (DBG_ERROR,
  1154. "Didn't recieve an S Irp when we expected to, or somebody messed up the IRP. Fail it.\n");
  1155. status = STATUS_INVALID_DEVICE_REQUEST;
  1156. goto EndAcpisimIssuePowerDIrp;
  1157. }
  1158. ASSERT (irpsp->MinorFunction == IRP_MN_QUERY_POWER || irpsp->MinorFunction == IRP_MN_SET_POWER);
  1159. if (irpsp->MinorFunction != IRP_MN_QUERY_POWER && irpsp->MinorFunction != IRP_MN_SET_POWER) {
  1160. DBG_PRINT (DBG_ERROR,
  1161. "Irp isn't SET or QUERY. Not sure why this wasn't caught earlier (somebody probably messed it up).\nWe don't support any other type. Fail it.\n");
  1162. status = STATUS_INVALID_DEVICE_REQUEST;
  1163. goto EndAcpisimIssuePowerDIrp;
  1164. }
  1165. //
  1166. // Make sure the S IRP is valid
  1167. //
  1168. if (irpsp->Parameters.Power.State.SystemState >= PowerSystemMaximum) {
  1169. ASSERT (0);
  1170. DBG_PRINT (DBG_ERROR,
  1171. "Received an undefined S IRP, or somebody messed up the IRP. Fail it.\n");
  1172. status = STATUS_INVALID_DEVICE_REQUEST;
  1173. goto EndAcpisimIssuePowerDIrp;
  1174. }
  1175. //
  1176. // Use our power mapping table to convert S-->D state
  1177. //
  1178. powerstate.DeviceState = deviceextension->PowerMappings [irpsp->Parameters.Power.State.SystemState - 1];
  1179. DBG_PRINT (DBG_INFO,
  1180. "S%d --> D%d\n", irpsp->Parameters.Power.State.SystemState - 1, powerstate.DeviceState - 1);
  1181. //
  1182. // We need a context to pass a pointer to the S IRP to the D IRP handler
  1183. // and a pointer to the device object.
  1184. //
  1185. context = ExAllocatePoolWithTag (NonPagedPool,
  1186. sizeof (POWER_CONTEXT)+4,
  1187. POWER_CONTEXT_TAG);
  1188. if (!context) {
  1189. DBG_PRINT (DBG_ERROR,
  1190. "Unable to allocate memory for the context.\n");
  1191. status = STATUS_INSUFFICIENT_RESOURCES;
  1192. goto EndAcpisimIssuePowerDIrp;
  1193. }
  1194. context->SIrp = Irp;
  1195. context->Context = DeviceObject;
  1196. //
  1197. // Send the D Irp
  1198. //
  1199. status = PoRequestPowerIrp (deviceextension->Pdo,
  1200. irpsp->MinorFunction,
  1201. powerstate,
  1202. AcpisimCompleteSIrp,
  1203. context,
  1204. NULL);
  1205. ASSERT (NT_SUCCESS (status));
  1206. if (!NT_SUCCESS (status)) {
  1207. DBG_PRINT (DBG_ERROR,
  1208. "AcpisimIssuePowerDIrp: PoRequestPowerIrp failed (%lx).\n");
  1209. goto EndAcpisimIssuePowerDIrp;
  1210. }
  1211. }
  1212. status = STATUS_MORE_PROCESSING_REQUIRED;
  1213. EndAcpisimIssuePowerDIrp:
  1214. //
  1215. // We need to complete the request if something went wrong. Also note,
  1216. // it is not necessary to assume our state is S0/D0 again. The power
  1217. // manager will send us an S0 IRP.
  1218. //
  1219. if (!NT_SUCCESS (status) && status != STATUS_MORE_PROCESSING_REQUIRED) {
  1220. DBG_PRINT (DBG_ERROR,
  1221. "AcpisimIssuePowerDIrp: Something bad happened. Just complete the S Irp with an error.");
  1222. PoStartNextPowerIrp (Irp);
  1223. Irp->IoStatus.Status = status;
  1224. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  1225. IoReleaseRemoveLock (&deviceextension->RemoveLock, Irp);
  1226. AcpisimDecrementIrpCount (DeviceObject);
  1227. if (context) {
  1228. ExFreePool (context);
  1229. }
  1230. }
  1231. DBG_PRINT (DBG_INFO,
  1232. "Exiting AcpisimIssuePowerDIrp.\n");
  1233. return status;
  1234. }
  1235. NTSTATUS
  1236. AcpisimCompleteSIrp
  1237. (
  1238. IN PDEVICE_OBJECT DeviceObject,
  1239. IN UCHAR MinorFunction,
  1240. IN POWER_STATE PowerState,
  1241. IN PVOID Context,
  1242. IN PIO_STATUS_BLOCK IoStatus
  1243. )
  1244. /*++
  1245. Routine Description:
  1246. This is the S-Irp completion routine set by PoRequestPowerIrp.
  1247. Arguments:
  1248. DeviceObject - pointer to the FDO
  1249. MinorFunction - type of request
  1250. PowerState - type of IRP
  1251. Context - Context passed into PoRequestPowerIrp
  1252. IoStatus - IoStatus block of completed D Irp
  1253. Return Value:
  1254. STATUS_SUCCESS
  1255. --*/
  1256. {
  1257. PPOWER_CONTEXT context = (PPOWER_CONTEXT) Context;
  1258. PDEVICE_OBJECT deviceobject = context->Context;
  1259. PDEVICE_EXTENSION deviceextension = AcpisimGetDeviceExtension (deviceobject);
  1260. PIRP sirp = context->SIrp;
  1261. DBG_PRINT (DBG_INFO,
  1262. "Entering AcpisimCompleteSIrp.\n");
  1263. //
  1264. // Propagate the device power IRP's status in the system power IRP
  1265. //
  1266. sirp->IoStatus.Status = IoStatus->Status;
  1267. //
  1268. // Tell the power manager we are done with this IRP
  1269. //
  1270. PoStartNextPowerIrp (sirp);
  1271. IoCompleteRequest (sirp, IO_NO_INCREMENT);
  1272. IoReleaseRemoveLock (&deviceextension->RemoveLock, sirp);
  1273. ExFreePool (Context);
  1274. //
  1275. // Normally our dispatch routine decrements IRP counts,
  1276. // but since it was returned STATUS_PENDING, it wasn't
  1277. // decremented earlier
  1278. //
  1279. AcpisimDecrementIrpCount (deviceobject);
  1280. DBG_PRINT (DBG_INFO,
  1281. "Exiting AcpisimCompleteSIrp.\n");
  1282. return STATUS_SUCCESS;
  1283. }
  1284. NTSTATUS
  1285. AcpisimD0Completion
  1286. (
  1287. IN PDEVICE_OBJECT DeviceObject,
  1288. IN PIRP Irp,
  1289. IN PVOID Context
  1290. )
  1291. /*++
  1292. Routine Description:
  1293. This is the D0 Irp completion routine
  1294. Arguments:
  1295. DeviceObject - pointer to the FDO
  1296. MinorFunction - type of request
  1297. Context - Context passed into IoSetCompletionRoutine
  1298. Return Value:
  1299. Error status or STATUS_MORE_PROCESSING_REQUIRED
  1300. --*/
  1301. {
  1302. NTSTATUS status = STATUS_UNSUCCESSFUL;
  1303. PDEVICE_EXTENSION deviceextension = AcpisimGetDeviceExtension (DeviceObject);
  1304. PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation (Irp);
  1305. POWER_STATE powerstate;
  1306. DBG_PRINT (DBG_INFO,
  1307. "Entering AcpisimD0Completion.\n");
  1308. //
  1309. // Make sure this IRP wasn't failed by the PDO or Lower FFDO
  1310. //
  1311. if (!NT_SUCCESS (Irp->IoStatus.Status)) {
  1312. DBG_PRINT (DBG_INFO,
  1313. "AcpisimD0Completion: Lower FFDO, BFDO, or PDO failed this IRP (%lx).\n",
  1314. status);
  1315. status = Irp->IoStatus.Status;
  1316. goto EndAcpisimD0Completion;
  1317. }
  1318. //
  1319. // This is where we do actual D0 transition work. Since this
  1320. // is a virtual device, the only thing we do is change our
  1321. // internal state.
  1322. //
  1323. AcpisimUpdatePowerState (DeviceObject, POWER_STATE_WORKING);
  1324. AcpisimUpdateDevicePowerState (DeviceObject, irpsp->Parameters.Power.State.DeviceState);
  1325. powerstate.DeviceState = PowerDeviceD0;
  1326. PoSetPowerState (DeviceObject, DevicePowerState, powerstate);
  1327. status = STATUS_MORE_PROCESSING_REQUIRED;
  1328. EndAcpisimD0Completion:
  1329. PoStartNextPowerIrp (Irp);
  1330. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  1331. IoReleaseRemoveLock (&deviceextension->RemoveLock, Irp);
  1332. AcpisimDecrementIrpCount (DeviceObject);
  1333. DBG_PRINT (DBG_INFO,
  1334. "Exiting AcpisimD0Completion.\n");
  1335. return status;
  1336. }
  1337. VOID
  1338. AcpisimInitDevPowerStateTable
  1339. (
  1340. IN PDEVICE_OBJECT DeviceObject
  1341. )
  1342. /*++
  1343. Routine Description:
  1344. This routine fills out the power mapping structure with defaults.
  1345. We simply default to using D3 in any non-S0 state.
  1346. Arguments:
  1347. DeviceObject - pointer to the FDO
  1348. Return Value:
  1349. None
  1350. --*/
  1351. {
  1352. PDEVICE_EXTENSION deviceextension = AcpisimGetDeviceExtension (DeviceObject);
  1353. UCHAR count;
  1354. deviceextension->PowerMappings[0] = PowerDeviceD0;
  1355. for (count = 1; count < 5; count ++) {
  1356. deviceextension->PowerMappings[count] = PowerDeviceD3;
  1357. }
  1358. }
  1359. NTSTATUS AcpisimDispatchIoctl
  1360. (
  1361. IN PDEVICE_OBJECT DeviceObject,
  1362. IN PIRP Irp
  1363. )
  1364. /*++
  1365. Routine Description:
  1366. This is the handler for IOCTL requests. We just call the supplied
  1367. function to handle the IOCTL, or pass it on if the handler doesn't
  1368. handle it.
  1369. Arguments:
  1370. DeviceObject - pointer to the device object the IRP pertains to
  1371. Irp - pointer to the IRP
  1372. Return Value:
  1373. result of IRP processing
  1374. --*/
  1375. {
  1376. PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation (Irp);
  1377. NTSTATUS status = STATUS_UNSUCCESSFUL;
  1378. ULONG count = 0;
  1379. DBG_PRINT (DBG_INFO, "Entering AcpisimDispatchIoctl\n");
  1380. status = AcpisimHandleIoctl (DeviceObject, Irp);
  1381. if (status == STATUS_NOT_SUPPORTED) {
  1382. //
  1383. // IOCTL wasn't handled, pass it on...
  1384. //
  1385. IoSkipCurrentIrpStackLocation (Irp);
  1386. status = IoCallDriver (AcpisimLibGetNextDevice (DeviceObject), Irp);
  1387. } else {
  1388. //
  1389. // IOCTL was handled, complete it.
  1390. //
  1391. Irp->IoStatus.Status = status;
  1392. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  1393. }
  1394. DBG_PRINT (DBG_INFO, "Exiting AcpisimDispatchIoctl\n");
  1395. return status;
  1396. }
  1397. NTSTATUS
  1398. AcpisimDispatchSystemControl
  1399. (
  1400. IN PDEVICE_OBJECT DeviceObject,
  1401. IN PIRP Irp
  1402. )
  1403. /*++
  1404. Routine Description:
  1405. This is the handler for System Control requests. Since we currently
  1406. don't support any System Control calls, we are just going to pass
  1407. them on to the next driver.
  1408. Arguments:
  1409. DeviceObject - pointer to the device object the IRP pertains to
  1410. Irp - pointer to the IRP
  1411. Return Value:
  1412. result of IoCallDriver
  1413. --*/
  1414. {
  1415. NTSTATUS status = STATUS_UNSUCCESSFUL;
  1416. DBG_PRINT (DBG_INFO, "Entering AcpisimDispatchSystemControl\n");
  1417. IoSkipCurrentIrpStackLocation (Irp);
  1418. status = IoCallDriver (AcpisimLibGetNextDevice (DeviceObject), Irp);
  1419. DBG_PRINT (DBG_INFO, "Exiting AcpisimDispatchSystemControl\n");
  1420. return status;
  1421. }
  1422. NTSTATUS AcpisimCreateClose
  1423. (
  1424. IN PDEVICE_OBJECT DeviceObject,
  1425. IN PIRP Irp
  1426. )
  1427. /*++
  1428. Routine Description:
  1429. This is the handler for CreateFile and CloseHandle requests.
  1430. We do nothing except update our internal extension to track
  1431. the number of outstanding handles.
  1432. Arguments:
  1433. DeviceObject - pointer to the device object the IRP pertains to
  1434. Irp - pointer to the IRP
  1435. Return Value:
  1436. result of IRP processing
  1437. --*/
  1438. {
  1439. NTSTATUS status = STATUS_UNSUCCESSFUL;
  1440. PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation (Irp);
  1441. PDEVICE_EXTENSION deviceextension = AcpisimGetDeviceExtension (DeviceObject);
  1442. ASSERT (irpsp->MajorFunction == IRP_MJ_CREATE || irpsp->MajorFunction == IRP_MJ_CLOSE);
  1443. switch (irpsp->MajorFunction) {
  1444. case IRP_MJ_CREATE:
  1445. InterlockedIncrement (&deviceextension->HandleCount);
  1446. status = STATUS_SUCCESS;
  1447. break;
  1448. case IRP_MJ_CLOSE:
  1449. InterlockedDecrement (&deviceextension->HandleCount);
  1450. status = STATUS_SUCCESS;
  1451. break;
  1452. default:
  1453. DBG_PRINT (DBG_ERROR,
  1454. "AcpisimCreateClose - unexpected Irp type.\n");
  1455. status = STATUS_INVALID_DEVICE_REQUEST;
  1456. break;
  1457. }
  1458. Irp->IoStatus.Status = status;
  1459. IoCompleteRequest (Irp, 0);
  1460. return STATUS_SUCCESS;
  1461. }