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.

607 lines
16 KiB

  1. /*--------------------------------------------------------------------------
  2. *
  3. * Copyright (C) Cyclades Corporation, 1999-2001.
  4. * All rights reserved.
  5. *
  6. * Cyclom-Y Enumerator Driver
  7. *
  8. * This file: power.c
  9. *
  10. * Description: This module contains contains the power calls
  11. * for the cyclom-y 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, Cyclomy_Power)
  32. //#pragma alloc_text (PAGE, Cyclomy_FDO_Power)
  33. //#pragma alloc_text (PAGE, Cyclomy_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. Cyclomy_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. Cyclomy_DecIoCount(fdoData);
  75. Cyclomy_KdPrint(fdoData,SER_DBG_POWER_TRACE, ("<OnPowerRequestComplete\n"));
  76. }
  77. NTSTATUS
  78. Cyclomy_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. Cyclomy_KdPrint(data,SER_DBG_POWER_TRACE, (">SystemPowerComplete\n"));
  95. if (!NT_SUCCESS(status)) {
  96. PoStartNextPowerIrp(Irp);
  97. Cyclomy_DecIoCount (data);
  98. Cyclomy_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. Cyclomy_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. Cyclomy_DecIoCount(data);
  143. Cyclomy_KdPrint(data,SER_DBG_POWER_TRACE, ("<2SystemPowerComplete\n"));
  144. return status;
  145. }
  146. Cyclomy_KdPrint(data,SER_DBG_POWER_TRACE, ("<3SystemPowerComplete\n"));
  147. return STATUS_MORE_PROCESSING_REQUIRED;
  148. }
  149. NTSTATUS
  150. Cyclomy_FDOPowerComplete (
  151. IN PDEVICE_OBJECT DeviceObject,
  152. IN PIRP Irp,
  153. IN PVOID Context
  154. )
  155. /*++
  156. --*/
  157. {
  158. POWER_STATE powerState;
  159. POWER_STATE_TYPE powerType;
  160. PIO_STACK_LOCATION stack;
  161. PFDO_DEVICE_DATA data;
  162. // NTSTATUS status = STATUS_SUCCESS; Removed in build 2072
  163. UNREFERENCED_PARAMETER (Context);
  164. if (Irp->PendingReturned) {
  165. IoMarkIrpPending(Irp);
  166. }
  167. data = (PFDO_DEVICE_DATA) DeviceObject->DeviceExtension;
  168. stack = IoGetCurrentIrpStackLocation (Irp);
  169. powerType = stack->Parameters.Power.Type;
  170. powerState = stack->Parameters.Power.State;
  171. Cyclomy_KdPrint(data,SER_DBG_POWER_TRACE, (">DevicePowerComplete\n"));
  172. switch (stack->MinorFunction) {
  173. case IRP_MN_SET_POWER:
  174. switch (powerType) {
  175. case DevicePowerState:
  176. //
  177. // Powering Up
  178. //
  179. ASSERT (powerState.DeviceState < data->DeviceState);
  180. Cyclomy_DoesBoardExist(data); // To initialize CD1400
  181. Cyclomy_EnableInterruptInPLX(data); // Enable interrupt in the PLX
  182. data->DeviceState = powerState.DeviceState;
  183. PoSetPowerState (data->Self, powerType, powerState);
  184. break;
  185. default:
  186. break;
  187. }
  188. break;
  189. case IRP_MN_QUERY_POWER:
  190. ASSERT (IRP_MN_QUERY_POWER != stack->MinorFunction);
  191. break;
  192. default:
  193. //
  194. // Basically, this is ASSERT(0)
  195. //
  196. ASSERT (0xBADBAD == IRP_MN_QUERY_POWER);
  197. break;
  198. }
  199. PoStartNextPowerIrp (Irp);
  200. Cyclomy_DecIoCount (data);
  201. Cyclomy_KdPrint(data,SER_DBG_POWER_TRACE, ("<DevicePowerComplete\n"));
  202. //return status; Changed to below line in build 2072
  203. return STATUS_SUCCESS; // Continue completion...
  204. }
  205. NTSTATUS
  206. Cyclomy_FDO_Power (
  207. PFDO_DEVICE_DATA Data,
  208. PIRP Irp
  209. )
  210. /*++
  211. --*/
  212. {
  213. NTSTATUS status;
  214. BOOLEAN hookit = FALSE;
  215. POWER_STATE powerState;
  216. POWER_STATE_TYPE powerType;
  217. PIO_STACK_LOCATION stack;
  218. // ADDED FANNY
  219. ULONG indexPDO;
  220. stack = IoGetCurrentIrpStackLocation (Irp);
  221. powerType = stack->Parameters.Power.Type;
  222. powerState = stack->Parameters.Power.State;
  223. status = Cyclomy_IncIoCount (Data);
  224. if (!NT_SUCCESS (status)) {
  225. Irp->IoStatus.Information = 0;
  226. Irp->IoStatus.Status = status;
  227. PoStartNextPowerIrp (Irp);
  228. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  229. return status;
  230. }
  231. switch (stack->MinorFunction) {
  232. case IRP_MN_SET_POWER:
  233. //
  234. // If it hasn't started, we just pass it through
  235. //
  236. //if (Data->Started != TRUE) { // Added in DDK final version
  237. // status = Irp->IoStatus.Status = STATUS_SUCCESS;
  238. // break;
  239. //}
  240. if (Data->DevicePnPState != Started) { // Toaster Bus compares to == NotStarted
  241. status = Irp->IoStatus.Status = STATUS_SUCCESS;
  242. break;
  243. }
  244. Cyclomy_KdPrint(Data,
  245. SER_DBG_PNP_TRACE,
  246. ("Cyclomy-PnP Setting %s state to %d\n",
  247. ((powerType == SystemPowerState) ? "System" : "Device"),
  248. powerState.SystemState));
  249. switch (powerType) {
  250. case DevicePowerState:
  251. Cyclomy_KdPrint(Data,SER_DBG_POWER_TRACE, ("SET_POWER Device %x\n",Irp));
  252. status = Irp->IoStatus.Status = STATUS_SUCCESS;
  253. if (Data->DeviceState < powerState.DeviceState) {
  254. //
  255. // Powering down
  256. //
  257. PoSetPowerState (Data->Self, powerType, powerState);
  258. Data->DeviceState = powerState.DeviceState;
  259. } else if (Data->DeviceState > powerState.DeviceState) {
  260. //
  261. // Powering Up
  262. //
  263. hookit = TRUE;
  264. }
  265. break;
  266. case SystemPowerState:
  267. Cyclomy_KdPrint(Data,SER_DBG_POWER_TRACE, ("SET_POWER System %x\n",Irp));
  268. IoMarkIrpPending(Irp);
  269. IoCopyCurrentIrpStackLocationToNext(Irp);
  270. status = Cyclomy_IncIoCount (Data);
  271. ASSERT (STATUS_SUCCESS == status);
  272. IoSetCompletionRoutine (Irp,
  273. Cyclomy_FDOSystemPowerComplete,
  274. NULL,
  275. TRUE,
  276. TRUE,
  277. TRUE);
  278. PoCallDriver (Data->TopOfStack, Irp);
  279. Cyclomy_DecIoCount (Data);
  280. return STATUS_PENDING;
  281. }
  282. break;
  283. case IRP_MN_QUERY_POWER:
  284. status = Irp->IoStatus.Status = STATUS_SUCCESS;
  285. break;
  286. default:
  287. //
  288. // status should be STATUS_SUCCESS
  289. //
  290. break;
  291. }
  292. if (hookit) {
  293. IoMarkIrpPending(Irp);
  294. IoCopyCurrentIrpStackLocationToNext (Irp);
  295. status = Cyclomy_IncIoCount (Data);
  296. ASSERT (STATUS_SUCCESS == status);
  297. IoSetCompletionRoutine (Irp,
  298. Cyclomy_FDOPowerComplete,
  299. NULL,
  300. TRUE,
  301. TRUE,
  302. TRUE);
  303. PoCallDriver (Data->TopOfStack, Irp);
  304. Cyclomy_KdPrint(Data,SER_DBG_POWER_TRACE, ("SET_POWER Device status %x\n",status));
  305. Cyclomy_DecIoCount (Data);
  306. return STATUS_PENDING;
  307. }
  308. PoStartNextPowerIrp (Irp);
  309. IoSkipCurrentIrpStackLocation(Irp);
  310. status = PoCallDriver (Data->TopOfStack, Irp);
  311. Cyclomy_DecIoCount (Data);
  312. return status;
  313. }
  314. NTSTATUS
  315. Cyclomy_PDO_Power (
  316. PPDO_DEVICE_DATA PdoData,
  317. PIRP Irp
  318. )
  319. /*++
  320. --*/
  321. {
  322. NTSTATUS status = STATUS_SUCCESS;
  323. PIO_STACK_LOCATION stack;
  324. POWER_STATE powerState;
  325. POWER_STATE_TYPE powerType;
  326. stack = IoGetCurrentIrpStackLocation (Irp);
  327. powerType = stack->Parameters.Power.Type;
  328. powerState = stack->Parameters.Power.State;
  329. switch (stack->MinorFunction) {
  330. case IRP_MN_SET_POWER:
  331. switch (powerType) {
  332. case DevicePowerState:
  333. if (PdoData->DeviceState > powerState.DeviceState) {
  334. //DbgPrint("Up\n");
  335. PoSetPowerState (PdoData->Self, powerType, powerState);
  336. PdoData->DeviceState = powerState.DeviceState;
  337. } else if (PdoData->DeviceState < powerState.DeviceState) {
  338. //
  339. // Powering down.
  340. //
  341. //DbgPrint("Down\n");
  342. PoSetPowerState (PdoData->Self, powerType, powerState);
  343. PdoData->DeviceState = powerState.DeviceState;
  344. }
  345. break;
  346. case SystemPowerState:
  347. //
  348. // Default to STATUS_SUCCESS
  349. //
  350. break;
  351. default:
  352. status = STATUS_NOT_IMPLEMENTED;
  353. break;
  354. }
  355. break;
  356. case IRP_MN_QUERY_POWER:
  357. //
  358. // Default to STATUS_SUCCESS
  359. //
  360. break;
  361. case IRP_MN_WAIT_WAKE:
  362. case IRP_MN_POWER_SEQUENCE:
  363. status = STATUS_NOT_IMPLEMENTED;
  364. break;
  365. default:
  366. status = Irp->IoStatus.Status;
  367. }
  368. Irp->IoStatus.Status = status;
  369. PoStartNextPowerIrp (Irp);
  370. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  371. return status;
  372. }
  373. NTSTATUS
  374. Cyclomy_Power (
  375. IN PDEVICE_OBJECT DeviceObject,
  376. IN PIRP Irp
  377. )
  378. /*++
  379. --*/
  380. {
  381. PIO_STACK_LOCATION irpStack;
  382. NTSTATUS status;
  383. PCOMMON_DEVICE_DATA commonData;
  384. status = STATUS_SUCCESS;
  385. irpStack = IoGetCurrentIrpStackLocation (Irp);
  386. ASSERT (IRP_MJ_POWER == irpStack->MajorFunction);
  387. commonData = (PCOMMON_DEVICE_DATA) DeviceObject->DeviceExtension;
  388. if (commonData->IsFDO) {
  389. status =
  390. Cyclomy_FDO_Power ((PFDO_DEVICE_DATA) DeviceObject->DeviceExtension,
  391. Irp);
  392. } else {
  393. status =
  394. Cyclomy_PDO_Power ((PPDO_DEVICE_DATA) DeviceObject->DeviceExtension,
  395. Irp);
  396. }
  397. return status;
  398. }
  399. NTSTATUS
  400. Cyclomy_GotoPowerState(IN PDEVICE_OBJECT PDevObj,
  401. IN PFDO_DEVICE_DATA PDevExt,
  402. IN DEVICE_POWER_STATE DevPowerState)
  403. /*++
  404. Routine Description:
  405. This routine causes the driver to request the stack go to a particular
  406. power state.
  407. Arguments:
  408. PDevObj - Pointer to the device object for this device
  409. PDevExt - Pointer to the device extension we are working from
  410. DevPowerState - the power state we wish to go to
  411. Return Value:
  412. The function value is the final status of the call
  413. --*/
  414. {
  415. KEVENT gotoPowEvent;
  416. NTSTATUS status;
  417. POWER_STATE powerState;
  418. UNREFERENCED_PARAMETER (PDevExt);
  419. PAGED_CODE();
  420. Cyclomy_KdPrint(PDevExt,SER_DBG_CYCLADES, ("In Cyclomy_GotoPowerState\n"));
  421. powerState.DeviceState = DevPowerState;
  422. KeInitializeEvent(&gotoPowEvent, SynchronizationEvent, FALSE);
  423. status = PoRequestPowerIrp(PDevObj, IRP_MN_SET_POWER, powerState,
  424. Cyclomy_SystemPowerCompletion, &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. Cyclomy_KdPrint(PDevExt,SER_DBG_CYCLADES, ("Cyclomy_GotoPowerState FAILED\n"));
  433. }
  434. #endif
  435. Cyclomy_KdPrint(PDevExt,SER_DBG_CYCLADES, ("Leaving Cyclomy_GotoPowerState\n"));
  436. return status;
  437. }
  438. NTSTATUS
  439. Cyclomy_SystemPowerCompletion(IN PDEVICE_OBJECT PDevObj, UCHAR MinorFunction,
  440. IN POWER_STATE PowerState, IN PVOID Context,
  441. PIO_STATUS_BLOCK IoStatus)
  442. /*++
  443. Routine Description:
  444. This routine is the completion routine for PoRequestPowerIrp calls
  445. in this module.
  446. Arguments:
  447. PDevObj - Pointer to the device object the irp is completing for
  448. MinorFunction - IRP_MN_XXXX value requested
  449. PowerState - Power state request was made of
  450. Context - Event to set or NULL if no setting required
  451. IoStatus - Status block from request
  452. Return Value:
  453. VOID
  454. --*/
  455. {
  456. UNREFERENCED_PARAMETER (PDevObj);
  457. UNREFERENCED_PARAMETER (MinorFunction);
  458. UNREFERENCED_PARAMETER (PowerState);
  459. UNREFERENCED_PARAMETER (IoStatus);
  460. if (Context != NULL) {
  461. KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, 0);
  462. }
  463. return STATUS_SUCCESS;
  464. }