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.

694 lines
19 KiB

  1. /*--------------------------------------------------------------------------
  2. *
  3. * Copyright (C) Cyclades Corporation, 2000-2001.
  4. * All rights reserved.
  5. *
  6. * Cyclades-Z Enumerator Driver
  7. *
  8. * This file: power.c
  9. *
  10. * Description: This module contains contains the power calls
  11. * for the cyclades-Z bus driver.
  12. *
  13. * Notes: This code supports Windows 2000 and Windows XP,
  14. * x86 and ia64 processors.
  15. *
  16. * Complies with Cyclades SW Coding Standard rev 1.3.
  17. *
  18. *--------------------------------------------------------------------------
  19. */
  20. /*-------------------------------------------------------------------------
  21. *
  22. * Change History
  23. *
  24. *--------------------------------------------------------------------------
  25. * Initial implementation based on Microsoft sample code.
  26. *
  27. *--------------------------------------------------------------------------
  28. */
  29. #include "pch.h"
  30. #ifdef ALLOC_PRAGMA
  31. //#pragma alloc_text (PAGE, Cycladz_Power)
  32. //#pragma alloc_text (PAGE, Cycladz_FDO_Power)
  33. //#pragma alloc_text (PAGE, Cycladz_PDO_Power)
  34. #endif
  35. typedef struct _POWER_COMPLETION_CONTEXT {
  36. PDEVICE_OBJECT DeviceObject;
  37. PIRP SIrp;
  38. } POWER_COMPLETION_CONTEXT, *PPOWER_COMPLETION_CONTEXT;
  39. VOID
  40. OnPowerRequestComplete(
  41. PDEVICE_OBJECT DeviceObject,
  42. UCHAR MinorFunction,
  43. POWER_STATE state,
  44. POWER_COMPLETION_CONTEXT* PowerContext,
  45. PIO_STATUS_BLOCK IoStatus
  46. )
  47. /*++
  48. Routine Description:
  49. Completion routine for D-IRP.
  50. Arguments:
  51. Return Value:
  52. NT status code
  53. --*/
  54. {
  55. PFDO_DEVICE_DATA fdoData = (PFDO_DEVICE_DATA) PowerContext->DeviceObject->DeviceExtension;
  56. PIRP sIrp = PowerContext->SIrp;
  57. UNREFERENCED_PARAMETER (DeviceObject);
  58. UNREFERENCED_PARAMETER (MinorFunction);
  59. UNREFERENCED_PARAMETER (state);
  60. Cycladz_KdPrint(fdoData,SER_DBG_POWER_TRACE, (">OnPowerRequestComplete\n"));
  61. //
  62. // Here we copy the D-IRP status into the S-IRP
  63. //
  64. sIrp->IoStatus.Status = IoStatus->Status;
  65. //
  66. // Release the IRP
  67. //
  68. PoStartNextPowerIrp(sIrp);
  69. IoCompleteRequest(sIrp, IO_NO_INCREMENT);
  70. //
  71. // Cleanup
  72. //
  73. ExFreePool(PowerContext);
  74. Cycladz_DecIoCount(fdoData);
  75. Cycladz_KdPrint(fdoData,SER_DBG_POWER_TRACE, ("<OnPowerRequestComplete\n"));
  76. }
  77. NTSTATUS
  78. Cycladz_FDOSystemPowerComplete (
  79. IN PDEVICE_OBJECT DeviceObject,
  80. IN PIRP Irp,
  81. IN PVOID Context
  82. )
  83. /*++
  84. --*/
  85. {
  86. POWER_COMPLETION_CONTEXT* powerContext;
  87. POWER_STATE powerState;
  88. POWER_STATE_TYPE powerType;
  89. PIO_STACK_LOCATION stack;
  90. PFDO_DEVICE_DATA data;
  91. NTSTATUS status = Irp->IoStatus.Status;
  92. UNREFERENCED_PARAMETER (Context);
  93. data = (PFDO_DEVICE_DATA) DeviceObject->DeviceExtension;
  94. Cycladz_KdPrint(data,SER_DBG_POWER_TRACE, (">SystemPowerComplete\n"));
  95. if (!NT_SUCCESS(status)) {
  96. PoStartNextPowerIrp(Irp);
  97. Cycladz_DecIoCount (data);
  98. Cycladz_KdPrint(data,SER_DBG_POWER_TRACE, ("<SystemPowerComplete1\n"));
  99. return STATUS_SUCCESS;
  100. }
  101. stack = IoGetCurrentIrpStackLocation (Irp);
  102. powerState = stack->Parameters.Power.State;
  103. switch (stack->Parameters.Power.State.SystemState) {
  104. case PowerSystemUnspecified:
  105. powerState.DeviceState = PowerDeviceUnspecified;
  106. break;
  107. case PowerSystemWorking:
  108. powerState.DeviceState = PowerDeviceD0;
  109. break;
  110. case PowerSystemSleeping1:
  111. case PowerSystemSleeping2:
  112. case PowerSystemSleeping3:
  113. case PowerSystemHibernate:
  114. case PowerSystemShutdown:
  115. case PowerSystemMaximum:
  116. powerState.DeviceState = PowerDeviceD3;
  117. break;
  118. default:
  119. powerState.DeviceState = PowerDeviceD3;
  120. }
  121. //
  122. // Send IRP to change device state
  123. //
  124. powerContext = (POWER_COMPLETION_CONTEXT*)
  125. ExAllocatePool(NonPagedPool, sizeof(POWER_COMPLETION_CONTEXT));
  126. if (!powerContext) {
  127. status = STATUS_INSUFFICIENT_RESOURCES;
  128. } else {
  129. powerContext->DeviceObject = DeviceObject;
  130. powerContext->SIrp = Irp;
  131. status = PoRequestPowerIrp(data->Self, IRP_MN_SET_POWER, powerState, OnPowerRequestComplete,
  132. powerContext, NULL);
  133. }
  134. if (!NT_SUCCESS(status)) {
  135. Cycladz_KdPrint(data,SER_DBG_POWER_TRACE, ("PoRequestPowerIrp %x\n",status));
  136. if (powerContext) {
  137. ExFreePool(powerContext);
  138. }
  139. PoStartNextPowerIrp(Irp);
  140. Irp->IoStatus.Status = status;
  141. //IoCompleteRequest(Irp, IO_NO_INCREMENT); Toaster has this line.
  142. Cycladz_DecIoCount(data);
  143. Cycladz_KdPrint(data,SER_DBG_POWER_TRACE, ("<2SystemPowerComplete\n"));
  144. return status;
  145. }
  146. Cycladz_KdPrint(data,SER_DBG_POWER_TRACE, ("<3SystemPowerComplete\n"));
  147. return STATUS_MORE_PROCESSING_REQUIRED;
  148. }
  149. VOID
  150. Cycladz_PowerOnWorkItem(
  151. IN PDEVICE_OBJECT DeviceObject,
  152. IN PVOID Context
  153. )
  154. /*++
  155. Routine Description:
  156. This routine starts the Z hardware.
  157. Arguments:
  158. Return Value:
  159. NT status code
  160. --*/
  161. {
  162. PIRP Irp;
  163. PFDO_DEVICE_DATA fdoData;
  164. PWORKER_THREAD_CONTEXT context = (PWORKER_THREAD_CONTEXT)Context;
  165. fdoData = (PFDO_DEVICE_DATA) DeviceObject->DeviceExtension;
  166. Cycladz_KdPrint(fdoData,SER_DBG_CYCLADES, (">Cycladz_PowerOnWorkItem Irp %x\n",context->Irp));
  167. Irp = context->Irp;
  168. Cycladz_DoesBoardExist(fdoData);
  169. PoSetPowerState (DeviceObject, context->PowerType, context->PowerState);
  170. PoStartNextPowerIrp (Irp);
  171. IoCompleteRequest (context->Irp, IO_NO_INCREMENT);
  172. //
  173. // Cleanup before exiting from the worker thread.
  174. //
  175. IoFreeWorkItem(context->WorkItem);
  176. ExFreePool((PVOID)context);
  177. Cycladz_KdPrint(fdoData,SER_DBG_CYCLADES, ("<Cycladz_PowerOnWorkItem\n"));
  178. Cycladz_DecIoCount (fdoData);
  179. }
  180. NTSTATUS
  181. Cycladz_FDOPowerComplete (
  182. IN PDEVICE_OBJECT DeviceObject,
  183. IN PIRP Irp,
  184. IN PVOID Context
  185. )
  186. /*++
  187. --*/
  188. {
  189. PIO_WORKITEM item;
  190. PWORKER_THREAD_CONTEXT context;
  191. POWER_STATE powerState;
  192. POWER_STATE_TYPE powerType;
  193. PIO_STACK_LOCATION stack;
  194. PFDO_DEVICE_DATA data;
  195. //NTSTATUS status = STATUS_SUCCESS; //Removed in build 2072
  196. UNREFERENCED_PARAMETER (Context);
  197. if (Irp->PendingReturned) {
  198. IoMarkIrpPending(Irp);
  199. }
  200. data = (PFDO_DEVICE_DATA) DeviceObject->DeviceExtension;
  201. stack = IoGetCurrentIrpStackLocation (Irp);
  202. powerType = stack->Parameters.Power.Type;
  203. powerState = stack->Parameters.Power.State;
  204. Cycladz_KdPrint(data,SER_DBG_CYCLADES, ("In Cycladz_FDOPowerComplete Irp %x\n",Irp));
  205. switch (stack->MinorFunction) {
  206. case IRP_MN_SET_POWER:
  207. switch (powerType) {
  208. case DevicePowerState:
  209. Cycladz_KdPrint(data,SER_DBG_CYCLADES, ("IRP_MN_SET_POWER Device\n"));
  210. //
  211. // Powering Up
  212. //
  213. ASSERT (powerState.DeviceState < data->DeviceState);
  214. context = ExAllocatePool (NonPagedPool,
  215. sizeof(WORKER_THREAD_CONTEXT));
  216. if(context){
  217. item = IoAllocateWorkItem(DeviceObject);
  218. context->Irp = Irp;
  219. context->DeviceObject= DeviceObject;
  220. context->WorkItem = item;
  221. context->PowerType = powerType;
  222. context->PowerState = powerState;
  223. if (item) {
  224. IoMarkIrpPending(Irp);
  225. IoQueueWorkItem (item,
  226. Cycladz_PowerOnWorkItem,
  227. DelayedWorkQueue,
  228. context);
  229. return STATUS_MORE_PROCESSING_REQUIRED;
  230. } else {
  231. //status = STATUS_INSUFFICIENT_RESOURCES;
  232. // What should we do? DDK says we cannot fail SET_POWER.
  233. }
  234. } else {
  235. //status = STATUS_INSUFFICIENT_RESOURCES;
  236. // What should we do? DDK says we cannot fail SET_POWER.
  237. }
  238. data->DeviceState = powerState.DeviceState;
  239. //PoSetPowerState (data->Self, powerType, powerState);
  240. break;
  241. default:
  242. Cycladz_KdPrint(data,SER_DBG_CYCLADES, ("IRP_MN_SET_POWER not Device\n"));
  243. break;
  244. }
  245. break;
  246. case IRP_MN_QUERY_POWER:
  247. Cycladz_KdPrint(data,SER_DBG_CYCLADES, ("IRP_MN_QUERY_POWER not Device\n"));
  248. ASSERT (IRP_MN_QUERY_POWER != stack->MinorFunction);
  249. break;
  250. default:
  251. ASSERT (0xBADBAD == IRP_MN_QUERY_POWER);
  252. break;
  253. }
  254. PoStartNextPowerIrp (Irp);
  255. Cycladz_DecIoCount (data);
  256. //return status; Changed to below line in build 2072
  257. Cycladz_KdPrint(data,SER_DBG_CYCLADES, ("Leaving Cycladz_FDOPowerComplete\n"));
  258. return STATUS_SUCCESS; // Continue completion...
  259. }
  260. NTSTATUS
  261. Cycladz_FDO_Power (
  262. PFDO_DEVICE_DATA Data,
  263. PIRP Irp
  264. )
  265. /*++
  266. --*/
  267. {
  268. NTSTATUS status;
  269. BOOLEAN hookit = FALSE;
  270. POWER_STATE powerState;
  271. POWER_STATE_TYPE powerType;
  272. PIO_STACK_LOCATION stack;
  273. // ADDED FANNY
  274. ULONG indexPDO;
  275. stack = IoGetCurrentIrpStackLocation (Irp);
  276. powerType = stack->Parameters.Power.Type;
  277. powerState = stack->Parameters.Power.State;
  278. Cycladz_KdPrint(Data,SER_DBG_CYCLADES, ("In Cycladz_FDO_Power Irp %x\n",Irp));
  279. status = Cycladz_IncIoCount (Data);
  280. if (!NT_SUCCESS (status)) {
  281. Irp->IoStatus.Information = 0;
  282. Irp->IoStatus.Status = status;
  283. PoStartNextPowerIrp (Irp);
  284. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  285. return status;
  286. }
  287. switch (stack->MinorFunction) {
  288. case IRP_MN_SET_POWER:
  289. //
  290. // If it hasn't started, we just pass it through
  291. //
  292. //if (Data->Started != TRUE) { // Added in DDK final version
  293. // status = Irp->IoStatus.Status = STATUS_SUCCESS;
  294. // break;
  295. //}
  296. if (Data->DevicePnPState != Started) { // Toaster Bus compares to == NotStarted
  297. status = Irp->IoStatus.Status = STATUS_SUCCESS;
  298. break;
  299. }
  300. Cycladz_KdPrint(Data,
  301. SER_DBG_PNP_TRACE,
  302. ("Cycladz-PnP Setting %s state to %d\n",
  303. ((powerType == SystemPowerState) ? "System" : "Device"),
  304. powerState.SystemState));
  305. switch (powerType) {
  306. case DevicePowerState:
  307. status = Irp->IoStatus.Status = STATUS_SUCCESS;
  308. if (Data->DeviceState < powerState.DeviceState) {
  309. //
  310. // Powering down
  311. //
  312. PoSetPowerState (Data->Self, powerType, powerState);
  313. Data->DeviceState = powerState.DeviceState;
  314. } else if (Data->DeviceState > powerState.DeviceState) {
  315. //
  316. // Powering Up
  317. //
  318. hookit = TRUE;
  319. }
  320. break;
  321. case SystemPowerState:
  322. IoMarkIrpPending(Irp);
  323. IoCopyCurrentIrpStackLocationToNext(Irp);
  324. status = Cycladz_IncIoCount (Data);
  325. ASSERT (STATUS_SUCCESS == status);
  326. IoSetCompletionRoutine (Irp,
  327. Cycladz_FDOSystemPowerComplete,
  328. NULL,
  329. TRUE,
  330. TRUE,
  331. TRUE);
  332. status = PoCallDriver (Data->TopOfStack, Irp);
  333. Cycladz_KdPrint(Data,SER_DBG_CYCLADES, ("Leaving Cycladz_FDO_Power\n"));
  334. Cycladz_DecIoCount (Data);
  335. return STATUS_PENDING;
  336. }
  337. break;
  338. case IRP_MN_QUERY_POWER:
  339. Cycladz_KdPrint(Data,SER_DBG_CYCLADES,("IRP_MN_QUERY_POWER\n"));
  340. status = Irp->IoStatus.Status = STATUS_SUCCESS;
  341. break;
  342. default:
  343. //
  344. // status should be STATUS_SUCCESS
  345. //
  346. break;
  347. }
  348. if (hookit) {
  349. IoMarkIrpPending(Irp);
  350. IoCopyCurrentIrpStackLocationToNext (Irp);
  351. status = Cycladz_IncIoCount (Data);
  352. ASSERT (STATUS_SUCCESS == status);
  353. IoSetCompletionRoutine (Irp,
  354. Cycladz_FDOPowerComplete,
  355. NULL,
  356. TRUE,
  357. TRUE,
  358. TRUE);
  359. status = PoCallDriver (Data->TopOfStack, Irp);
  360. Cycladz_KdPrint(Data,SER_DBG_CYCLADES, ("Leaving Cycladz_FDO_Power\n"));
  361. Cycladz_DecIoCount (Data);
  362. return STATUS_PENDING;
  363. }
  364. PoStartNextPowerIrp (Irp);
  365. IoSkipCurrentIrpStackLocation(Irp);
  366. status = PoCallDriver (Data->TopOfStack, Irp);
  367. Cycladz_KdPrint(Data,SER_DBG_CYCLADES, ("Leaving Cycladz_FDO_Power\n"));
  368. Cycladz_DecIoCount (Data);
  369. return status;
  370. }
  371. NTSTATUS
  372. Cycladz_PDO_Power (
  373. PPDO_DEVICE_DATA PdoData,
  374. PIRP Irp
  375. )
  376. /*++
  377. --*/
  378. {
  379. NTSTATUS status = STATUS_SUCCESS;
  380. PIO_STACK_LOCATION stack;
  381. POWER_STATE powerState;
  382. POWER_STATE_TYPE powerType;
  383. stack = IoGetCurrentIrpStackLocation (Irp);
  384. powerType = stack->Parameters.Power.Type;
  385. powerState = stack->Parameters.Power.State;
  386. switch (stack->MinorFunction) {
  387. case IRP_MN_SET_POWER:
  388. switch (powerType) {
  389. case DevicePowerState:
  390. Cycladz_KdPrint(PdoData,SER_DBG_CYCLADES,("IRP_MN_SET_POWER Device Pdo %x\n",
  391. PdoData->Self));
  392. if (PdoData->DeviceState > powerState.DeviceState) {
  393. PoSetPowerState (PdoData->Self, powerType, powerState);
  394. PdoData->DeviceState = powerState.DeviceState;
  395. } else if (PdoData->DeviceState < powerState.DeviceState) {
  396. //
  397. // Powering down.
  398. //
  399. PoSetPowerState (PdoData->Self, powerType, powerState);
  400. PdoData->DeviceState = powerState.DeviceState;
  401. }
  402. break;
  403. case SystemPowerState:
  404. Cycladz_KdPrint(PdoData,SER_DBG_CYCLADES,("IRP_MN_SET_POWER System Pdo %x\n",
  405. PdoData->Self));
  406. //
  407. // Default to STATUS_SUCCESS
  408. //
  409. break;
  410. default:
  411. status = STATUS_NOT_IMPLEMENTED;
  412. break;
  413. }
  414. break;
  415. case IRP_MN_QUERY_POWER:
  416. Cycladz_KdPrint(PdoData,SER_DBG_CYCLADES,("IRP_MN_QUERY_POWER Pdo %x\n",PdoData->Self));
  417. //
  418. // Default to STATUS_SUCCESS
  419. //
  420. break;
  421. case IRP_MN_WAIT_WAKE:
  422. case IRP_MN_POWER_SEQUENCE:
  423. Cycladz_KdPrint(PdoData,SER_DBG_CYCLADES,("IRP_MN_ NOT IMPLEMENTED\n"));
  424. status = STATUS_NOT_IMPLEMENTED;
  425. break;
  426. default:
  427. status = Irp->IoStatus.Status;
  428. }
  429. Irp->IoStatus.Status = status;
  430. PoStartNextPowerIrp (Irp);
  431. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  432. return status;
  433. }
  434. NTSTATUS
  435. Cycladz_Power (
  436. IN PDEVICE_OBJECT DeviceObject,
  437. IN PIRP Irp
  438. )
  439. /*++
  440. --*/
  441. {
  442. PIO_STACK_LOCATION irpStack;
  443. NTSTATUS status;
  444. PCOMMON_DEVICE_DATA commonData;
  445. status = STATUS_SUCCESS;
  446. irpStack = IoGetCurrentIrpStackLocation (Irp);
  447. ASSERT (IRP_MJ_POWER == irpStack->MajorFunction);
  448. commonData = (PCOMMON_DEVICE_DATA) DeviceObject->DeviceExtension;
  449. if (commonData->IsFDO) {
  450. status =
  451. Cycladz_FDO_Power ((PFDO_DEVICE_DATA) DeviceObject->DeviceExtension,
  452. Irp);
  453. } else {
  454. status =
  455. Cycladz_PDO_Power ((PPDO_DEVICE_DATA) DeviceObject->DeviceExtension,
  456. Irp);
  457. }
  458. return status;
  459. }
  460. NTSTATUS
  461. Cycladz_GotoPowerState(IN PDEVICE_OBJECT PDevObj,
  462. IN PFDO_DEVICE_DATA PDevExt,
  463. IN DEVICE_POWER_STATE DevPowerState)
  464. /*++
  465. Routine Description:
  466. This routine causes the driver to request the stack go to a particular
  467. power state.
  468. Arguments:
  469. PDevObj - Pointer to the device object for this device
  470. PDevExt - Pointer to the device extension we are working from
  471. DevPowerState - the power state we wish to go to
  472. Return Value:
  473. The function value is the final status of the call
  474. --*/
  475. {
  476. KEVENT gotoPowEvent;
  477. NTSTATUS status;
  478. POWER_STATE powerState;
  479. UNREFERENCED_PARAMETER (PDevExt);
  480. PAGED_CODE();
  481. Cycladz_KdPrint(PDevExt,SER_DBG_CYCLADES, ("In Cycladz_GotoPowerState\n"));
  482. powerState.DeviceState = DevPowerState;
  483. KeInitializeEvent(&gotoPowEvent, SynchronizationEvent, FALSE);
  484. status = PoRequestPowerIrp(PDevObj, IRP_MN_SET_POWER, powerState,
  485. Cycladz_SystemPowerCompletion, &gotoPowEvent,
  486. NULL);
  487. if (status == STATUS_PENDING) {
  488. KeWaitForSingleObject(&gotoPowEvent, Executive, KernelMode, FALSE, NULL);
  489. status = STATUS_SUCCESS;
  490. }
  491. #if DBG
  492. if (!NT_SUCCESS(status)) {
  493. Cycladz_KdPrint(PDevExt,SER_DBG_CYCLADES, ("Cycladz_GotoPowerState FAILED\n"));
  494. }
  495. #endif
  496. Cycladz_KdPrint(PDevExt,SER_DBG_CYCLADES, ("Leaving Cycladz_GotoPowerState\n"));
  497. return status;
  498. }
  499. NTSTATUS
  500. Cycladz_SystemPowerCompletion(IN PDEVICE_OBJECT PDevObj, UCHAR MinorFunction,
  501. IN POWER_STATE PowerState, IN PVOID Context,
  502. PIO_STATUS_BLOCK IoStatus)
  503. /*++
  504. Routine Description:
  505. This routine is the completion routine for PoRequestPowerIrp calls
  506. in this module.
  507. Arguments:
  508. PDevObj - Pointer to the device object the irp is completing for
  509. MinorFunction - IRP_MN_XXXX value requested
  510. PowerState - Power state request was made of
  511. Context - Event to set or NULL if no setting required
  512. IoStatus - Status block from request
  513. Return Value:
  514. VOID
  515. --*/
  516. {
  517. UNREFERENCED_PARAMETER (PDevObj);
  518. UNREFERENCED_PARAMETER (MinorFunction);
  519. UNREFERENCED_PARAMETER (PowerState);
  520. UNREFERENCED_PARAMETER (IoStatus);
  521. if (Context != NULL) {
  522. KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, 0);
  523. }
  524. return STATUS_SUCCESS;
  525. }