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.

399 lines
8.4 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. acpioprg.c
  5. Abstract:
  6. This module provides support for registering ACPI operation regions
  7. Author:
  8. Stephane Plante (splante)
  9. Environment:
  10. NT Kernel Mode Driver Only
  11. --*/
  12. #include "pch.h"
  13. #ifdef ALLOC_PRAGMA
  14. #pragma alloc_text(PAGE,RegisterOperationRegionHandler)
  15. #endif
  16. NTSTATUS
  17. EXPORT
  18. InternalRawAccessOpRegionHandler (
  19. IN ULONG dwAccType,
  20. IN PFIELDUNITOBJ FieldUnit,
  21. IN POBJDATA data,
  22. IN ULONG_PTR Context,
  23. IN PFNAA CompletionHandler,
  24. IN PVOID IntContext
  25. )
  26. {
  27. NTSTATUS status;
  28. PNSOBJ HostDevice = NULL;
  29. PACPI_POWER_INFO DeviceNode;
  30. PVOID DeviceHandle;
  31. //
  32. // Get the device
  33. //
  34. status = AMLIGetFieldUnitRegionObj( FieldUnit, &HostDevice );
  35. if ( AMLIERR( status ) != AMLIERR_NONE || HostDevice == NULL) {
  36. return (STATUS_UNSUCCESSFUL);
  37. }
  38. HostDevice = NSGETPARENT(HostDevice);
  39. ACPIPrint( (
  40. ACPI_PRINT_IO,
  41. "Raw OpRegion Access on field unit object %x device %x\n",
  42. FieldUnit, HostDevice
  43. ));
  44. if ( (!HostDevice) || (NSGETOBJTYPE(HostDevice)!=OBJTYPE_DEVICE) ) {
  45. return (STATUS_UNSUCCESSFUL);
  46. }
  47. DeviceNode = OSPowerFindPowerInfo(HostDevice);
  48. if ( DeviceNode == NULL ) {
  49. return (STATUS_UNSUCCESSFUL);
  50. }
  51. DeviceHandle = DeviceNode->Context;
  52. ACPIPrint( (
  53. ACPI_PRINT_IO,
  54. "DeviceHandle %x\n",
  55. DeviceHandle
  56. ) );
  57. if ( !(POPREGIONHANDLER)Context || !(((POPREGIONHANDLER)Context)->Handler) ) {
  58. return (STATUS_UNSUCCESSFUL);
  59. }
  60. return(
  61. (((POPREGIONHANDLER)Context)->Handler)(
  62. dwAccType,
  63. FieldUnit,
  64. data,
  65. ((POPREGIONHANDLER)Context)->HandlerContext,
  66. CompletionHandler,
  67. IntContext
  68. )
  69. );
  70. }
  71. NTSTATUS
  72. EXPORT
  73. InternalOpRegionHandler (
  74. IN ULONG dwAccType,
  75. IN PNSOBJ pnsOpRegion,
  76. IN ULONG dwAddr,
  77. IN ULONG dwSize,
  78. IN PULONG pdwData,
  79. IN ULONG_PTR Context,
  80. IN PFNAA CompletionHandler,
  81. IN PVOID IntContext
  82. )
  83. {
  84. PNSOBJ HostDevice;
  85. PACPI_POWER_INFO DeviceNode;
  86. PVOID DeviceHandle;
  87. NTSTATUS status;
  88. HostDevice = NSGETPARENT(pnsOpRegion);
  89. ACPIPrint( (
  90. ACPI_PRINT_IO,
  91. "OpRegion Access on region %x device %x\n",
  92. pnsOpRegion, HostDevice
  93. ) );
  94. if ( (!HostDevice) || (NSGETOBJTYPE(HostDevice) != OBJTYPE_DEVICE) ) {
  95. return (STATUS_UNSUCCESSFUL);
  96. }
  97. DeviceNode = OSPowerFindPowerInfo (HostDevice);
  98. if ( DeviceNode == NULL ) {
  99. return (STATUS_UNSUCCESSFUL);
  100. }
  101. DeviceHandle = DeviceNode->Context;
  102. ACPIPrint( (
  103. ACPI_PRINT_IO,
  104. "DeviceHandle %x\n",
  105. DeviceHandle
  106. ) );
  107. if ( !(POPREGIONHANDLER)Context || !(((POPREGIONHANDLER)Context)->Handler) ) {
  108. return (STATUS_UNSUCCESSFUL);
  109. }
  110. status = (((POPREGIONHANDLER)Context)->Handler) (
  111. dwAccType,
  112. pnsOpRegion,
  113. dwAddr,
  114. dwSize,
  115. pdwData,
  116. ((POPREGIONHANDLER)Context)->HandlerContext,
  117. CompletionHandler,
  118. IntContext);
  119. ACPIPrint( (
  120. ACPI_PRINT_IO,
  121. "Return from OR handler - status %x\n",
  122. status
  123. ) );
  124. return (status);
  125. }
  126. //
  127. // Register to receive accesses to the specified operation region
  128. //
  129. NTSTATUS
  130. RegisterOperationRegionHandler (
  131. IN PNSOBJ RegionParent,
  132. IN ULONG AccessType,
  133. IN ULONG RegionSpace,
  134. IN PFNHND Handler,
  135. IN ULONG_PTR Context,
  136. OUT PVOID *OperationRegionObject
  137. )
  138. {
  139. NTSTATUS status;
  140. OBJDATA regArgs[2];
  141. POPREGIONHANDLER HandlerNode;
  142. PNSOBJ regObject;
  143. PAGED_CODE();
  144. *OperationRegionObject = NULL;
  145. status = STATUS_SUCCESS;
  146. //
  147. // Allocate a new Operation Region Object
  148. //
  149. HandlerNode = ExAllocatePool (NonPagedPool, sizeof(OPREGIONHANDLER));
  150. if ( !HandlerNode ) {
  151. return (STATUS_INSUFFICIENT_RESOURCES);
  152. }
  153. //
  154. // Init the Operation Region Object
  155. //
  156. HandlerNode->Handler = Handler;
  157. HandlerNode->HandlerContext = (PVOID)Context;
  158. HandlerNode->AccessType = AccessType;
  159. HandlerNode->RegionSpace = RegionSpace;
  160. //
  161. // Raw or Cooked access supported
  162. //
  163. switch ( AccessType ) {
  164. case EVTYPE_RS_COOKACCESS:
  165. status = AMLIRegEventHandler(
  166. AccessType,
  167. RegionSpace,
  168. InternalOpRegionHandler,
  169. (ULONG_PTR)HandlerNode
  170. );
  171. if ( AMLIERR(status) != AMLIERR_NONE ) {
  172. status = STATUS_UNSUCCESSFUL;
  173. }
  174. break;
  175. case EVTYPE_RS_RAWACCESS:
  176. status = AMLIRegEventHandler(
  177. AccessType,
  178. RegionSpace,
  179. InternalRawAccessOpRegionHandler,
  180. (ULONG_PTR)HandlerNode
  181. );
  182. if ( AMLIERR(status) != AMLIERR_NONE ) {
  183. status = STATUS_UNSUCCESSFUL;
  184. }
  185. break;
  186. default:
  187. status = STATUS_INVALID_PARAMETER;
  188. break;
  189. }
  190. //
  191. // Cleanup if needed
  192. //
  193. if ( !NT_SUCCESS (status) ) {
  194. ExFreePool (HandlerNode);
  195. return (status);
  196. }
  197. //
  198. // Remember the handler
  199. //
  200. *OperationRegionObject = HandlerNode;
  201. //
  202. // Can we find something?
  203. //
  204. if ( RegionParent == NULL ) {
  205. //
  206. // Do nothing
  207. //
  208. return (STATUS_SUCCESS);
  209. }
  210. //
  211. // see if there is a _REG object to run
  212. //
  213. status = AMLIGetNameSpaceObject(
  214. "_REG",
  215. RegionParent,
  216. &regObject,
  217. NSF_LOCAL_SCOPE
  218. );
  219. if ( !NT_SUCCESS(status) ) {
  220. //
  221. // Nothing to do
  222. //
  223. return (STATUS_SUCCESS);
  224. }
  225. //
  226. // Initialize the parameters
  227. //
  228. RtlZeroMemory( regArgs, sizeof(OBJDATA) * 2 );
  229. regArgs[0].dwDataType = OBJTYPE_INTDATA;
  230. regArgs[0].uipDataValue = RegionSpace;
  231. regArgs[1].dwDataType = OBJTYPE_INTDATA;
  232. regArgs[1].uipDataValue = 1;
  233. //
  234. // Eval the request. We can do this asynchronously since we don't actually
  235. // care when the registration is complete
  236. //
  237. AMLIAsyncEvalObject(
  238. regObject,
  239. NULL,
  240. 2,
  241. regArgs,
  242. NULL,
  243. NULL
  244. );
  245. //
  246. // Done
  247. //
  248. return (STATUS_SUCCESS);
  249. }
  250. //
  251. // UnRegister to receive accesses to the specified operation region
  252. //
  253. NTSTATUS
  254. UnRegisterOperationRegionHandler (
  255. IN PNSOBJ RegionParent,
  256. IN PVOID OperationRegionObject
  257. )
  258. {
  259. NTSTATUS status;
  260. OBJDATA regArgs[2];
  261. PNSOBJ regObject;
  262. POPREGIONHANDLER HandlerNode = (POPREGIONHANDLER) OperationRegionObject;
  263. PAGED_CODE();
  264. //
  265. // Is there a _REG method that we should run?
  266. //
  267. if ( RegionParent != NULL ) {
  268. status = AMLIGetNameSpaceObject(
  269. "_REG",
  270. RegionParent,
  271. &regObject,
  272. NSF_LOCAL_SCOPE
  273. );
  274. if ( NT_SUCCESS(status) ) {
  275. //
  276. // Initialize the parameters
  277. //
  278. RtlZeroMemory( regArgs, sizeof(OBJDATA) * 2 );
  279. regArgs[0].dwDataType = OBJTYPE_INTDATA;
  280. regArgs[0].uipDataValue = HandlerNode->RegionSpace;
  281. regArgs[1].dwDataType = OBJTYPE_INTDATA;
  282. regArgs[1].uipDataValue = 0;
  283. //
  284. // Eval the request. We don't care what it returns, but we must do
  285. // it synchronously
  286. //
  287. AMLIEvalNameSpaceObject(
  288. regObject,
  289. NULL,
  290. 2,
  291. regArgs
  292. );
  293. }
  294. }
  295. //
  296. // Call interpreter with null handler to remove the handler for this access/region
  297. //
  298. status = AMLIRegEventHandler(
  299. HandlerNode->AccessType,
  300. HandlerNode->RegionSpace,
  301. NULL,
  302. 0
  303. );
  304. if ( AMLIERR(status) != AMLIERR_NONE ) {
  305. return (STATUS_UNSUCCESSFUL);
  306. }
  307. //
  308. // Cleanup
  309. //
  310. ExFreePool (HandlerNode);
  311. return (STATUS_SUCCESS);
  312. }