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.

524 lines
12 KiB

  1. /*++
  2. Copyright (c) 2000-2001 Microsoft Corporation
  3. Module Name:
  4. acpisim.c
  5. Abstract:
  6. ACPI BIOS Simulator / Generic 3rd Party Operation Region Provider
  7. Author(s):
  8. Vincent Geglia
  9. Michael T. Murphy
  10. Chris Burgess
  11. Environment:
  12. Kernel mode
  13. Notes:
  14. Revision History:
  15. --*/
  16. //
  17. // General includes
  18. //
  19. #include <ntddk.h>
  20. #include <stdarg.h>
  21. #include <stdio.h>
  22. #include <ntpoapi.h>
  23. //
  24. // Specific includes
  25. //
  26. #include "acpisim.h"
  27. #include "dispatch.h"
  28. #include "util.h"
  29. //
  30. // Debug global flag
  31. //
  32. #ifdef DBG
  33. extern ULONG AcpisimDebugMask = 0x00000000;
  34. #endif
  35. //
  36. // Globals
  37. //
  38. PDRIVER_OBJECT_EXTENSION g_DriverObjectExtension = 0;
  39. //
  40. // Define supported IRPs, friendly name them, and associate handlers
  41. //
  42. IRP_DISPATCH_TABLE g_IrpDispatchTable [] = {
  43. IRP_MJ_PNP, "PnP Irp", AcpisimDispatchPnp,
  44. IRP_MJ_POWER, "Power Irp", AcpisimDispatchPower,
  45. IRP_MJ_DEVICE_CONTROL, "IOCTL Irp", AcpisimDispatchIoctl,
  46. IRP_MJ_CREATE, "Create Irp", AcpisimCreateClose,
  47. IRP_MJ_CLOSE, "Close Irp", AcpisimCreateClose,
  48. IRP_MJ_SYSTEM_CONTROL, "System Control IRP", AcpisimDispatchSystemControl
  49. };
  50. //
  51. // Private funtion prototypes
  52. //
  53. NTSTATUS DriverEntry
  54. (
  55. IN PDRIVER_OBJECT DriverObject,
  56. IN PUNICODE_STRING RegistryPath
  57. );
  58. NTSTATUS
  59. AcpisimGeneralDispatch
  60. (
  61. IN PDEVICE_OBJECT DeviceObject,
  62. IN PIRP Irp
  63. );
  64. VOID
  65. AcpisimUnload
  66. (
  67. IN PDRIVER_OBJECT DriverObject
  68. );
  69. NTSTATUS
  70. AcpisimAddDevice
  71. (
  72. IN PDRIVER_OBJECT DriverObject,
  73. IN PDEVICE_OBJECT Pdo
  74. );
  75. //
  76. // Define pageable / init discardable routines
  77. //
  78. #ifdef ALLOC_PRAGMA
  79. #pragma alloc_text (INIT, DriverEntry)
  80. #endif
  81. NTSTATUS DriverEntry
  82. (
  83. IN PDRIVER_OBJECT DriverObject,
  84. IN PUNICODE_STRING RegistryPath
  85. )
  86. /*++
  87. Routine Description:
  88. Installable driver initialization entry point.
  89. This entry point is called directly by the I/O system.
  90. Arguments:
  91. DriverObject - pointer to the driver object
  92. RegistryPath - pointer to a unicode string representing the path,
  93. to driver-specific key in the registry.
  94. Return Value:
  95. STATUS_SUCCESS if successful,
  96. STATUS_UNSUCCESSFUL otherwise.
  97. --*/
  98. {
  99. NTSTATUS status = STATUS_UNSUCCESSFUL;
  100. ULONG count = 0, subcount = 0;
  101. DBG_PRINT (DBG_INFO, "Entering DriverEntry\n");
  102. status = IoAllocateDriverObjectExtension (DriverObject,
  103. (PVOID) 'GLBL',
  104. sizeof (DRIVER_OBJECT_EXTENSION),
  105. &g_DriverObjectExtension);
  106. if (!NT_SUCCESS (status)) {
  107. DBG_PRINT (DBG_ERROR, "Unable to allocate global driver object extension (%lx).\n", status);
  108. goto EndDriverEntry;
  109. }
  110. RtlZeroMemory (g_DriverObjectExtension, sizeof (DRIVER_OBJECT_EXTENSION));
  111. RtlInitUnicodeString (&g_DriverObjectExtension->RegistryPath,
  112. (PCWSTR) RegistryPath->Buffer);
  113. g_DriverObjectExtension->DriverObject = DriverObject;
  114. //
  115. // Init dispatch points. We'll use a generic dispatch routine for
  116. // IRP types we handle.
  117. //
  118. while (count <= IRP_MJ_MAXIMUM_FUNCTION) {
  119. for (subcount = 0; subcount < sizeof (g_IrpDispatchTable) / sizeof (IRP_DISPATCH_TABLE); subcount++) {
  120. if (count == g_IrpDispatchTable[subcount].IrpFunction) {
  121. DriverObject->MajorFunction [count] = AcpisimGeneralDispatch;
  122. }
  123. }
  124. count ++;
  125. }
  126. DriverObject->DriverUnload = AcpisimUnload;
  127. DriverObject->DriverExtension->AddDevice = AcpisimAddDevice;
  128. EndDriverEntry:
  129. DBG_PRINT (DBG_INFO, "Exiting DriverEntry\n");
  130. return status;
  131. }
  132. NTSTATUS
  133. AcpisimGeneralDispatch
  134. (
  135. IN PDEVICE_OBJECT DeviceObject,
  136. IN PIRP Irp
  137. )
  138. /*++
  139. Routine Description:
  140. This is a general dispatch routine for supported IRPs.
  141. Arguments:
  142. DeviceObject - pointer to the device object
  143. Irp - pointer to the IRP being passed in
  144. Return Value:
  145. status of IRP handling
  146. --*/
  147. {
  148. PDEVICE_EXTENSION deviceextension = AcpisimGetDeviceExtension (DeviceObject);
  149. PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation (Irp);
  150. NTSTATUS status = STATUS_UNSUCCESSFUL;
  151. ULONG count = 0;
  152. DBG_PRINT (DBG_INFO, "Entering AcpisimGeneralDispatch\n");
  153. InterlockedIncrement (&deviceextension->OutstandingIrpCount);
  154. //
  155. // Acquire the remove lock for outstanding I/O
  156. //
  157. IoAcquireRemoveLock (&deviceextension->RemoveLock, Irp);
  158. while (count < sizeof (g_IrpDispatchTable) / sizeof (IRP_DISPATCH_TABLE)) {
  159. if (irpsp->MajorFunction == g_IrpDispatchTable[count].IrpFunction) {
  160. DBG_PRINT (DBG_INFO,
  161. "Recognized IRP MajorFunction = 0x%x '%s'.\n",
  162. g_IrpDispatchTable[count].IrpFunction,
  163. g_IrpDispatchTable[count].IrpName
  164. );
  165. status = g_IrpDispatchTable[count].IrpHandler (DeviceObject, Irp);
  166. goto EndAcpisimProcessIncomingIrp;
  167. }
  168. count ++;
  169. }
  170. //
  171. // Unrecognized IRP - pass it on
  172. //
  173. DBG_PRINT (DBG_INFO, "Unrecognized IRP MajorFunction = 0x%x\n, pass it on.\n", irpsp->MajorFunction);
  174. IoSkipCurrentIrpStackLocation (Irp);
  175. status = IoCallDriver (deviceextension->NextDevice, Irp);
  176. EndAcpisimProcessIncomingIrp:
  177. //
  178. // If the status is pending, the IRP hasn't "left" our
  179. // driver yet. Whoever completes the IRP will do the
  180. // decrement.
  181. //
  182. if (status != STATUS_PENDING)
  183. {
  184. AcpisimDecrementIrpCount (DeviceObject);
  185. IoReleaseRemoveLock (&deviceextension->RemoveLock, Irp);
  186. }
  187. DBG_PRINT (DBG_INFO, "Exiting AcpisimGeneralDispatch\n");
  188. return status;
  189. }
  190. VOID
  191. AcpisimUnload
  192. (
  193. IN PDRIVER_OBJECT DriverObject
  194. )
  195. /*++
  196. Routine Description:
  197. This is the driver unload routine.
  198. Arguments:
  199. DriverObject - pointer to the driver object
  200. Return Value:
  201. none
  202. --*/
  203. {
  204. PDRIVER_OBJECT_EXTENSION driverobjectextension = 0;
  205. driverobjectextension = IoGetDriverObjectExtension (DriverObject,
  206. (PVOID) 'GLBL');
  207. if (!driverobjectextension) {
  208. DBG_PRINT (DBG_ERROR, "Unable to get driver object extension. Memory will probably leak.\n");
  209. goto EndAcpisimUnload;
  210. }
  211. EndAcpisimUnload:
  212. return;
  213. }
  214. NTSTATUS
  215. AcpisimAddDevice
  216. (
  217. IN PDRIVER_OBJECT DriverObject,
  218. IN PDEVICE_OBJECT Pdo
  219. )
  220. /*++
  221. Routine Description:
  222. This is the driver WDM AddDevice Routine
  223. Arguments:
  224. DriverObject - pointer to the driver object
  225. Pdo - pointer to PDO for this device
  226. Return Value:
  227. status of device addition
  228. --*/
  229. {
  230. NTSTATUS status = STATUS_UNSUCCESSFUL;
  231. PDEVICE_OBJECT deviceobject = 0;
  232. PDEVICE_EXTENSION deviceextension = 0;
  233. CONST GUID guid = ACPISIM_GUID;
  234. DBG_PRINT (DBG_INFO, "Entering AcpisimAddDevice.\n");
  235. //
  236. // If Pdo is NULL, we are being asked to do legacy detection.
  237. // Our device is never legacy detected, so return accordingly.
  238. //
  239. if (Pdo == NULL) {
  240. DBG_PRINT (DBG_WARN, "AddDevice - asked to do legacy detection (Pdo = NULL). Not supported...\n");
  241. status = STATUS_NO_MORE_ENTRIES;
  242. goto EndAcpisimAddDevice;
  243. }
  244. //
  245. // Create our FDO. Don't use a name - we'll use a device interface
  246. //
  247. status = IoCreateDevice (DriverObject,
  248. sizeof (DEVICE_EXTENSION),
  249. 0,
  250. FILE_DEVICE_UNKNOWN,
  251. 0,
  252. TRUE,
  253. &deviceobject);
  254. if (!NT_SUCCESS (status)) {
  255. DBG_PRINT (DBG_ERROR, "Can't create FDO. Status = %lx.\n", status);
  256. goto EndAcpisimAddDevice;
  257. }
  258. //
  259. // Init our device extension
  260. //
  261. deviceextension = deviceobject->DeviceExtension;
  262. RtlZeroMemory (deviceextension, sizeof (DEVICE_EXTENSION));
  263. deviceextension->Signature = ACPISIM_TAG;
  264. deviceextension->PnpState = PNP_STATE_INITIALIZING;
  265. deviceextension->OutstandingIrpCount = 1;
  266. deviceextension->DeviceObject = deviceobject;
  267. deviceextension->Pdo = Pdo;
  268. KeInitializeEvent (&deviceextension->IrpsCompleted, SynchronizationEvent, FALSE);
  269. //
  270. // Initialize the remove lock
  271. //
  272. IoInitializeRemoveLock (&deviceextension->RemoveLock,
  273. ACPISIM_TAG,
  274. 1,
  275. 20);
  276. //
  277. // Attach our newly created FDO to the device stack
  278. //
  279. deviceextension->NextDevice = IoAttachDeviceToDeviceStack (deviceobject, Pdo);
  280. if (!deviceextension->NextDevice) {
  281. DBG_PRINT (DBG_ERROR, "Error attaching to device stack. AddDevice failed.\n");
  282. status = STATUS_UNSUCCESSFUL;
  283. goto EndAcpisimAddDevice;
  284. }
  285. //
  286. // Set up device object flags
  287. // Copy DO_POWER_PAGABLE and DO_POWER_INRUSH from next device to
  288. // play by rules, and avoid bugcheck 0x9F.
  289. //
  290. deviceobject->Flags |= (deviceextension->NextDevice->Flags & DO_POWER_PAGABLE);
  291. deviceobject->Flags |= (deviceextension->NextDevice->Flags & DO_POWER_INRUSH);
  292. //
  293. // Register our device interface, so we can be accessed from user mode
  294. //
  295. status = IoRegisterDeviceInterface (Pdo,
  296. &guid,
  297. NULL,
  298. &deviceextension->InterfaceString);
  299. if (!NT_SUCCESS (status)) {
  300. DBG_PRINT (DBG_ERROR, "Error registering device interface. Status = %lx.\n", status);
  301. goto EndAcpisimAddDevice;
  302. }
  303. AcpisimSetDevExtFlags (deviceobject, DE_FLAG_INTERFACE_REGISTERED);
  304. //
  305. // In AddDevice, we cannot determine power state because
  306. // we are not allowed to touch the hardware. Initialize
  307. // it to PowerDeviceUnspecified.
  308. //
  309. AcpisimUpdatePowerState (deviceobject, POWER_STATE_WORKING);
  310. AcpisimUpdateDevicePowerState (deviceobject, PowerDeviceUnspecified);
  311. //
  312. // We are done adding our device - clear DO_DEVICE_INITIALIZING
  313. //
  314. deviceobject->Flags &= ~DO_DEVICE_INITIALIZING;
  315. EndAcpisimAddDevice:
  316. //
  317. // Do cleanup, if necessary
  318. //
  319. if (!NT_SUCCESS (status)) {
  320. if (deviceobject) {
  321. if (deviceextension && deviceextension->NextDevice) {
  322. IoDetachDevice (deviceextension->NextDevice);
  323. }
  324. IoDeleteDevice (deviceobject);
  325. }
  326. }
  327. DBG_PRINT (DBG_INFO, "Exiting AcpisimAddDevice (%lx).\n", status);
  328. return status;
  329. }
  330. VOID
  331. AcpisimDbgPrint
  332. (
  333. ULONG DebugLevel,
  334. TCHAR *Text,
  335. ...
  336. )
  337. /*++
  338. Routine Description:
  339. Prints to the debugger if checked build, and the print level
  340. is unmasked.
  341. Arguments:
  342. DebugLevel - print level to associate message with
  343. Text - Message to print
  344. Return Value:
  345. None
  346. --*/
  347. {
  348. TCHAR textout[2000];
  349. va_list va;
  350. va_start (va, Text);
  351. vsprintf (textout, Text, va);
  352. va_end (va);
  353. #if DBG
  354. if (DebugLevel & AcpisimDebugMask) {
  355. DbgPrint ("ACPISIM:");
  356. DbgPrint (textout);
  357. }
  358. #endif
  359. }