Source code of Windows XP (NT5)
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.

469 lines
11 KiB

  1. /*++
  2. Copyright (c) 1999-2001 Microsoft Corporation
  3. Module Name:
  4. pnpmem.c
  5. Abstract:
  6. This module implements the Plug and Play Memory driver entry points.
  7. Author:
  8. Dave Richards (daveri) 16-Aug-1999
  9. Environment:
  10. Kernel mode only.
  11. Revision History:
  12. --*/
  13. #include "pnpmem.h"
  14. #include <initguid.h>
  15. #include <poclass.h>
  16. #define PM_DEBUG_BUFFER_SIZE 512
  17. #define rgzMemoryManagement L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Session Manager\\Memory Management"
  18. #define rgzMemoryRemovable L"Memory Removable"
  19. NTSTATUS
  20. DriverEntry(
  21. IN PDRIVER_OBJECT DriverObject,
  22. IN PUNICODE_STRING RegistryPath
  23. );
  24. NTSTATUS
  25. PmAddDevice(
  26. IN PDRIVER_OBJECT DriverObject,
  27. IN PDEVICE_OBJECT Pdo
  28. );
  29. NTSTATUS
  30. PmPnpDispatch(
  31. IN PDEVICE_OBJECT Fdo,
  32. IN PIRP Irp
  33. );
  34. VOID
  35. PmUnload(
  36. IN PDRIVER_OBJECT DriverObject
  37. );
  38. #ifdef ALLOC_PRAGMA
  39. #pragma alloc_text(INIT, DriverEntry)
  40. #pragma alloc_text(PAGE, PmAddDevice)
  41. #pragma alloc_text(PAGE, PmUnload)
  42. #endif
  43. ULONG DbgMask = 0xFFFFFFFF;
  44. BOOLEAN MemoryRemovalSupported;
  45. #if DBG
  46. VOID
  47. PmDebugPrint(
  48. ULONG DebugPrintLevel,
  49. PCCHAR DebugMessage,
  50. ...
  51. )
  52. /*++
  53. Routine Description:
  54. Arguments:
  55. DebugPrintLevel - The bit mask that when anded with the debuglevel, must
  56. equal itself
  57. DebugMessage - The string to feed through vsprintf
  58. Return Value:
  59. None
  60. --*/
  61. {
  62. va_list ap;
  63. UCHAR debugBuffer[PM_DEBUG_BUFFER_SIZE];
  64. //
  65. // Get the variable arguments
  66. //
  67. va_start( ap, DebugMessage );
  68. //
  69. // Call the kernel function to print the message
  70. //
  71. _vsnprintf( debugBuffer, PM_DEBUG_BUFFER_SIZE, DebugMessage, ap );
  72. if (DebugPrintLevel & DbgMask) {
  73. DbgPrint("%s", debugBuffer);
  74. }
  75. //
  76. // We are done with the varargs
  77. //
  78. va_end( ap );
  79. }
  80. #endif
  81. NTSTATUS
  82. PmAddDevice(
  83. IN PDRIVER_OBJECT DriverObject,
  84. IN PDEVICE_OBJECT PhysicalDeviceObject
  85. )
  86. /*++
  87. Routine Description:
  88. This function creates a functional device object and attaches it to
  89. the physical device object (device stack).
  90. Arguments:
  91. DriverObject - The driver object.
  92. Pdo - The physical device object.
  93. Return Value:
  94. NTSTATUS
  95. --*/
  96. {
  97. PDEVICE_OBJECT functionalDeviceObject;
  98. PDEVICE_OBJECT attachedDeviceObject;
  99. PPM_DEVICE_EXTENSION deviceExtension;
  100. NTSTATUS status;
  101. PAGED_CODE();
  102. //
  103. // Create the FDO.
  104. //
  105. status = IoCreateDevice(
  106. DriverObject,
  107. sizeof (PM_DEVICE_EXTENSION),
  108. NULL,
  109. FILE_DEVICE_UNKNOWN | FILE_DEVICE_SECURE_OPEN,
  110. 0,
  111. FALSE,
  112. &functionalDeviceObject
  113. );
  114. if (!NT_SUCCESS(status)) {
  115. return status;
  116. }
  117. //
  118. // Attach the FDO (indirectly) to the PDO.
  119. //
  120. deviceExtension = functionalDeviceObject->DeviceExtension;
  121. deviceExtension->AttachedDevice = IoAttachDeviceToDeviceStack(
  122. functionalDeviceObject,
  123. PhysicalDeviceObject
  124. );
  125. if (deviceExtension->AttachedDevice == NULL) {
  126. IoDeleteDevice(functionalDeviceObject);
  127. return STATUS_NO_SUCH_DEVICE;
  128. }
  129. IoInitializeRemoveLock(&deviceExtension->RemoveLock, 0, 1, 20);
  130. functionalDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  131. return status;
  132. }
  133. NTSTATUS
  134. PmControlDispatch(
  135. IN PDEVICE_OBJECT DeviceObject,
  136. IN PIRP Irp
  137. )
  138. {
  139. PPM_DEVICE_EXTENSION deviceExtension;
  140. deviceExtension = DeviceObject->DeviceExtension;
  141. IoSkipCurrentIrpStackLocation(Irp);
  142. return IoCallDriver(deviceExtension->AttachedDevice, Irp);
  143. }
  144. VOID
  145. PmPowerCallback(
  146. IN PDEVICE_OBJECT DeviceObject,
  147. IN UCHAR MinorFunction,
  148. IN POWER_STATE PowerState,
  149. IN PVOID Context,
  150. IN PIO_STATUS_BLOCK IoStatus
  151. )
  152. {
  153. PPM_DEVICE_EXTENSION deviceExtension;
  154. PIRP Irp;
  155. NTSTATUS status;
  156. Irp = Context;
  157. deviceExtension = DeviceObject->DeviceExtension;
  158. Irp->IoStatus.Status = IoStatus->Status;
  159. PoStartNextPowerIrp(Irp);
  160. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  161. IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp);
  162. }
  163. NTSTATUS
  164. PmPowerCompletion(
  165. IN PDEVICE_OBJECT DeviceObject,
  166. IN PIRP Irp,
  167. IN PVOID NotUsed
  168. )
  169. /*++
  170. Routine Description:
  171. The completion routine for Power
  172. Arguments:
  173. DeviceObject - pointer to a device object.
  174. Irp - pointer to an I/O Request Packet.
  175. Not used - context pointer
  176. Return Value:
  177. NT status code
  178. --*/
  179. {
  180. PIO_STACK_LOCATION irpStack;
  181. PPM_DEVICE_EXTENSION deviceExtension;
  182. NTSTATUS status;
  183. irpStack = IoGetCurrentIrpStackLocation(Irp);
  184. deviceExtension = DeviceObject->DeviceExtension;
  185. if (irpStack->Parameters.Power.Type == SystemPowerState) {
  186. SYSTEM_POWER_STATE system =
  187. irpStack->Parameters.Power.State.SystemState;
  188. POWER_STATE power;
  189. if (NT_SUCCESS(Irp->IoStatus.Status)) {
  190. power.DeviceState = deviceExtension->DeviceStateMapping[system];
  191. status = PoRequestPowerIrp(DeviceObject,
  192. irpStack->MinorFunction,
  193. power,
  194. PmPowerCallback,
  195. Irp,
  196. NULL);
  197. if (NT_SUCCESS(status)) {
  198. return STATUS_MORE_PROCESSING_REQUIRED;
  199. } else {
  200. Irp->IoStatus.Status = status;
  201. }
  202. }
  203. PoStartNextPowerIrp(Irp);
  204. IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp);
  205. return STATUS_SUCCESS;
  206. } else {
  207. if (NT_SUCCESS(Irp->IoStatus.Status)) {
  208. PoSetPowerState(DeviceObject, DevicePowerState,
  209. irpStack->Parameters.Power.State);
  210. deviceExtension->PowerState =
  211. irpStack->Parameters.Power.State.DeviceState;
  212. }
  213. PoStartNextPowerIrp(Irp);
  214. IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp);
  215. return STATUS_SUCCESS;
  216. }
  217. }
  218. NTSTATUS
  219. PmPowerDispatch(
  220. IN PDEVICE_OBJECT DeviceObject,
  221. IN PIRP Irp
  222. )
  223. {
  224. PPM_DEVICE_EXTENSION deviceExtension;
  225. PIO_STACK_LOCATION irpStack;
  226. NTSTATUS status;
  227. irpStack = IoGetCurrentIrpStackLocation(Irp);
  228. deviceExtension = DeviceObject->DeviceExtension;
  229. status = IoAcquireRemoveLock(&deviceExtension->RemoveLock, (PVOID) Irp);
  230. if (status == STATUS_DELETE_PENDING) {
  231. Irp->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
  232. PoStartNextPowerIrp(Irp);
  233. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  234. return STATUS_NO_SUCH_DEVICE;
  235. }
  236. if (irpStack->Parameters.Power.Type == SystemPowerState) {
  237. switch (irpStack->MinorFunction) {
  238. case IRP_MN_QUERY_POWER:
  239. case IRP_MN_SET_POWER:
  240. IoMarkIrpPending(Irp);
  241. IoCopyCurrentIrpStackLocationToNext(Irp);
  242. IoSetCompletionRoutine(Irp,
  243. PmPowerCompletion,
  244. NULL, //Context
  245. TRUE, //InvokeOnSuccess
  246. TRUE, //InvokeOnError
  247. TRUE //InvokeOnCancel
  248. );
  249. (VOID) PoCallDriver(deviceExtension->AttachedDevice, Irp);
  250. return STATUS_PENDING;
  251. default:
  252. PoStartNextPowerIrp(Irp);
  253. IoSkipCurrentIrpStackLocation(Irp);
  254. status = PoCallDriver(deviceExtension->AttachedDevice, Irp);
  255. IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp);
  256. return status;
  257. }
  258. } else {
  259. switch (irpStack->MinorFunction) {
  260. case IRP_MN_SET_POWER:
  261. if (irpStack->Parameters.Power.State.DeviceState <=
  262. deviceExtension->PowerState) {
  263. //
  264. // Powering up device
  265. //
  266. IoCopyCurrentIrpStackLocationToNext(Irp);
  267. IoSetCompletionRoutine(Irp,
  268. PmPowerCompletion,
  269. NULL, //Context
  270. TRUE, //InvokeOnSuccess
  271. TRUE, //InvokeOnError
  272. TRUE //InvokeOnCancel
  273. );
  274. (VOID) PoCallDriver(deviceExtension->AttachedDevice, Irp);
  275. return STATUS_PENDING;
  276. } else {
  277. //
  278. // Powering down device
  279. //
  280. PoSetPowerState(DeviceObject, DevicePowerState,
  281. irpStack->Parameters.Power.State);
  282. deviceExtension->PowerState =
  283. irpStack->Parameters.Power.State.DeviceState;
  284. //
  285. // Fall through ...
  286. //
  287. }
  288. case IRP_MN_QUERY_POWER:
  289. //
  290. // Fall through as the bus driver will mark this
  291. // STATUS_SUCCESS and complete it, if it gets that far.
  292. //
  293. default:
  294. PoStartNextPowerIrp(Irp);
  295. IoSkipCurrentIrpStackLocation(Irp);
  296. break;
  297. }
  298. status = PoCallDriver(deviceExtension->AttachedDevice, Irp);
  299. IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp);
  300. return status;
  301. }
  302. }
  303. NTSTATUS
  304. DriverEntry(
  305. IN PDRIVER_OBJECT DriverObject,
  306. IN PUNICODE_STRING RegistryPath
  307. )
  308. /*++
  309. Routine Description:
  310. This function initializes the driver object.
  311. Arguments:
  312. DriverObject - The driver object.
  313. RegistryPath - The registry path for the device.
  314. Return Value:
  315. STATUS_SUCCESS
  316. --*/
  317. {
  318. OBJECT_ATTRIBUTES objectAttributes;
  319. UNICODE_STRING unicodeString;
  320. PKEY_VALUE_PARTIAL_INFORMATION valueInfo;
  321. HANDLE hMemoryManagement;
  322. NTSTATUS status;
  323. PAGED_CODE();
  324. RtlInitUnicodeString (&unicodeString, rgzMemoryManagement);
  325. InitializeObjectAttributes (&objectAttributes,
  326. &unicodeString,
  327. OBJ_CASE_INSENSITIVE,
  328. NULL, // handle
  329. NULL);
  330. status = ZwOpenKey(&hMemoryManagement, KEY_READ, &objectAttributes);
  331. if (NT_SUCCESS(status)) {
  332. status = PmGetRegistryValue(hMemoryManagement,
  333. rgzMemoryRemovable,
  334. &valueInfo);
  335. if (NT_SUCCESS(status)) {
  336. if ((valueInfo->Type == REG_DWORD) &&
  337. (valueInfo->DataLength >= sizeof(ULONG))) {
  338. MemoryRemovalSupported = (BOOLEAN) *((PULONG)valueInfo->Data);
  339. }
  340. ExFreePool(valueInfo);
  341. }
  342. ZwClose(hMemoryManagement);
  343. }
  344. DriverObject->MajorFunction[IRP_MJ_PNP] = PmPnpDispatch;
  345. DriverObject->MajorFunction[IRP_MJ_POWER] = PmPowerDispatch;
  346. DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = PmControlDispatch;
  347. DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = PmControlDispatch;
  348. DriverObject->DriverExtension->AddDevice = PmAddDevice;
  349. return STATUS_SUCCESS;
  350. }
  351. VOID
  352. PmUnload(
  353. IN PDRIVER_OBJECT DriverObject
  354. )
  355. /*++
  356. Routine Description:
  357. This is called to reverse any operations performed in DriverEntry before a
  358. driver is unloaded.
  359. Arguments:
  360. DriverObject - The system owned driver object for PNPMEM
  361. --*/
  362. {
  363. PAGED_CODE();
  364. return;
  365. }