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.

825 lines
28 KiB

  1. #include "precomp.h" // Precompiled header
  2. /****************************************************************************************
  3. * *
  4. * Module: SPX_POWER.C *
  5. * *
  6. * Creation: 15th October 1998 *
  7. * *
  8. * Author: Paul Smith *
  9. * *
  10. * Version: 1.0.0 *
  11. * *
  12. * Description: Handle all Power IRPS. *
  13. * *
  14. ****************************************************************************************/
  15. /* History...
  16. 1.0.0 27/09/98 PBS Creation.
  17. */
  18. #define FILE_ID SPX_POWR_C // File ID for Event Logging see SPX_DEFS.H for values.
  19. BOOLEAN BREAK_ON_POWER_UP = FALSE;
  20. // Prototypes
  21. NTSTATUS Spx_Card_FDO_DispatchPower(IN PDEVICE_OBJECT pFDO, IN PIRP pIrp);
  22. NTSTATUS Spx_CardSetSystemPowerState(IN PDEVICE_OBJECT pDevObject, IN PIRP pIrp);
  23. NTSTATUS Spx_CardSetDevicePowerState(IN PDEVICE_OBJECT pDevObject, IN PIRP pIrp);
  24. NTSTATUS Spx_CardSetPowerStateD0(IN PDEVICE_OBJECT pDevObject, IN PIRP pIrp);
  25. NTSTATUS Spx_CardSetPowerStateD3(IN PDEVICE_OBJECT pDevObject, IN PIRP pIrp);
  26. NTSTATUS Spx_Port_PDO_DispatchPower(IN PDEVICE_OBJECT pPDO, IN PIRP pIrp);
  27. NTSTATUS Spx_PortQuerySystemPowerState(IN PDEVICE_OBJECT pDevObject, IN PIRP pIrp);
  28. NTSTATUS Spx_PortSetSystemPowerState(IN PDEVICE_OBJECT pDevObject, IN PIRP pIrp);
  29. NTSTATUS Spx_PortSetDevicePowerState(IN PDEVICE_OBJECT pDevObject, IN PIRP pIrp);
  30. NTSTATUS Spx_PortSetPowerStateD0(IN PDEVICE_OBJECT pDevObject, IN PIRP pIrp);
  31. NTSTATUS Spx_PortSetPowerStateD3(IN PDEVICE_OBJECT pDevObject, IN PIRP pIrp);
  32. NTSTATUS Spx_PowerWaitForDriverBelow(IN PDEVICE_OBJECT pLowerDevObj, IN PIRP pIrp);
  33. // End of prototypes
  34. // Paging..
  35. #ifdef ALLOC_PRAGMA
  36. #pragma alloc_text(PAGE, Spx_DispatchPower)
  37. #pragma alloc_text(PAGE, Spx_Card_FDO_DispatchPower)
  38. #pragma alloc_text(PAGE, Spx_CardSetSystemPowerState)
  39. #pragma alloc_text(PAGE, Spx_CardSetDevicePowerState)
  40. #pragma alloc_text(PAGE, Spx_CardSetPowerStateD0)
  41. #pragma alloc_text(PAGE, Spx_CardSetPowerStateD3)
  42. #pragma alloc_text(PAGE, Spx_Port_PDO_DispatchPower)
  43. #pragma alloc_text(PAGE, Spx_PortQuerySystemPowerState)
  44. #pragma alloc_text(PAGE, Spx_PortSetSystemPowerState)
  45. #pragma alloc_text(PAGE, Spx_PortSetDevicePowerState)
  46. #pragma alloc_text(PAGE, Spx_PortSetPowerStateD0)
  47. #pragma alloc_text(PAGE, Spx_PortSetPowerStateD3)
  48. #endif // ALLOC_PRAGMA
  49. //////////////////////////////////////////////////////////////////////////////////////////
  50. //
  51. // Routine Description:
  52. // The power dispatch routine determine if the IRP is for a card or a port and
  53. // then call the correct dispatch routine.
  54. //
  55. // Arguments:
  56. // pDevObject - pointer to a device object.
  57. // pIrp - pointer to an I/O request packet.
  58. //
  59. // Return value:
  60. // NT status code.
  61. //
  62. //////////////////////////////////////////////////////////////////////////////////////////
  63. NTSTATUS
  64. Spx_DispatchPower(IN PDEVICE_OBJECT pDevObject, IN PIRP pIrp)
  65. {
  66. PCOMMON_OBJECT_DATA CommonData = (PCOMMON_OBJECT_DATA) pDevObject->DeviceExtension;
  67. NTSTATUS status = STATUS_SUCCESS;
  68. PAGED_CODE(); // Macro in checked build to assert if pagable code is run at or above dispatch IRQL
  69. if(CommonData->IsFDO)
  70. status = Spx_Card_FDO_DispatchPower(pDevObject, pIrp);
  71. else
  72. status = Spx_Port_PDO_DispatchPower(pDevObject, pIrp);
  73. return status;
  74. } // Spx_DispatchPower
  75. //////////////////////////////////////////////////////////////////////////////////////////
  76. //
  77. // Routine Description:
  78. // The power dispatch routine to handle power IRPs for card devices.
  79. //
  80. // Arguments:
  81. // pFDO - pointer to a device object.
  82. // pIrp - pointer to an I/O request packet.
  83. //
  84. // Return value:
  85. // NT status code.
  86. //
  87. //////////////////////////////////////////////////////////////////////////////////////////
  88. NTSTATUS
  89. Spx_Card_FDO_DispatchPower(IN PDEVICE_OBJECT pFDO, IN PIRP pIrp)
  90. {
  91. PCARD_DEVICE_EXTENSION pCard = pFDO->DeviceExtension;
  92. NTSTATUS status = STATUS_SUCCESS;
  93. PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  94. PAGED_CODE(); // Macro in checked build to assert if pagable code is run at or above dispatch IRQL
  95. switch (pIrpStack->MinorFunction)
  96. {
  97. case IRP_MN_SET_POWER: // Driver MUST never fail this IRP.
  98. {
  99. switch(pIrpStack->Parameters.Power.Type)
  100. {
  101. case SystemPowerState:
  102. SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Got IRP_MN_SET_POWER Irp - Type SystemPowerState for Card %d.\n",
  103. PRODUCT_NAME, pCard->CardNumber));
  104. return Spx_CardSetSystemPowerState(pFDO, pIrp);
  105. case DevicePowerState:
  106. SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Got IRP_MN_SET_POWER Irp - Type DevicePowerState for Card %d.\n",
  107. PRODUCT_NAME, pCard->CardNumber));
  108. return Spx_CardSetDevicePowerState(pFDO, pIrp);
  109. default:
  110. SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Got IRP_MN_SET_POWER - Type 0x%02X Irp for Card %d.\n",
  111. PRODUCT_NAME, pIrpStack->Parameters.Power.Type, pCard->CardNumber));
  112. status = STATUS_SUCCESS;
  113. pIrp->IoStatus.Status = status;
  114. break;
  115. }
  116. break;
  117. }
  118. case IRP_MN_QUERY_POWER:
  119. {
  120. switch(pIrpStack->Parameters.Power.Type)
  121. {
  122. case SystemPowerState:
  123. SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Got IRP_MN_QUERY_POWER Irp - Type SystemPowerState for Card %d.\n",
  124. PRODUCT_NAME, pCard->CardNumber));
  125. status = STATUS_SUCCESS;
  126. pIrp->IoStatus.Status = status;
  127. break;
  128. case DevicePowerState:
  129. SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Got IRP_MN_QUERY_POWER Irp - Type DevicePowerState for Card %d.\n",
  130. PRODUCT_NAME, pCard->CardNumber));
  131. status = STATUS_SUCCESS;
  132. pIrp->IoStatus.Status = status;
  133. break;
  134. default:
  135. SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Got IRP_MN_QUERY_POWER - Type 0x%02X Irp for Card %d.\n",
  136. PRODUCT_NAME, pIrpStack->Parameters.Power.Type, pCard->CardNumber));
  137. status = STATUS_SUCCESS;
  138. pIrp->IoStatus.Status = status;
  139. break;
  140. }
  141. break;
  142. }
  143. case IRP_MN_WAIT_WAKE:
  144. SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Got IRP_MN_WAIT_WAKE Irp for Card %d.\n",
  145. PRODUCT_NAME, pCard->CardNumber));
  146. status = STATUS_NOT_SUPPORTED;
  147. pIrp->IoStatus.Status = status;
  148. break;
  149. case IRP_MN_POWER_SEQUENCE:
  150. SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Got IRP_MN_POWER_SEQUENCE Irp for Card %d.\n",
  151. PRODUCT_NAME, pCard->CardNumber));
  152. status = STATUS_NOT_IMPLEMENTED;
  153. pIrp->IoStatus.Status = status;
  154. break;
  155. default:
  156. SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Got an UNKNOWN POWER Irp for Card %d.\n",
  157. PRODUCT_NAME, pCard->CardNumber));
  158. status = STATUS_NOT_SUPPORTED;
  159. break;
  160. }
  161. PoStartNextPowerIrp(pIrp);
  162. IoSkipCurrentIrpStackLocation(pIrp);
  163. PoCallDriver(pCard->LowerDeviceObject, pIrp);
  164. return status;
  165. } // Spx_Card_FDO_DispatchPower
  166. //////////////////////////////////////////////////////////////////////////////////////////
  167. // Spx_CardSetSystemPowerState
  168. //////////////////////////////////////////////////////////////////////////////////////////
  169. NTSTATUS
  170. Spx_CardSetSystemPowerState(IN PDEVICE_OBJECT pDevObject, IN PIRP pIrp)
  171. {
  172. PCARD_DEVICE_EXTENSION pCard = pDevObject->DeviceExtension;
  173. NTSTATUS status = STATUS_SUCCESS;
  174. PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  175. POWER_STATE PowerState;
  176. PAGED_CODE(); // Macro in checked build to assert if pagable code is run at or above dispatch IRQL
  177. SpxDbgMsg(SPX_TRACE_CALLS, ("%s: Entering Spx_CardSetSystemPowerState for Card %d.\n",
  178. PRODUCT_NAME, pCard->CardNumber));
  179. switch (pIrpStack->Parameters.Power.State.SystemState)
  180. {
  181. case PowerSystemUnspecified:
  182. PowerState.DeviceState = PowerDeviceUnspecified;
  183. PoRequestPowerIrp(pCard->PDO, IRP_MN_SET_POWER, PowerState, NULL, NULL, NULL);
  184. break;
  185. case PowerSystemWorking:
  186. PowerState.DeviceState = PowerDeviceD0;
  187. PoRequestPowerIrp(pCard->PDO, IRP_MN_SET_POWER, PowerState, NULL, NULL, NULL);
  188. break;
  189. case PowerSystemSleeping1:
  190. case PowerSystemSleeping2:
  191. case PowerSystemSleeping3:
  192. case PowerSystemHibernate:
  193. case PowerSystemShutdown:
  194. case PowerSystemMaximum:
  195. PowerState.DeviceState = PowerDeviceD3;
  196. PoRequestPowerIrp(pCard->PDO, IRP_MN_SET_POWER, PowerState, NULL, NULL, NULL);
  197. break;
  198. default:
  199. break;
  200. }
  201. pIrp->IoStatus.Status = STATUS_SUCCESS;
  202. PoStartNextPowerIrp(pIrp);
  203. IoSkipCurrentIrpStackLocation(pIrp);
  204. PoCallDriver(pCard->LowerDeviceObject, pIrp);
  205. return status;
  206. } // Spx_CardSetSystemPowerState
  207. //////////////////////////////////////////////////////////////////////////////////////////
  208. // Spx_CardSetDevicePowerState
  209. //////////////////////////////////////////////////////////////////////////////////////////
  210. NTSTATUS
  211. Spx_CardSetDevicePowerState(IN PDEVICE_OBJECT pDevObject, IN PIRP pIrp)
  212. {
  213. PCARD_DEVICE_EXTENSION pCard = pDevObject->DeviceExtension;
  214. NTSTATUS status = STATUS_SUCCESS;
  215. PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  216. PAGED_CODE(); // Macro in checked build to assert if pagable code is run at or above dispatch IRQL
  217. SpxDbgMsg(SPX_TRACE_CALLS, ("%s: Entering Spx_CardSetDevicePowerState for Card %d.\n",
  218. PRODUCT_NAME, pCard->CardNumber));
  219. switch(pIrpStack->Parameters.Power.State.DeviceState)
  220. {
  221. case PowerDeviceD0:
  222. SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: System requests Card %d goes into power state D0.\n",
  223. PRODUCT_NAME, pCard->CardNumber));
  224. if(pCard->DeviceState == pIrpStack->Parameters.Power.State.DeviceState)
  225. SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Card %d is already in power state D0.\n",
  226. PRODUCT_NAME, pCard->CardNumber));
  227. else
  228. return Spx_CardSetPowerStateD0(pDevObject, pIrp); // Switch ON
  229. break;
  230. case PowerDeviceD1:
  231. SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: System requests Card %d goes into power state D1.\n",
  232. PRODUCT_NAME, pCard->CardNumber));
  233. if(pCard->DeviceState >= pIrpStack->Parameters.Power.State.DeviceState)
  234. SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Card %d is already in power state D1 or lower.\n",
  235. PRODUCT_NAME, pCard->CardNumber));
  236. else
  237. return Spx_CardSetPowerStateD3(pDevObject, pIrp); // Switch OFF
  238. break;
  239. case PowerDeviceD2:
  240. SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: System requests Card %d goes into power state D2.\n",
  241. PRODUCT_NAME, pCard->CardNumber));
  242. if(pCard->DeviceState >= pIrpStack->Parameters.Power.State.DeviceState)
  243. SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Card %d is already in power state D2 or lower.\n",
  244. PRODUCT_NAME, pCard->CardNumber));
  245. else
  246. return Spx_CardSetPowerStateD3(pDevObject, pIrp); // Switch OFF
  247. break;
  248. case PowerDeviceD3:
  249. SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: System requests Card %d goes into power state D3.\n",
  250. PRODUCT_NAME, pCard->CardNumber));
  251. if(pCard->DeviceState == pIrpStack->Parameters.Power.State.DeviceState)
  252. SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Card %d is already in power state D3.\n",
  253. PRODUCT_NAME, pCard->CardNumber));
  254. else
  255. return Spx_CardSetPowerStateD3(pDevObject, pIrp); // Switch OFF
  256. break;
  257. default:
  258. break;
  259. }
  260. pIrp->IoStatus.Status = STATUS_SUCCESS;
  261. PoStartNextPowerIrp(pIrp);
  262. IoSkipCurrentIrpStackLocation(pIrp);
  263. PoCallDriver(pCard->LowerDeviceObject, pIrp);
  264. return status;
  265. } // Spx_CardSetDevicePowerState
  266. //////////////////////////////////////////////////////////////////////////////////////////
  267. // Spx_SetPowerStateD0 - Sets power state D0 for Card - ON
  268. //////////////////////////////////////////////////////////////////////////////////////////
  269. NTSTATUS
  270. Spx_CardSetPowerStateD0(IN PDEVICE_OBJECT pDevObject, IN PIRP pIrp)
  271. {
  272. PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  273. PCARD_DEVICE_EXTENSION pCard = pDevObject->DeviceExtension;
  274. NTSTATUS status = STATUS_SUCCESS;
  275. PAGED_CODE(); // Macro in checked build to assert if pagable code is run at or above dispatch IRQL
  276. SpxDbgMsg(SPX_TRACE_CALLS, ("%s: Entering Spx_CardSetPowerStateD0 for Card %d.\n",
  277. PRODUCT_NAME, pCard->CardNumber));
  278. status = Spx_PowerWaitForDriverBelow(pCard->LowerDeviceObject, pIrp);
  279. #if DBG
  280. if(BREAK_ON_POWER_UP)
  281. {
  282. BREAK_ON_POWER_UP = FALSE;
  283. KdPrint(("%s: Breaking debugger whilst powering up Card %d to debug after a hibernate\n", PRODUCT_NAME, pCard->CardNumber));
  284. DbgBreakPoint();
  285. }
  286. #endif
  287. SetPnpPowerFlags(pCard, PPF_POWERED);
  288. if(SPX_SUCCESS(pIrp->IoStatus.Status = XXX_CardPowerUp(pCard))) // RESTORE HARDWARE STATE HERE & START CARD
  289. {
  290. // Inform Power Manager the of the new power state.
  291. PoSetPowerState(pDevObject, pIrpStack->Parameters.Power.Type, pIrpStack->Parameters.Power.State);
  292. pCard->DeviceState = PowerDeviceD0; // Store new power state.
  293. }
  294. PoStartNextPowerIrp(pIrp); // Ready for next power IRP.
  295. IoCompleteRequest(pIrp, IO_NO_INCREMENT); // Complete current IRP.
  296. return status;
  297. } // Spx_SetPowerStateD0
  298. //////////////////////////////////////////////////////////////////////////////////////////
  299. // Spx_SetPowerStateD3 - Sets power state D3 for Card - OFF
  300. //////////////////////////////////////////////////////////////////////////////////////////
  301. NTSTATUS
  302. Spx_CardSetPowerStateD3(IN PDEVICE_OBJECT pDevObject, IN PIRP pIrp)
  303. {
  304. PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  305. PCARD_DEVICE_EXTENSION pCard = pDevObject->DeviceExtension;
  306. NTSTATUS status = STATUS_SUCCESS;
  307. PAGED_CODE(); // Macro in checked build to assert if pagable code is run at or above dispatch IRQL
  308. SpxDbgMsg(SPX_TRACE_CALLS, ("%s: Entering Spx_CardSetPowerStateD3 for Card %d.\n",
  309. PRODUCT_NAME, pCard->CardNumber));
  310. ClearPnpPowerFlags(pCard, PPF_POWERED);
  311. if(SPX_SUCCESS(pIrp->IoStatus.Status = XXX_CardPowerDown(pCard))) // SAVE HARDWARE STATE HERE & STOP CARD
  312. {
  313. // Inform Power Manager the of the new power state.
  314. PoSetPowerState(pDevObject, pIrpStack->Parameters.Power.Type, pIrpStack->Parameters.Power.State);
  315. pCard->DeviceState = PowerDeviceD3; // Store new power state.
  316. }
  317. PoStartNextPowerIrp(pIrp); // Ready for next power IRP.
  318. IoSkipCurrentIrpStackLocation(pIrp);
  319. PoCallDriver(pCard->LowerDeviceObject, pIrp); // Pass IRP on down.
  320. return status;
  321. } // Spx_SetPowerStateD3
  322. //////////////////////////////////////////////////////////////////////////////////////////
  323. //
  324. // Routine Description:
  325. // The power dispatch routine to handle power IRPs for port devices.
  326. //
  327. // Arguments:
  328. // pPDO - pointer to a device object.
  329. // pIrp - pointer to an I/O request packet.
  330. //
  331. // Return value:
  332. // NT status code.
  333. //
  334. //////////////////////////////////////////////////////////////////////////////////////////
  335. NTSTATUS
  336. Spx_Port_PDO_DispatchPower(IN PDEVICE_OBJECT pPDO, IN PIRP pIrp)
  337. {
  338. PPORT_DEVICE_EXTENSION pPort = pPDO->DeviceExtension;
  339. NTSTATUS status = STATUS_SUCCESS;
  340. PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  341. POWER_STATE PowerState;
  342. PAGED_CODE(); // Macro in checked build to assert if pagable code is run at or above dispatch IRQL
  343. switch (pIrpStack->MinorFunction)
  344. {
  345. case IRP_MN_SET_POWER:
  346. {
  347. switch(pIrpStack->Parameters.Power.Type)
  348. {
  349. case SystemPowerState:
  350. SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Got IRP_MN_SET_POWER Irp - Type SystemPowerState for Port %d.\n",
  351. PRODUCT_NAME, pPort->PortNumber));
  352. return Spx_PortSetSystemPowerState(pPDO, pIrp);
  353. case DevicePowerState:
  354. SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Got IRP_MN_SET_POWER Irp - Type DevicePowerState for Port %d.\n",
  355. PRODUCT_NAME, pPort->PortNumber));
  356. return Spx_PortSetDevicePowerState(pPDO, pIrp);
  357. default:
  358. SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Got IRP_MN_SET_POWER - Type 0x%02X Irp for Port %d.\n",
  359. PRODUCT_NAME, pIrpStack->Parameters.Power.Type, pPort->PortNumber));
  360. status = STATUS_SUCCESS;
  361. pIrp->IoStatus.Status = status;
  362. break;
  363. }
  364. break;
  365. }
  366. case IRP_MN_QUERY_POWER:
  367. {
  368. switch(pIrpStack->Parameters.Power.Type)
  369. {
  370. case SystemPowerState:
  371. SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Got IRP_MN_QUERY_POWER Irp - Type SystemPowerState for Port %d.\n",
  372. PRODUCT_NAME, pPort->PortNumber));
  373. return Spx_PortQuerySystemPowerState(pPDO, pIrp);
  374. case DevicePowerState:
  375. SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Got IRP_MN_QUERY_POWER Irp - Type DevicePowerState for Port %d.\n",
  376. PRODUCT_NAME, pPort->PortNumber));
  377. switch(pIrpStack->Parameters.Power.State.DeviceState)
  378. {
  379. case PowerDeviceD0:
  380. SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: System is asking if Port %d can go to power state D0.\n",
  381. PRODUCT_NAME, pPort->PortNumber));
  382. status = STATUS_SUCCESS;
  383. break;
  384. case PowerDeviceD1:
  385. case PowerDeviceD2:
  386. case PowerDeviceD3:
  387. SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: System is asking if Port %d can go to low power state D1, D2 or D3.\n",
  388. PRODUCT_NAME, pPort->PortNumber));
  389. status = XXX_PortQueryPowerDown(pPort);
  390. break;
  391. default:
  392. status = STATUS_SUCCESS;
  393. break;
  394. }
  395. break;
  396. default:
  397. SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Got IRP_MN_QUERY_POWER - Type 0x%02X Irp for Port %d.\n",
  398. PRODUCT_NAME, pIrpStack->Parameters.Power.Type, pPort->PortNumber));
  399. break;
  400. }
  401. pIrp->IoStatus.Status = status;
  402. break;
  403. }
  404. case IRP_MN_WAIT_WAKE:
  405. SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Got IRP_MN_WAIT_WAKE Irp for Port %d.\n",
  406. PRODUCT_NAME, pPort->PortNumber));
  407. status = STATUS_NOT_SUPPORTED;
  408. pIrp->IoStatus.Status = status;
  409. break;
  410. case IRP_MN_POWER_SEQUENCE:
  411. SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Got IRP_MN_POWER_SEQUENCE Irp for Port %d.\n",
  412. PRODUCT_NAME, pPort->PortNumber));
  413. status = STATUS_NOT_IMPLEMENTED;
  414. pIrp->IoStatus.Status = status;
  415. break;
  416. default:
  417. SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Got an UNKNOWN POWER Irp for Port %d.\n",
  418. PRODUCT_NAME, pPort->PortNumber));
  419. status = STATUS_NOT_SUPPORTED;
  420. break;
  421. }
  422. PoStartNextPowerIrp(pIrp);
  423. IoCompleteRequest(pIrp, IO_NO_INCREMENT); // Complete current IRP.
  424. return status;
  425. } // Spx_Port_PDO_DispatchPower
  426. //////////////////////////////////////////////////////////////////////////////////////////
  427. // Spx_PortSetSystemPowerState
  428. //////////////////////////////////////////////////////////////////////////////////////////
  429. NTSTATUS
  430. Spx_PortSetSystemPowerState(IN PDEVICE_OBJECT pDevObject, IN PIRP pIrp)
  431. {
  432. PPORT_DEVICE_EXTENSION pPort = pDevObject->DeviceExtension;
  433. NTSTATUS status = STATUS_SUCCESS;
  434. PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  435. POWER_STATE PowerState;
  436. PAGED_CODE(); // Macro in checked build to assert if pagable code is run at or above dispatch IRQL
  437. SpxDbgMsg(SPX_TRACE_CALLS, ("%s: Entering Spx_PortSetSystemPowerState for Port %d.\n",
  438. PRODUCT_NAME, pPort->PortNumber));
  439. switch (pIrpStack->Parameters.Power.State.SystemState)
  440. {
  441. case PowerSystemUnspecified:
  442. PowerState.DeviceState = PowerDeviceUnspecified;
  443. PoRequestPowerIrp(pDevObject, IRP_MN_SET_POWER, PowerState, NULL, NULL, NULL);
  444. break;
  445. case PowerSystemWorking:
  446. PowerState.DeviceState = PowerDeviceD0;
  447. PoRequestPowerIrp(pDevObject, IRP_MN_SET_POWER, PowerState, NULL, NULL, NULL);
  448. break;
  449. case PowerSystemSleeping1:
  450. case PowerSystemSleeping2:
  451. case PowerSystemSleeping3:
  452. case PowerSystemHibernate:
  453. case PowerSystemShutdown:
  454. case PowerSystemMaximum:
  455. PowerState.DeviceState = PowerDeviceD3;
  456. PoRequestPowerIrp(pDevObject, IRP_MN_SET_POWER, PowerState, NULL, NULL, NULL);
  457. break;
  458. default:
  459. break;
  460. }
  461. pIrp->IoStatus.Status = STATUS_SUCCESS;
  462. PoStartNextPowerIrp(pIrp);
  463. IoCompleteRequest(pIrp, IO_NO_INCREMENT); // Complete current IRP.
  464. return status;
  465. } // Spx_PortSetSystemPowerState
  466. //////////////////////////////////////////////////////////////////////////////////////////
  467. // Spx_PortQuerySystemPowerState
  468. //////////////////////////////////////////////////////////////////////////////////////////
  469. NTSTATUS
  470. Spx_PortQuerySystemPowerState(IN PDEVICE_OBJECT pDevObject, IN PIRP pIrp)
  471. {
  472. PPORT_DEVICE_EXTENSION pPort = pDevObject->DeviceExtension;
  473. NTSTATUS status = STATUS_SUCCESS;
  474. PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  475. POWER_STATE PowerState;
  476. PAGED_CODE(); // Macro in checked build to assert if pagable code is run at or above dispatch IRQL
  477. SpxDbgMsg(SPX_TRACE_CALLS, ("%s: Entering Spx_PortQuerySystemPowerState for Port %d.\n",
  478. PRODUCT_NAME, pPort->PortNumber));
  479. switch (pIrpStack->Parameters.Power.State.SystemState)
  480. {
  481. case PowerSystemUnspecified:
  482. PowerState.DeviceState = PowerDeviceUnspecified;
  483. PoRequestPowerIrp(pDevObject, IRP_MN_QUERY_POWER, PowerState, NULL, NULL, NULL);
  484. break;
  485. case PowerSystemWorking:
  486. PowerState.DeviceState = PowerDeviceD0;
  487. PoRequestPowerIrp(pDevObject, IRP_MN_QUERY_POWER, PowerState, NULL, NULL, NULL);
  488. break;
  489. case PowerSystemSleeping1:
  490. case PowerSystemSleeping2:
  491. case PowerSystemSleeping3:
  492. case PowerSystemHibernate:
  493. case PowerSystemShutdown:
  494. case PowerSystemMaximum:
  495. PowerState.DeviceState = PowerDeviceD3;
  496. PoRequestPowerIrp(pDevObject, IRP_MN_QUERY_POWER, PowerState, NULL, NULL, NULL);
  497. break;
  498. default:
  499. break;
  500. }
  501. pIrp->IoStatus.Status = STATUS_SUCCESS;
  502. PoStartNextPowerIrp(pIrp);
  503. IoCompleteRequest(pIrp, IO_NO_INCREMENT); // Complete current IRP.
  504. return status;
  505. } // Spx_PortQuerySystemPowerState
  506. //////////////////////////////////////////////////////////////////////////////////////////
  507. // Spx_PortSetDevicePowerState
  508. //////////////////////////////////////////////////////////////////////////////////////////
  509. NTSTATUS
  510. Spx_PortSetDevicePowerState(IN PDEVICE_OBJECT pDevObject, IN PIRP pIrp)
  511. {
  512. PPORT_DEVICE_EXTENSION pPort = pDevObject->DeviceExtension;
  513. NTSTATUS status = STATUS_SUCCESS;
  514. PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  515. PAGED_CODE(); // Macro in checked build to assert if pagable code is run at or above dispatch IRQL
  516. SpxDbgMsg(SPX_TRACE_CALLS, ("%s: Entering Spx_PortSetDevicePowerState for Port %d.\n",
  517. PRODUCT_NAME, pPort->PortNumber));
  518. switch(pIrpStack->Parameters.Power.State.DeviceState)
  519. {
  520. case PowerDeviceD0:
  521. SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: System requests Port %d goes into power state D0.\n",
  522. PRODUCT_NAME, pPort->PortNumber));
  523. if(pPort->DeviceState == pIrpStack->Parameters.Power.State.DeviceState)
  524. SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Port %d is already in power state D0.\n",
  525. PRODUCT_NAME, pPort->PortNumber));
  526. else
  527. return Spx_PortSetPowerStateD0(pDevObject, pIrp); // Switch ON
  528. break;
  529. case PowerDeviceD1:
  530. SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: System requests Port %d goes into power state D1.\n",
  531. PRODUCT_NAME, pPort->PortNumber));
  532. if(pPort->DeviceState >= pIrpStack->Parameters.Power.State.DeviceState)
  533. SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Port %d is already in power state D1 or lower.\n",
  534. PRODUCT_NAME, pPort->PortNumber));
  535. else
  536. return Spx_PortSetPowerStateD3(pDevObject, pIrp); // Switch OFF
  537. break;
  538. case PowerDeviceD2:
  539. SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: System requests Port %d goes into power state D2.\n",
  540. PRODUCT_NAME, pPort->PortNumber));
  541. if(pPort->DeviceState >= pIrpStack->Parameters.Power.State.DeviceState)
  542. SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Port %d is already in power state D2 or lower.\n",
  543. PRODUCT_NAME, pPort->PortNumber));
  544. else
  545. return Spx_PortSetPowerStateD3(pDevObject, pIrp); // Switch OFF
  546. break;
  547. case PowerDeviceD3:
  548. SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: System requests Port %d goes into power state D3.\n",
  549. PRODUCT_NAME, pPort->PortNumber));
  550. if(pPort->DeviceState == pIrpStack->Parameters.Power.State.DeviceState)
  551. SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Port %d is already in power state D3.\n",
  552. PRODUCT_NAME, pPort->PortNumber));
  553. else
  554. return Spx_PortSetPowerStateD3(pDevObject, pIrp); // Switch OFF
  555. break;
  556. default:
  557. break;
  558. }
  559. pIrp->IoStatus.Status = STATUS_SUCCESS;
  560. PoStartNextPowerIrp(pIrp);
  561. IoCompleteRequest(pIrp, IO_NO_INCREMENT); // Complete current IRP.
  562. return status;
  563. } // Spx_PortSetDevicePowerState
  564. //////////////////////////////////////////////////////////////////////////////////////////
  565. // Spx_PortSetPowerStateD0 - Sets power state D0 for Port - ON
  566. //////////////////////////////////////////////////////////////////////////////////////////
  567. NTSTATUS
  568. Spx_PortSetPowerStateD0(IN PDEVICE_OBJECT pDevObject, IN PIRP pIrp)
  569. {
  570. PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  571. PPORT_DEVICE_EXTENSION pPort = pDevObject->DeviceExtension;
  572. NTSTATUS status = STATUS_SUCCESS;
  573. PAGED_CODE(); // Macro in checked build to assert if pagable code is run at or above dispatch IRQL
  574. SpxDbgMsg(SPX_TRACE_CALLS, ("%s: Entering Spx_PortSetPowerStateD0 for Port %d.\n",
  575. PRODUCT_NAME, pPort->PortNumber));
  576. SetPnpPowerFlags(pPort, PPF_POWERED);
  577. if(SPX_SUCCESS(pIrp->IoStatus.Status = XXX_PortPowerUp(pPort))) // RESTORE HARDWARE STATE HERE & START PORT
  578. {
  579. // Inform Power Manager the of the new power state.
  580. PoSetPowerState(pDevObject, pIrpStack->Parameters.Power.Type, pIrpStack->Parameters.Power.State);
  581. pPort->DeviceState = PowerDeviceD0; // Store new power state.
  582. Spx_UnstallIrps(pPort); // Restart any queued IRPs (from a previous start)
  583. }
  584. PoStartNextPowerIrp(pIrp); // Ready for next power IRP.
  585. IoCompleteRequest(pIrp, IO_NO_INCREMENT); // Complete current IRP.
  586. return status;
  587. } // Spx_PortSetPowerStateD0
  588. //////////////////////////////////////////////////////////////////////////////////////////
  589. // Spx_PortSetPowerStateD3 - Sets power state D3 for Port - OFF
  590. //////////////////////////////////////////////////////////////////////////////////////////
  591. NTSTATUS
  592. Spx_PortSetPowerStateD3(IN PDEVICE_OBJECT pDevObject, IN PIRP pIrp)
  593. {
  594. PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  595. PPORT_DEVICE_EXTENSION pPort = pDevObject->DeviceExtension;
  596. NTSTATUS status = STATUS_SUCCESS;
  597. PAGED_CODE(); // Macro in checked build to assert if pagable code is run at or above dispatch IRQL
  598. SpxDbgMsg(SPX_TRACE_CALLS, ("%s: Entering Spx_PortSetPowerStateD3 for Port %d.\n",
  599. PRODUCT_NAME, pPort->PortNumber));
  600. ClearPnpPowerFlags(pPort, PPF_POWERED);
  601. if(SPX_SUCCESS(pIrp->IoStatus.Status = XXX_PortPowerDown(pPort))) // SAVE HARDWARE STATE HERE & STOP PORT
  602. {
  603. // Inform Power Manager the of the new power state.
  604. PoSetPowerState(pDevObject, pIrpStack->Parameters.Power.Type, pIrpStack->Parameters.Power.State);
  605. pPort->DeviceState = PowerDeviceD3; // Store new power state.
  606. }
  607. PoStartNextPowerIrp(pIrp); // Ready for next power IRP.
  608. IoCompleteRequest(pIrp, IO_NO_INCREMENT); // Complete current IRP.
  609. return status;
  610. } // Spx_PortSetPowerStateD3
  611. //////////////////////////////////////////////////////////////////////////////////////////
  612. // Spx_PowerWaitForDriverBelow - Waits for lower driver.
  613. //////////////////////////////////////////////////////////////////////////////////////////
  614. NTSTATUS
  615. Spx_PowerWaitForDriverBelow(IN PDEVICE_OBJECT pLowerDevObj, IN PIRP pIrp)
  616. {
  617. KEVENT EventWaitLowerDrivers;
  618. NTSTATUS status;
  619. pIrp->IoStatus.Status = STATUS_SUCCESS;
  620. IoCopyCurrentIrpStackLocationToNext(pIrp); // Copy parameters to the stack below
  621. KeInitializeEvent(&EventWaitLowerDrivers, SynchronizationEvent, FALSE); // Initialise event if need to wait
  622. IoSetCompletionRoutine(pIrp, Spx_DispatchPnpPowerComplete, &EventWaitLowerDrivers, TRUE, TRUE, TRUE);
  623. if((status = PoCallDriver(pLowerDevObj, pIrp)) == STATUS_PENDING)
  624. {
  625. KeWaitForSingleObject(&EventWaitLowerDrivers, Executive, KernelMode, FALSE, NULL);
  626. status = pIrp->IoStatus.Status;
  627. }
  628. return(status);
  629. } // Spx_PowerWaitForDriverBelow