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.

908 lines
22 KiB

  1. /*++
  2. Module Name:
  3. power.c
  4. Abstract:
  5. This module contains the code that handles the power IRPs for the serial
  6. driver.
  7. Environment:
  8. Kernel mode
  9. Revision History :
  10. --*/
  11. #include "precomp.h"
  12. #ifdef ALLOC_PRAGMA
  13. //#pragma alloc_text(PAGEMX0, MoxaGotoPowerState)
  14. //#pragma alloc_text(PAGEMX0, MoxaPowerDispatch)
  15. //#pragma alloc_text(PAGEMX0, MoxaSetPowerD0)
  16. //#pragma alloc_text(PAGEMX0, MoxaSetPowerD3)
  17. //#pragma alloc_text(PAGEMX0, MoxaSaveDeviceState)
  18. //#pragma alloc_text(PAGEMX0, MoxaRestoreDeviceState)
  19. //#pragma alloc_text(PAGEMX0, MoxaSendWaitWake)
  20. #endif // ALLOC_PRAGMA
  21. NTSTATUS
  22. MoxaSystemPowerCompletion(IN PDEVICE_OBJECT PDevObj, UCHAR MinorFunction,
  23. IN POWER_STATE PowerState, IN PVOID Context,
  24. PIO_STATUS_BLOCK IoStatus)
  25. /*++
  26. Routine Description:
  27. This routine is the completion routine for PoRequestPowerIrp calls
  28. in this module.
  29. Arguments:
  30. PDevObj - Pointer to the device object the irp is completing for
  31. MinorFunction - IRP_MN_XXXX value requested
  32. PowerState - Power state request was made of
  33. Context - Event to set or NULL if no setting required
  34. IoStatus - Status block from request
  35. Return Value:
  36. VOID
  37. --*/
  38. {
  39. if (Context != NULL) {
  40. KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, 0);
  41. }
  42. return STATUS_SUCCESS;
  43. }
  44. VOID
  45. MoxaSaveDeviceState(IN PMOXA_DEVICE_EXTENSION PDevExt)
  46. /*++
  47. Routine Description:
  48. This routine saves the device state of the UART
  49. Arguments:
  50. PDevExt - Pointer to the device extension for the devobj to save the state
  51. for.
  52. Return Value:
  53. VOID
  54. --*/
  55. {
  56. PMOXA_DEVICE_STATE pDevState = &PDevExt->DeviceState;
  57. KIRQL oldIrql;
  58. // PAGED_CODE();
  59. MoxaKdPrint (MX_DBG_TRACE, ("Entering MoxaSaveDeviceState\n"));
  60. MoxaKillAllReadsOrWrites(
  61. PDevExt->DeviceObject,
  62. &PDevExt->WriteQueue,
  63. &PDevExt->CurrentWriteIrp
  64. );
  65. MoxaKillAllReadsOrWrites(
  66. PDevExt->DeviceObject,
  67. &PDevExt->ReadQueue,
  68. &PDevExt->CurrentReadIrp
  69. );
  70. //
  71. // Clean out the Tx/Rx queue
  72. //
  73. KeAcquireSpinLock(
  74. &PDevExt->ControlLock,
  75. &oldIrql
  76. );
  77. PDevExt->TotalCharsQueued = 0;
  78. MoxaFunc( // flush input/output queue
  79. PDevExt->PortOfs,
  80. FC_FlushQueue,
  81. 2
  82. );
  83. KeReleaseSpinLock(
  84. &PDevExt->ControlLock,
  85. oldIrql
  86. );
  87. //
  88. // Read necessary registers direct
  89. //
  90. pDevState->HostState = *(PUSHORT)(PDevExt->PortOfs + HostStat);
  91. MoxaKdPrint (MX_DBG_TRACE, ("Leaving MoxaSaveDeviceState\n"));
  92. }
  93. VOID
  94. MoxaRestoreDeviceState(IN PMOXA_DEVICE_EXTENSION PDevExt)
  95. /*++
  96. Routine Description:
  97. This routine restores the device state of the UART
  98. Arguments:
  99. PDevExt - Pointer to the device extension for the devobj to restore the
  100. state for.
  101. Return Value:
  102. VOID
  103. --*/
  104. {
  105. PMOXA_DEVICE_STATE pDevState = &PDevExt->DeviceState;
  106. SHORT divisor;
  107. USHORT max;
  108. // PAGED_CODE();
  109. MoxaKdPrint (MX_DBG_TRACE, ("Enter MoxaRestoreDeviceState\n"));
  110. MoxaKdPrint (MX_DBG_TRACE, ("------ PDevExt: %x\n", PDevExt));
  111. if (PDevExt->DeviceState.Reopen == TRUE) {
  112. USHORT arg,i;
  113. //MoxaFunc1(PDevExt->PortOfs, FC_ChannelReset, Magic_code);
  114. //
  115. // Restore Host Stat
  116. //
  117. *(PUSHORT)(PDevExt->PortOfs + HostStat) = pDevState->HostState;
  118. MoxaFunc1(PDevExt->PortOfs, FC_SetDataMode, PDevExt->DataMode);
  119. MoxaGetDivisorFromBaud(
  120. PDevExt->ClockType,
  121. PDevExt->CurrentBaud,
  122. &divisor
  123. );
  124. MoxaFunc1(PDevExt->PortOfs, FC_SetBaud, divisor);
  125. *(PUSHORT)(PDevExt->PortOfs+ Tx_trigger) = (USHORT)MoxaTxLowWater;
  126. MoxaFunc1(PDevExt->PortOfs, FC_SetTxFIFOCnt, PDevExt->TxFifoAmount);
  127. MoxaFunc1(PDevExt->PortOfs, FC_SetRxFIFOTrig,PDevExt->RxFifoTrigger);
  128. MoxaFunc1(PDevExt->PortOfs, FC_SetLineIrq,Magic_code);
  129. MoxaFunc1(PDevExt->PortOfs, FC_SetXoffLimit, (USHORT)PDevExt->HandFlow.XoffLimit);
  130. MoxaFunc1(PDevExt->PortOfs, FC_SetFlowRepl, (USHORT)PDevExt->HandFlow.FlowReplace);
  131. arg = (MoxaFlagBit[PDevExt->PortNo] & 3);
  132. MoxaFunc1(
  133. PDevExt->PortOfs,
  134. FC_LineControl,
  135. arg
  136. );
  137. for (i=0; i<sizeof(SERIAL_CHARS); i++)
  138. (PDevExt->PortOfs + FuncArg)[i] = ((PUCHAR)&PDevExt->SpecialChars)[i];
  139. *(PDevExt->PortOfs + FuncCode) = FC_SetChars;
  140. MoxaWaitFinish1(PDevExt->PortOfs);
  141. PDevExt->ModemStatus = *(PUSHORT)(PDevExt->PortOfs + FlagStat) >> 4;
  142. if (PDevExt->HandFlow.ControlHandShake & SERIAL_CTS_HANDSHAKE)
  143. arg = CTS_FlowCtl;
  144. if (PDevExt->HandFlow.FlowReplace & SERIAL_RTS_HANDSHAKE)
  145. arg |= RTS_FlowCtl;
  146. if (PDevExt->HandFlow.FlowReplace & SERIAL_AUTO_TRANSMIT)
  147. arg |= Tx_FlowCtl;
  148. if (PDevExt->HandFlow.FlowReplace & SERIAL_AUTO_RECEIVE)
  149. arg |= Rx_FlowCtl;
  150. MoxaFunc1(PDevExt->PortOfs,FC_SetFlowCtl, arg);
  151. if (MoxaFlagBit[PDevExt->PortNo] & 4)
  152. MoxaFunc1(PDevExt->PortOfs,FC_SetXoffState,Magic_code);
  153. MoxaFunc1(PDevExt->PortOfs, FC_EnableCH, Magic_code);
  154. if (PDevExt->NumberNeededForRead)
  155. MoxaKdPrint (MX_DBG_TRACE, ("NumberNeededForRead=%d\n",PDevExt->NumberNeededForRead));
  156. PDevExt->DeviceState.Reopen = FALSE;
  157. }
  158. MoxaKdPrint (MX_DBG_TRACE, ("Exit restore\n"));
  159. }
  160. NTSTATUS
  161. MoxaPowerDispatch(IN PDEVICE_OBJECT PDevObj, IN PIRP PIrp)
  162. /*++
  163. Routine Description:
  164. This is a dispatch routine for the IRPs that come to the driver with the
  165. IRP_MJ_POWER major code (power IRPs).
  166. Arguments:
  167. PDevObj - Pointer to the device object for this device
  168. PIrp - Pointer to the IRP for the current request
  169. Return Value:
  170. The function value is the final status of the call
  171. --*/
  172. {
  173. PMOXA_DEVICE_EXTENSION pDevExt = PDevObj->DeviceExtension;
  174. PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(PIrp);
  175. NTSTATUS status;
  176. PDEVICE_OBJECT pLowerDevObj = pDevExt->LowerDeviceObject;
  177. PDEVICE_OBJECT pPdo = pDevExt->Pdo;
  178. BOOLEAN acceptingIRPs;
  179. // PAGED_CODE();
  180. if (pDevExt->ControlDevice) { // Control Device
  181. PoStartNextPowerIrp(PIrp);
  182. status = STATUS_CANCELLED;
  183. PIrp->IoStatus.Information = 0L;
  184. PIrp->IoStatus.Status = status;
  185. IoCompleteRequest(
  186. PIrp,
  187. 0
  188. );
  189. return status;
  190. }
  191. if ((status = MoxaIRPPrologue(PIrp, pDevExt)) != STATUS_SUCCESS) {
  192. PoStartNextPowerIrp(PIrp);
  193. MoxaCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
  194. return status;
  195. }
  196. switch (pIrpStack->MinorFunction) {
  197. case IRP_MN_WAIT_WAKE:
  198. MoxaKdPrint (MX_DBG_TRACE, ("Got IRP_MN_WAIT_WAKE Irp\n"));
  199. break;
  200. case IRP_MN_POWER_SEQUENCE:
  201. MoxaKdPrint (MX_DBG_TRACE, ("Got IRP_MN_POWER_SEQUENCE Irp\n"));
  202. break;
  203. case IRP_MN_SET_POWER:
  204. MoxaKdPrint (MX_DBG_TRACE,("Got IRP_MN_SET_POWER Irp\n"));
  205. //
  206. // Perform different ops if it was system or device
  207. //
  208. switch (pIrpStack->Parameters.Power.Type) {
  209. case SystemPowerState: {
  210. POWER_STATE powerState;
  211. //
  212. // They asked for a system power state change
  213. //
  214. MoxaKdPrint (MX_DBG_TRACE, ("------: SystemPowerState\n"));
  215. //
  216. // We will only service this if we are policy owner -- we
  217. // don't need to lock on this value since we only service
  218. // one power request at a time.
  219. //
  220. if (pDevExt->OwnsPowerPolicy != TRUE) {
  221. status = STATUS_SUCCESS;
  222. goto PowerExit;
  223. }
  224. switch (pIrpStack->Parameters.Power.State.SystemState) {
  225. case PowerSystemUnspecified:
  226. powerState.DeviceState = PowerDeviceUnspecified;
  227. break;
  228. case PowerSystemWorking:
  229. powerState.DeviceState = PowerDeviceD0;
  230. break;
  231. case PowerSystemSleeping1:
  232. case PowerSystemSleeping2:
  233. case PowerSystemSleeping3:
  234. case PowerSystemHibernate:
  235. case PowerSystemShutdown:
  236. case PowerSystemMaximum:
  237. powerState.DeviceState = PowerDeviceD3;
  238. break;
  239. default:
  240. status = STATUS_SUCCESS;
  241. goto PowerExit;
  242. break;
  243. }
  244. PoSetPowerState(PDevObj, pIrpStack->Parameters.Power.Type,
  245. pIrpStack->Parameters.Power.State);
  246. //
  247. // Send IRP to change device state
  248. //
  249. PoRequestPowerIrp(pPdo, IRP_MN_SET_POWER, powerState, NULL, NULL,
  250. NULL);
  251. goto PowerExit;
  252. }
  253. case DevicePowerState:
  254. MoxaKdPrint (MX_DBG_TRACE, ("------: DevicePowerState\n"));
  255. break;
  256. default:
  257. MoxaKdPrint (MX_DBG_TRACE, ("------: UNKNOWN PowerState\n"));
  258. goto PowerExit;
  259. }
  260. //
  261. // If we are already in the requested state, just pass the IRP down
  262. //
  263. if (pDevExt->PowerState
  264. == pIrpStack->Parameters.Power.State.DeviceState) {
  265. MoxaKdPrint (MX_DBG_TRACE, ("Already in requested power state\n")
  266. );
  267. break;
  268. }
  269. switch (pIrpStack->Parameters.Power.State.DeviceState) {
  270. case PowerDeviceD0:
  271. MoxaKdPrint (MX_DBG_TRACE,("Going to power state D0\n"));
  272. return MoxaSetPowerD0(PDevObj, PIrp);
  273. case PowerDeviceD1:
  274. case PowerDeviceD2:
  275. case PowerDeviceD3:
  276. MoxaKdPrint (MX_DBG_TRACE,("Going to power state D3\n"));
  277. return MoxaSetPowerD3(PDevObj, PIrp);
  278. default:
  279. break;
  280. }
  281. break;
  282. case IRP_MN_QUERY_POWER:
  283. MoxaKdPrint (MX_DBG_TRACE,("Got IRP_MN_QUERY_POWER Irp\n"));
  284. //
  285. // Check if we have a wait-wake pending and if so,
  286. // ensure we don't power down too far.
  287. //
  288. if (pDevExt->PendingWakeIrp != NULL) {
  289. if (pIrpStack->Parameters.Power.Type == SystemPowerState
  290. && pIrpStack->Parameters.Power.State.SystemState
  291. > pDevExt->SystemWake) {
  292. status = PIrp->IoStatus.Status = STATUS_INVALID_DEVICE_STATE;
  293. PoStartNextPowerIrp(PIrp);
  294. MoxaCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
  295. return status;
  296. }
  297. }
  298. //
  299. // If no wait-wake, always successful
  300. //
  301. PIrp->IoStatus.Status = STATUS_SUCCESS;
  302. PoStartNextPowerIrp(PIrp);
  303. IoSkipCurrentIrpStackLocation(PIrp);
  304. return MoxaPoCallDriver(pDevExt, pLowerDevObj, PIrp);
  305. } // switch (pIrpStack->MinorFunction)
  306. PowerExit:;
  307. PoStartNextPowerIrp(PIrp);
  308. //
  309. // Pass to the lower driver
  310. //
  311. IoSkipCurrentIrpStackLocation(PIrp);
  312. status = MoxaPoCallDriver(pDevExt, pLowerDevObj, PIrp);
  313. return status;
  314. }
  315. NTSTATUS
  316. MoxaSetPowerD0(IN PDEVICE_OBJECT PDevObj, IN PIRP PIrp)
  317. /*++
  318. Routine Description:
  319. This routine Decides if we need to pass the power Irp down the stack
  320. or not. It then either sets up a completion handler to finish the
  321. initialization or calls the completion handler directly.
  322. Arguments:
  323. PDevObj - Pointer to the devobj we are changing power state on
  324. PIrp - Pointer to the IRP for the current request
  325. Return Value:
  326. Return status of either PoCallDriver of the call to the initialization
  327. routine.
  328. --*/
  329. {
  330. PMOXA_DEVICE_EXTENSION pDevExt = PDevObj->DeviceExtension;
  331. PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(PIrp);
  332. NTSTATUS status;
  333. ULONG boardReady = 0;
  334. KEVENT event;
  335. IO_STATUS_BLOCK IoStatusBlock;
  336. // PAGED_CODE();
  337. MoxaKdPrint (MX_DBG_TRACE, ("In MoxaSetPowerD0\n"));
  338. MoxaKdPrint (MX_DBG_TRACE, ("SetPowerD0 has IRP %x\n", PIrp));
  339. // ASSERT(pDevExt->LowerDeviceObject);
  340. //
  341. // Set up completion to init device when it is on
  342. //
  343. KeClearEvent(&pDevExt->PowerD0Event);
  344. IoCopyCurrentIrpStackLocationToNext(PIrp);
  345. IoSetCompletionRoutine(PIrp, MoxaSyncCompletion, &pDevExt->PowerD0Event,
  346. TRUE, TRUE, TRUE);
  347. MoxaKdPrint (MX_DBG_TRACE, ("Calling next driver\n"));
  348. status = PoCallDriver(pDevExt->LowerDeviceObject, PIrp);
  349. if (status == STATUS_PENDING) {
  350. MoxaKdPrint (MX_DBG_TRACE, ("Waiting for next driver\n"));
  351. KeWaitForSingleObject (&pDevExt->PowerD0Event, Executive, KernelMode,
  352. FALSE, NULL);
  353. } else {
  354. if (!NT_SUCCESS(status)) {
  355. PIrp->IoStatus.Status = status;
  356. PoStartNextPowerIrp(PIrp);
  357. MoxaCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
  358. return status;
  359. }
  360. }
  361. if (!NT_SUCCESS(PIrp->IoStatus.Status)) {
  362. PoStartNextPowerIrp(PIrp);
  363. MoxaCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
  364. return PIrp->IoStatus.Status;
  365. }
  366. KeInitializeEvent(&event, NotificationEvent, FALSE);
  367. MoxaKdPrint(MX_DBG_TRACE,("Get board ready ...\n"));
  368. status = MoxaIoSyncIoctlEx(IOCTL_MOXA_INTERNAL_BOARD_READY, TRUE,
  369. pDevExt->LowerDeviceObject, &event, &IoStatusBlock,
  370. NULL, 0, &boardReady,
  371. sizeof(boardReady));
  372. MoxaKdPrint(MX_DBG_TRACE,("status=%x,boardReady=%x\n",status,boardReady));
  373. if (NT_SUCCESS(status) && boardReady) {
  374. //
  375. // Restore the device
  376. //
  377. //
  378. // Theoretically we could change states in the middle of processing
  379. // the restore which would result in a bad PKINTERRUPT being used
  380. // in MoxaRestoreDeviceState().
  381. //
  382. if (pDevExt->PNPState == SERIAL_PNP_STARTED) {
  383. MoxaRestoreDeviceState(pDevExt);
  384. }
  385. pDevExt->PowerState = PowerDeviceD0;
  386. MoxaGlobalData->BoardReady[pDevExt->BoardNo] = TRUE;
  387. }
  388. else
  389. MoxaGlobalData->BoardReady[pDevExt->BoardNo] = FALSE;
  390. //
  391. // Now that we are powered up, call PoSetPowerState
  392. //
  393. PoSetPowerState(PDevObj, pIrpStack->Parameters.Power.Type,
  394. pIrpStack->Parameters.Power.State);
  395. PoStartNextPowerIrp(PIrp);
  396. MoxaCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
  397. MoxaKdPrint (MX_DBG_TRACE,("Leaving MoxaSetPowerD0\n"));
  398. return STATUS_SUCCESS;
  399. }
  400. NTSTATUS
  401. MoxaGotoPowerState(IN PDEVICE_OBJECT PDevObj,
  402. IN PMOXA_DEVICE_EXTENSION PDevExt,
  403. IN DEVICE_POWER_STATE DevPowerState)
  404. /*++
  405. Routine Description:
  406. This routine causes the driver to request the stack go to a particular
  407. power state.
  408. Arguments:
  409. PDevObj - Pointer to the device object for this device
  410. PDevExt - Pointer to the device extension we are working from
  411. DevPowerState - the power state we wish to go to
  412. Return Value:
  413. The function value is the final status of the call
  414. --*/
  415. {
  416. KEVENT gotoPowEvent;
  417. NTSTATUS status;
  418. POWER_STATE powerState;
  419. // PAGED_CODE();
  420. MoxaKdPrint (MX_DBG_TRACE,("In MoxaGotoPowerState\n"));
  421. powerState.DeviceState = DevPowerState;
  422. KeInitializeEvent(&gotoPowEvent, SynchronizationEvent, FALSE);
  423. status = PoRequestPowerIrp(PDevObj, IRP_MN_SET_POWER, powerState,
  424. MoxaSystemPowerCompletion, &gotoPowEvent,
  425. NULL);
  426. if (status == STATUS_PENDING) {
  427. KeWaitForSingleObject(&gotoPowEvent, Executive, KernelMode, FALSE, NULL);
  428. status = STATUS_SUCCESS;
  429. }
  430. #if DBG
  431. if (!NT_SUCCESS(status)) {
  432. MoxaKdPrint (MX_DBG_TRACE,("MoxaGotoPowerState FAILED\n"));
  433. }
  434. #endif
  435. MoxaKdPrint (MX_DBG_TRACE,("Leaving MoxaGotoPowerState\n"));
  436. return status;
  437. }
  438. NTSTATUS
  439. MoxaSetPowerD3(IN PDEVICE_OBJECT PDevObj, IN PIRP PIrp)
  440. /*++
  441. Routine Description:
  442. This routine handles the SET_POWER minor function.
  443. Arguments:
  444. PDevObj - Pointer to the device object for this device
  445. PIrp - Pointer to the IRP for the current request
  446. Return Value:
  447. The function value is the final status of the call
  448. --*/
  449. {
  450. NTSTATUS status = STATUS_SUCCESS;
  451. PMOXA_DEVICE_EXTENSION pDevExt = PDevObj->DeviceExtension;
  452. PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(PIrp);
  453. // PAGED_CODE();
  454. MoxaKdPrint (MX_DBG_TRACE,("In MoxaSetPowerD3\n"));
  455. //
  456. // Before we power down, call PoSetPowerState
  457. //
  458. PoSetPowerState(PDevObj, pIrpStack->Parameters.Power.Type,
  459. pIrpStack->Parameters.Power.State);
  460. pDevExt->PowerState = PowerDeviceD3;
  461. //
  462. // If the device is not closed, disable interrupts and allow the fifo's
  463. // to flush.
  464. //
  465. if (pDevExt->DeviceIsOpened == TRUE) {
  466. LARGE_INTEGER charTime;
  467. pDevExt->DeviceState.Reopen = TRUE;
  468. //
  469. // Save the device state
  470. //
  471. MoxaSaveDeviceState(pDevExt);
  472. MoxaFunc1(pDevExt->PortOfs, FC_DisableCH, Magic_code);
  473. MoxaKdPrint (MX_DBG_TRACE,("Port Disabled\n"));
  474. }
  475. //
  476. // If the device is not open, we don't need to save the state;
  477. // we can just reset the device on power-up
  478. //
  479. PIrp->IoStatus.Status = STATUS_SUCCESS;
  480. //
  481. // For what we are doing, we don't need a completion routine
  482. // since we don't race on the power requests.
  483. //
  484. PIrp->IoStatus.Status = STATUS_SUCCESS;
  485. PoStartNextPowerIrp(PIrp);
  486. IoSkipCurrentIrpStackLocation(PIrp);
  487. return MoxaPoCallDriver(pDevExt, pDevExt->LowerDeviceObject, PIrp);
  488. }
  489. NTSTATUS
  490. MoxaSendWaitWake(PMOXA_DEVICE_EXTENSION PDevExt)
  491. /*++
  492. Routine Description:
  493. This routine causes a waitwake IRP to be sent
  494. Arguments:
  495. PDevExt - Pointer to the device extension for this device
  496. Return Value:
  497. STATUS_INVALID_DEVICE_STATE if one is already pending, else result
  498. of call to PoRequestPowerIrp.
  499. --*/
  500. {
  501. NTSTATUS status;
  502. PIRP pIrp;
  503. POWER_STATE powerState;
  504. // PAGED_CODE();
  505. //
  506. // Make sure one isn't pending already -- serial will only handle one at
  507. // a time.
  508. //
  509. if (PDevExt->PendingWakeIrp != NULL) {
  510. return STATUS_INVALID_DEVICE_STATE;
  511. }
  512. //
  513. // Make sure we are capable of waking the machine
  514. //
  515. if (PDevExt->SystemWake <= PowerSystemWorking) {
  516. return STATUS_INVALID_DEVICE_STATE;
  517. }
  518. //
  519. // Send IRP to request wait wake and add a pending irp flag
  520. //
  521. //
  522. InterlockedIncrement(&PDevExt->PendingIRPCnt);
  523. powerState.SystemState = PDevExt->SystemWake;
  524. status = PoRequestPowerIrp(PDevExt->Pdo, IRP_MN_WAIT_WAKE,
  525. powerState, MoxaWakeCompletion, PDevExt, &pIrp);
  526. if (status == STATUS_PENDING) {
  527. status = STATUS_SUCCESS;
  528. PDevExt->PendingWakeIrp = pIrp;
  529. } else if (!NT_SUCCESS(status)) {
  530. MoxaIRPEpilogue(PDevExt);
  531. }
  532. return status;
  533. }
  534. NTSTATUS
  535. MoxaWakeCompletion(IN PDEVICE_OBJECT PDevObj, IN UCHAR MinorFunction,
  536. IN POWER_STATE PowerState, IN PVOID Context,
  537. IN PIO_STATUS_BLOCK IoStatus)
  538. /*++
  539. Routine Description:
  540. This routine handles completion of the waitwake IRP.
  541. Arguments:
  542. PDevObj - Pointer to the device object for this device
  543. MinorFunction - Minor function previously supplied to PoRequestPowerIrp
  544. PowerState - PowerState previously supplied to PoRequestPowerIrp
  545. Context - a pointer to the device extension
  546. IoStatus - current/final status of the waitwake IRP
  547. Return Value:
  548. The function value is the final status of attempting to process the
  549. waitwake.
  550. --*/
  551. {
  552. NTSTATUS status;
  553. PMOXA_DEVICE_EXTENSION pDevExt = (PMOXA_DEVICE_EXTENSION)Context;
  554. POWER_STATE powerState;
  555. status = IoStatus->Status;
  556. if (NT_SUCCESS(status)) {
  557. NTSTATUS tmpStatus;
  558. PIRP pIrp;
  559. PKEVENT pEvent;
  560. //
  561. // A wakeup has occurred -- powerup our stack
  562. //
  563. powerState.DeviceState = PowerDeviceD0;
  564. pEvent = ExAllocatePool(NonPagedPool, sizeof(KEVENT));
  565. if (pEvent == NULL) {
  566. status = STATUS_INSUFFICIENT_RESOURCES;
  567. goto ErrorExitWakeCompletion;
  568. }
  569. KeInitializeEvent(pEvent, SynchronizationEvent, FALSE);
  570. tmpStatus = PoRequestPowerIrp(pDevExt->Pdo, IRP_MN_SET_POWER, powerState,
  571. MoxaSystemPowerCompletion, pEvent,
  572. NULL);
  573. if (tmpStatus == STATUS_PENDING) {
  574. KeWaitForSingleObject(pEvent, Executive, KernelMode, FALSE, NULL);
  575. tmpStatus = STATUS_SUCCESS;
  576. }
  577. ExFreePool(pEvent);
  578. if (!NT_SUCCESS(tmpStatus)) {
  579. status = tmpStatus;
  580. goto ErrorExitWakeCompletion;
  581. }
  582. //
  583. // Send another WaitWake Irp
  584. //
  585. powerState.SystemState = pDevExt->SystemWake;
  586. tmpStatus = PoRequestPowerIrp(pDevExt->Pdo, IRP_MN_WAIT_WAKE,
  587. powerState, MoxaWakeCompletion,
  588. pDevExt, &pIrp);
  589. if (tmpStatus == STATUS_PENDING) {
  590. pDevExt->PendingWakeIrp = pIrp;
  591. goto ExitWakeCompletion;
  592. }
  593. status = tmpStatus;
  594. }
  595. ErrorExitWakeCompletion:;
  596. pDevExt->PendingWakeIrp = NULL;
  597. MoxaIRPEpilogue(pDevExt);
  598. ExitWakeCompletion:;
  599. return status;
  600. }