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.

432 lines
11 KiB

  1. #include "spsim.h"
  2. #include "spsimioct.h"
  3. NTSTATUS
  4. SpSimCreateStaOpRegion(
  5. IN PSPSIM_EXTENSION SpSim
  6. )
  7. /*++
  8. Description:
  9. Retrieves information to construct the STA array that tells us
  10. what devices we control the _STA on
  11. Arguments:
  12. SpSim - device extension
  13. Return Value:
  14. NTSTATUS
  15. --*/
  16. {
  17. NTSTATUS status;
  18. ACPI_EVAL_INPUT_BUFFER input;
  19. PACPI_EVAL_OUTPUT_BUFFER output = NULL;
  20. ULONG i;
  21. PACPI_METHOD_ARGUMENT argument;
  22. //
  23. // Allocate a buffer big enough for all possible slots
  24. //
  25. ULONG outputSize = sizeof(ACPI_EVAL_OUTPUT_BUFFER);
  26. PAGED_CODE();
  27. output = ExAllocatePool(PagedPool, outputSize);
  28. if (!output) {
  29. return STATUS_INSUFFICIENT_RESOURCES;
  30. }
  31. //
  32. // Send a IOCTL to ACPI to request evaluate the
  33. // SPSIM_STA_NAMES_METHOD under this object if present.
  34. //
  35. RtlZeroMemory(&input, sizeof(ACPI_EVAL_INPUT_BUFFER));
  36. input.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;
  37. input.MethodNameAsUlong = SPSIM_STA_NAMES_METHOD;
  38. status = SpSimSendIoctl(SpSim->PhysicalDeviceObject,
  39. IOCTL_ACPI_EVAL_METHOD,
  40. &input,
  41. sizeof(ACPI_EVAL_INPUT_BUFFER),
  42. output,
  43. outputSize
  44. );
  45. if (status == STATUS_BUFFER_OVERFLOW) {
  46. outputSize = output->Length;
  47. ExFreePool(output);
  48. output = ExAllocatePool(PagedPool, outputSize);
  49. if (!output) {
  50. return STATUS_INSUFFICIENT_RESOURCES;
  51. }
  52. status = SpSimSendIoctl(SpSim->PhysicalDeviceObject,
  53. IOCTL_ACPI_EVAL_METHOD,
  54. &input,
  55. sizeof(ACPI_EVAL_INPUT_BUFFER),
  56. output,
  57. outputSize
  58. );
  59. }
  60. if (NT_SUCCESS(status)) {
  61. argument = output->Argument;
  62. for (i = 0; i < output->Count; i++) {
  63. if (argument->Type != ACPI_METHOD_ARGUMENT_STRING) {
  64. status = STATUS_INVALID_PARAMETER;
  65. break;
  66. }
  67. argument = ACPI_METHOD_NEXT_ARGUMENT(argument);
  68. }
  69. SpSim->StaOpRegionValues = ExAllocatePool(NonPagedPool,
  70. sizeof(UCHAR) * output->Count);
  71. if (SpSim->StaOpRegionValues == NULL) {
  72. status = STATUS_INSUFFICIENT_RESOURCES;
  73. } else {
  74. SpSim->StaNames = output;
  75. SpSim->StaCount = output->Count;
  76. RtlZeroMemory(SpSim->StaOpRegionValues,
  77. sizeof(UCHAR) * SpSim->StaCount);
  78. }
  79. }
  80. if (!NT_SUCCESS(status)) {
  81. ExFreePool(output);
  82. SpSim->StaOpRegionValues = NULL;
  83. SpSim->StaNames = NULL;
  84. SpSim->StaCount = 0;
  85. }
  86. return status;
  87. }
  88. VOID
  89. SpSimDeleteStaOpRegion(
  90. IN PSPSIM_EXTENSION SpSim
  91. )
  92. {
  93. if (SpSim->StaNames) {
  94. ExFreePool(SpSim->StaNames);
  95. SpSim->StaNames = NULL;
  96. }
  97. if (SpSim->StaOpRegionValues) {
  98. ExFreePool(SpSim->StaOpRegionValues);
  99. SpSim->StaOpRegionValues = NULL;
  100. }
  101. }
  102. NTSTATUS
  103. SpSimGetDeviceName(
  104. PSPSIM_EXTENSION SpSim,
  105. PIRP Irp,
  106. PIO_STACK_LOCATION IrpStack
  107. )
  108. {
  109. PSPSIM_DEVICE_NAME name;
  110. PACPI_METHOD_ARGUMENT argument;
  111. PUCHAR source;
  112. PWCHAR dest;
  113. ULONG remainingBuffer, i, nameSize;
  114. if (Irp->AssociatedIrp.SystemBuffer == NULL) {
  115. return STATUS_INVALID_PARAMETER;
  116. }
  117. if (SpSim->StaNames == NULL) {
  118. return STATUS_INVALID_PARAMETER;
  119. }
  120. name = Irp->AssociatedIrp.SystemBuffer;
  121. if (name->Device >= SpSim->StaCount) {
  122. return STATUS_INVALID_PARAMETER;
  123. }
  124. if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength <
  125. sizeof(SPSIM_DEVICE_NAME)) {
  126. return STATUS_INVALID_PARAMETER;
  127. }
  128. argument = SpSim->StaNames->Argument;
  129. i = 0;
  130. while (i != name->Device) {
  131. argument = ACPI_METHOD_NEXT_ARGUMENT(argument);
  132. i++;
  133. }
  134. nameSize = argument->DataLength * sizeof(WCHAR);
  135. name->DeviceNameLength = argument->DataLength;
  136. if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < (sizeof(SPSIM_DEVICE_NAME) + (nameSize - sizeof(WCHAR)))) {
  137. Irp->IoStatus.Information = sizeof(SPSIM_DEVICE_NAME);
  138. return STATUS_BUFFER_OVERFLOW;
  139. }
  140. source = argument->Data;
  141. dest = name->DeviceName;
  142. while(*source) {
  143. *dest++ = (WCHAR) *source++;
  144. }
  145. *dest = UNICODE_NULL;
  146. Irp->IoStatus.Information = sizeof(SPSIM_DEVICE_NAME) - sizeof(WCHAR) +
  147. nameSize;
  148. return STATUS_SUCCESS;
  149. }
  150. NTSTATUS
  151. SpSimGetManagedDevicesIoctl(
  152. PSPSIM_EXTENSION SpSim,
  153. PIRP Irp,
  154. PIO_STACK_LOCATION IrpStack
  155. )
  156. {
  157. PACPI_METHOD_ARGUMENT argument;
  158. PSPSIM_MANAGED_DEVICES managed;
  159. ULONG i, outputSize;
  160. PUCHAR current;
  161. NTSTATUS status;
  162. if (Irp->AssociatedIrp.SystemBuffer == NULL) {
  163. return STATUS_INVALID_PARAMETER;
  164. }
  165. if (SpSim->StaOpRegionValues == NULL) {
  166. return STATUS_INVALID_PARAMETER;
  167. }
  168. if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(SPSIM_MANAGED_DEVICES)) {
  169. return STATUS_INVALID_PARAMETER;
  170. }
  171. managed = Irp->AssociatedIrp.SystemBuffer;
  172. managed->Count = SpSim->StaCount;
  173. outputSize = (sizeof(SPSIM_MANAGED_DEVICES) - sizeof(UCHAR)) +
  174. SpSim->StaCount * sizeof(UCHAR);
  175. if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < outputSize) {
  176. Irp->IoStatus.Information = sizeof(SPSIM_MANAGED_DEVICES);
  177. return STATUS_BUFFER_OVERFLOW;
  178. }
  179. RtlCopyMemory(managed->StaValues,
  180. SpSim->StaOpRegionValues,
  181. SpSim->StaCount);
  182. Irp->IoStatus.Information = outputSize;
  183. return STATUS_SUCCESS;
  184. }
  185. NTSTATUS
  186. SpSimStaOpRegionReadWrite(
  187. PSPSIM_EXTENSION SpSim,
  188. ULONG AccessType,
  189. ULONG Offset,
  190. ULONG Size,
  191. PUCHAR Data
  192. )
  193. {
  194. ULONG i;
  195. PUCHAR current;
  196. if (SpSim->StaOpRegionValues == NULL) {
  197. return STATUS_INVALID_PARAMETER;
  198. }
  199. if (Offset >= SpSim->StaCount) {
  200. return STATUS_INVALID_PARAMETER;
  201. }
  202. if (Offset + Size > SpSim->StaCount) {
  203. return STATUS_INVALID_PARAMETER;
  204. }
  205. ASSERT(Offset < SpSim->StaCount);
  206. current = SpSim->StaOpRegionValues + Offset;
  207. if (AccessType & ACPI_OPREGION_WRITE) {
  208. for (i = 0 ; i < Size; i++) {
  209. *current++ = *Data++;
  210. }
  211. } else {
  212. for (i = 0 ; i < Size; i++) {
  213. *Data++ = *current++;
  214. }
  215. }
  216. return STATUS_SUCCESS;
  217. }
  218. NTSTATUS
  219. EXPORT
  220. SpSimStaOpRegionHandler (
  221. ULONG AccessType,
  222. PVOID OpRegion,
  223. ULONG Address,
  224. ULONG Size,
  225. PULONG Data,
  226. ULONG_PTR Context,
  227. PACPI_OPREGION_CALLBACK CompletionHandler,
  228. PVOID CompletionContext
  229. )
  230. /*++
  231. Routine Description:
  232. This routine handles requests to service the
  233. SPSIM operation region contained within this driver
  234. Arguments:
  235. AccessType - Read or Write data
  236. OpRegion - Operation region object
  237. Address - Address within the EC address space
  238. Size - Number of bytes to transfer
  239. Data - Data buffer to transfer to/from
  240. Context - SpSim
  241. CompletionHandler - AMLI handler to call when operation is complete
  242. CompletionContext - Context to pass to the AMLI handler
  243. Return Value:
  244. Status
  245. --*/
  246. {
  247. NTSTATUS status;
  248. status = SpSimStaOpRegionReadWrite((PSPSIM_EXTENSION) Context,
  249. AccessType,
  250. Address,
  251. Size,
  252. (PUCHAR)Data);
  253. return status;
  254. }
  255. NTSTATUS
  256. SpSimInstallStaOpRegionHandler(
  257. IN OUT PSPSIM_EXTENSION SpSim
  258. )
  259. /*++
  260. Routine Description:
  261. This calls the ACPI driver to install itself as the op region
  262. handler for the STA region. It also allocates the memory for the
  263. opregion itself.
  264. Arguments:
  265. pSpSimData - Pointer to the SpSim extension
  266. Return Value:
  267. Status
  268. --*/
  269. {
  270. NTSTATUS status;
  271. status=RegisterOpRegionHandler (
  272. SpSim->AttachedDevice,
  273. ACPI_OPREGION_ACCESS_AS_COOKED,
  274. STA_OPREGION,
  275. SpSimStaOpRegionHandler,
  276. SpSim,
  277. 0,
  278. &SpSim->StaOpRegion
  279. );
  280. //
  281. // Check the status code
  282. //
  283. if(!NT_SUCCESS(status)) {
  284. SpSim->StaOpRegion = NULL;
  285. DbgPrint("Not successful in installing:=%x\n", status);
  286. return status;
  287. }
  288. // XXXX
  289. return STATUS_SUCCESS;
  290. }
  291. NTSTATUS
  292. SpSimRemoveStaOpRegionHandler (
  293. IN OUT PSPSIM_EXTENSION SpSim
  294. )
  295. /*++
  296. Routine Description:
  297. Uninstalls itself as the opregion handler.
  298. Arguments:
  299. SpSim - Pointer to the SpSim extension
  300. Return Value:
  301. Status
  302. --*/
  303. {
  304. NTSTATUS status;
  305. PIRP irp;
  306. if (SpSim->StaOpRegion != NULL) {
  307. status = DeRegisterOpRegionHandler (
  308. SpSim->AttachedDevice,
  309. SpSim->StaOpRegion
  310. );
  311. SpSim->StaOpRegion = NULL;
  312. } else {
  313. status = STATUS_SUCCESS;
  314. }
  315. return status;
  316. }
  317. NTSTATUS
  318. SpSimAccessStaIoctl(
  319. PSPSIM_EXTENSION SpSim,
  320. PIRP Irp,
  321. PIO_STACK_LOCATION IrpStack
  322. )
  323. {
  324. PSPSIM_ACCESS_STA access;
  325. NTSTATUS status;
  326. ULONG accessType;
  327. if (Irp->AssociatedIrp.SystemBuffer == NULL) {
  328. return STATUS_INVALID_PARAMETER;
  329. }
  330. if (SpSim->StaNames == NULL) {
  331. return STATUS_INVALID_PARAMETER;
  332. }
  333. if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(SPSIM_ACCESS_STA)) {
  334. return STATUS_INVALID_PARAMETER;
  335. }
  336. access = Irp->AssociatedIrp.SystemBuffer;
  337. accessType = access->WriteOperation ? ACPI_OPREGION_WRITE :
  338. ACPI_OPREGION_READ;
  339. status = SpSimStaOpRegionReadWrite(SpSim,
  340. accessType,
  341. access->Device,
  342. sizeof(UCHAR),
  343. &access->StaValue);
  344. if (NT_SUCCESS(status)) {
  345. Irp->IoStatus.Information = sizeof(SPSIM_ACCESS_STA);
  346. } else {
  347. Irp->IoStatus.Information = 0;
  348. }
  349. return status;
  350. }