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.

466 lines
12 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation All Rights Reserved
  3. Module Name:
  4. memory.c
  5. Abstract:
  6. This module controls access to the simulated memory space of the SHPC.
  7. Environment:
  8. Kernel Mode
  9. Revision History:
  10. Davis Walker (dwalker) Sept 8 2000
  11. --*/
  12. #include "hpsp.h"
  13. NTSTATUS
  14. HpsInitHBRB(
  15. IN PHPS_DEVICE_EXTENSION Extension
  16. )
  17. {
  18. NTSTATUS status;
  19. ACPI_EVAL_INPUT_BUFFER input;
  20. PACPI_EVAL_OUTPUT_BUFFER output = NULL;
  21. ULONG count;
  22. PACPI_METHOD_ARGUMENT argument;
  23. ULONG outputSize = sizeof(ACPI_EVAL_OUTPUT_BUFFER) + sizeof(ACPI_METHOD_ARGUMENT) * HBRB_PACKAGE_COUNT;
  24. PHYSICAL_ADDRESS HBRB;
  25. PHBRB_HEADER HBRBHeader;
  26. PHBRB_CAPABILITIES_HEADER HBRBCapHeader;
  27. PAGED_CODE();
  28. output = ExAllocatePool(PagedPool | POOL_COLD_ALLOCATION, outputSize);
  29. if (!output) {
  30. status = STATUS_INSUFFICIENT_RESOURCES;
  31. goto cleanup;
  32. }
  33. RtlZeroMemory(&input, sizeof(ACPI_EVAL_INPUT_BUFFER));
  34. RtlZeroMemory(output, outputSize);
  35. //
  36. // Send a IOCTL to ACPI to request it to run the HBRB method on this device
  37. // if the method it is present
  38. //
  39. input.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;
  40. input.MethodNameAsUlong = (ULONG)'BRBH';
  41. //
  42. // HpsSendIoctl deals with sending this from the top of the stack.
  43. //
  44. status = HpsSendIoctl(Extension->Self,
  45. IOCTL_ACPI_EVAL_METHOD,
  46. &input,
  47. sizeof(ACPI_EVAL_INPUT_BUFFER),
  48. output,
  49. outputSize
  50. );
  51. if (!NT_SUCCESS(status)) {
  52. goto cleanup;
  53. }
  54. //
  55. // Check they are all integers and in the right bounds
  56. //
  57. ASSERT(output->Count <= HBRB_PACKAGE_COUNT);
  58. if (output->Argument[0].Type != ACPI_METHOD_ARGUMENT_INTEGER) {
  59. status = STATUS_UNSUCCESSFUL;
  60. goto cleanup;
  61. }
  62. HBRB.LowPart = output->Argument[0].Argument;
  63. if (output->Count > 1) {
  64. if (output->Argument[1].Type != ACPI_METHOD_ARGUMENT_INTEGER) {
  65. status = STATUS_UNSUCCESSFUL;
  66. goto cleanup;
  67. }
  68. HBRB.HighPart = output->Argument[1].Argument;
  69. }
  70. Extension->HBRBOffset = (PUCHAR)HBRB.QuadPart;
  71. Extension->HBRBLength = sizeof(HBRB_HEADER) + sizeof(HBRB_CAPABILITIES_HEADER) + sizeof(SHPC_REGISTER_SET);
  72. Extension->HBRBRegisterSetOffset = sizeof(HBRB_HEADER) + sizeof(HBRB_CAPABILITIES_HEADER);
  73. Extension->HBRB = ExAllocatePool(NonPagedPool,sizeof(HBRB_HEADER) +
  74. sizeof(HBRB_CAPABILITIES_HEADER) +
  75. sizeof(SHPC_REGISTER_SET)
  76. );
  77. if (!Extension->HBRB) {
  78. goto cleanup;
  79. }
  80. HBRBHeader = (PHBRB_HEADER)Extension->HBRB;
  81. HBRBHeader->BusNumber = 0;
  82. HBRBHeader->VendorID = 0x9999;
  83. HBRBHeader->DeviceID = 0x0123;
  84. HBRBHeader->SubSystemID = 0x1234;
  85. HBRBHeader->SubVendorID = 0x9999;
  86. HBRBHeader->ProgIF = 1;
  87. HBRBHeader->RevisionID = 1;
  88. HBRBHeader->HBRBVersion = 1;
  89. HBRBHeader->CapabilitiesPtr = sizeof(HBRB_HEADER);
  90. HBRBHeader->Size = sizeof(HBRB_HEADER) + sizeof(HBRB_CAPABILITIES_HEADER) + sizeof(SHPC_REGISTER_SET);
  91. HBRBCapHeader = (PHBRB_CAPABILITIES_HEADER)((PUCHAR)HBRBHeader + sizeof(HBRB_HEADER));
  92. HBRBCapHeader->CapabilityID = 0xC;
  93. HBRBCapHeader->Next = 0x0;
  94. status = HpsInitRegisters(Extension);
  95. if (!NT_SUCCESS(status)) {
  96. goto cleanup;
  97. }
  98. RtlCopyMemory((PUCHAR)HBRBCapHeader + sizeof(HBRB_CAPABILITIES_HEADER),
  99. &Extension->RegisterSet,
  100. sizeof(SHPC_REGISTER_SET)
  101. );
  102. cleanup:
  103. if (output) {
  104. ExFreePool(output);
  105. }
  106. return status;
  107. }
  108. NTSTATUS
  109. HpsGetHBRBHwInit(
  110. IN PHPS_DEVICE_EXTENSION DeviceExtension
  111. )
  112. {
  113. NTSTATUS status;
  114. ACPI_EVAL_INPUT_BUFFER input;
  115. PACPI_EVAL_OUTPUT_BUFFER output = NULL;
  116. ULONG count;
  117. PACPI_METHOD_ARGUMENT argument;
  118. ULONG outputSize = sizeof(ACPI_EVAL_OUTPUT_BUFFER) + sizeof(ACPI_METHOD_ARGUMENT) + sizeof(HPS_HWINIT_DESCRIPTOR);
  119. PHYSICAL_ADDRESS HBRB;
  120. PHBRB_HEADER HBRBHeader;
  121. PHBRB_CAPABILITIES_HEADER HBRBCapHeader;
  122. PAGED_CODE();
  123. output = ExAllocatePool(PagedPool | POOL_COLD_ALLOCATION, outputSize);
  124. if (!output) {
  125. status = STATUS_INSUFFICIENT_RESOURCES;
  126. goto cleanup;
  127. }
  128. RtlZeroMemory(&input, sizeof(ACPI_EVAL_INPUT_BUFFER));
  129. RtlZeroMemory(output, outputSize);
  130. //
  131. // Send a IOCTL to ACPI to request it to run the HBRB method on this device
  132. // if the method it is present
  133. //
  134. input.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;
  135. input.MethodNameAsUlong = (ULONG)'IHBH';
  136. //
  137. // HpsSendIoctl deals with sending this from the top of the stack.
  138. //
  139. status = HpsSendIoctl(DeviceExtension->Self,
  140. IOCTL_ACPI_EVAL_METHOD,
  141. &input,
  142. sizeof(ACPI_EVAL_INPUT_BUFFER),
  143. output,
  144. outputSize
  145. );
  146. if (!NT_SUCCESS(status)) {
  147. goto cleanup;
  148. }
  149. //
  150. // Check they are all integers and in the right bounds
  151. //
  152. ASSERT(output->Count == 1);
  153. if ((output->Argument[0].Type != ACPI_METHOD_ARGUMENT_BUFFER) ||
  154. (output->Argument[0].DataLength != sizeof(HPS_HWINIT_DESCRIPTOR))) {
  155. status = STATUS_UNSUCCESSFUL;
  156. goto cleanup;
  157. }
  158. RtlCopyMemory(&DeviceExtension->HwInitData,
  159. output->Argument[0].Data,
  160. output->Argument[0].DataLength
  161. );
  162. cleanup:
  163. if (output) {
  164. ExFreePool(output);
  165. }
  166. return status;
  167. }
  168. NTSTATUS
  169. HpsSendIoctl(
  170. IN PDEVICE_OBJECT Device,
  171. IN ULONG IoctlCode,
  172. IN PVOID InputBuffer OPTIONAL,
  173. IN ULONG InputBufferLength,
  174. IN PVOID OutputBuffer OPTIONAL,
  175. IN ULONG OutputBufferLength
  176. )
  177. /*++
  178. Description:
  179. Builds and send an IOCTL to a device and return the results
  180. Arguments:
  181. Device - a device on the device stack to receive the IOCTL - the
  182. irp is always sent to the top of the stack
  183. IoctlCode - the IOCTL to run
  184. InputBuffer - arguments to the IOCTL
  185. InputBufferLength - length in bytes of the InputBuffer
  186. OutputBuffer - data returned by the IOCTL
  187. OnputBufferLength - the size in bytes of the OutputBuffer
  188. Return Value:
  189. Status
  190. --*/
  191. {
  192. NTSTATUS status;
  193. IO_STATUS_BLOCK ioStatus;
  194. KEVENT event;
  195. PIRP irp;
  196. PDEVICE_OBJECT targetDevice = NULL;
  197. PAGED_CODE();
  198. KeInitializeEvent(&event, SynchronizationEvent, FALSE);
  199. //
  200. // Get the top of the stack to send the IRP to
  201. //
  202. targetDevice = IoGetAttachedDeviceReference(Device);
  203. if (!targetDevice) {
  204. status = STATUS_INVALID_PARAMETER;
  205. goto exit;
  206. }
  207. //
  208. // Get Io to build the IRP for us
  209. //
  210. irp = IoBuildDeviceIoControlRequest(IoctlCode,
  211. targetDevice,
  212. InputBuffer,
  213. InputBufferLength,
  214. OutputBuffer,
  215. OutputBufferLength,
  216. FALSE, // InternalDeviceIoControl
  217. &event,
  218. &ioStatus
  219. );
  220. if (!irp) {
  221. status = STATUS_INSUFFICIENT_RESOURCES;
  222. goto exit;
  223. }
  224. //
  225. // Send the IRP and wait for it to complete
  226. //
  227. status = IoCallDriver(targetDevice, irp);
  228. if (status == STATUS_PENDING) {
  229. KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
  230. status = ioStatus.Status;
  231. }
  232. exit:
  233. if (targetDevice) {
  234. ObDereferenceObject(targetDevice);
  235. }
  236. return status;
  237. }
  238. VOID
  239. HpsMemoryInterfaceReference(
  240. IN PVOID Context
  241. )
  242. {
  243. PHPS_DEVICE_EXTENSION Extension = (PHPS_DEVICE_EXTENSION)Context;
  244. if (InterlockedExchangeAdd(&Extension->MemoryInterfaceCount,1) == 0) {
  245. //
  246. // This is the first increment. Put this device extension on the
  247. // list of device extensions.
  248. //
  249. InsertHeadList(&HpsDeviceExtensions,&Extension->ListEntry);
  250. }
  251. }
  252. VOID
  253. HpsMemoryInterfaceDereference(
  254. IN PVOID Context
  255. )
  256. {
  257. PHPS_DEVICE_EXTENSION Extension = (PHPS_DEVICE_EXTENSION)Context;
  258. LONG decrementedValue;
  259. decrementedValue = InterlockedDecrement(&Extension->MemoryInterfaceCount);
  260. ASSERT(decrementedValue >= 0);
  261. if (decrementedValue == 0) {
  262. //
  263. // This is the final decrement. Remove the device extension from the list
  264. //
  265. RemoveEntryList(&Extension->ListEntry);
  266. }
  267. }
  268. VOID
  269. HpsReadRegister(
  270. IN PUCHAR Register,
  271. IN PUCHAR Buffer,
  272. IN ULONG Length
  273. )
  274. {
  275. PHPS_DEVICE_EXTENSION extension;
  276. ULONG offset;
  277. extension = HpsFindExtensionForHbrb(Register,Length);
  278. offset = (ULONG)(Register - extension->HBRBOffset);
  279. if ((offset < extension->HBRBLength) &&
  280. ((offset+Length) <= extension->HBRBLength)) {
  281. RtlCopyMemory(Buffer,(PUCHAR)extension->HBRB + offset,Length);
  282. }
  283. }
  284. VOID
  285. HpsWriteRegister(
  286. IN PUCHAR Register,
  287. IN PUCHAR Buffer,
  288. IN ULONG Length
  289. )
  290. {
  291. PHPS_DEVICE_EXTENSION extension;
  292. ULONG hbrbOffset, shpcOffset, shpcLength, bufferOffset;
  293. ULONG registerNum, registerOffset, registerLength, registerData;
  294. KIRQL irql;
  295. extension = HpsFindExtensionForHbrb(Register,Length);
  296. HpsLockRegisterSet(extension,
  297. &irql
  298. );
  299. hbrbOffset = (ULONG)(Register - extension->HBRBOffset);
  300. if ((hbrbOffset < extension->HBRBLength) &&
  301. ((hbrbOffset+Length) <= extension->HBRBLength)) {
  302. RtlCopyMemory((PUCHAR)extension->HBRB + hbrbOffset,Buffer,Length);
  303. }
  304. if ((hbrbOffset >= extension->HBRBRegisterSetOffset) &&
  305. ((hbrbOffset + Length) < (extension->HBRBRegisterSetOffset + sizeof(SHPC_REGISTER_SET)))) {
  306. //
  307. // The write is to the SHPC register set.
  308. //
  309. shpcOffset = hbrbOffset - extension->HBRBRegisterSetOffset;
  310. shpcLength = Length;
  311. bufferOffset = 0;
  312. while (bufferOffset < Length) {
  313. registerNum = shpcOffset / sizeof(ULONG);
  314. registerOffset = shpcOffset - (registerNum * sizeof(ULONG));
  315. registerLength = min(shpcLength,sizeof(ULONG)-registerOffset);
  316. registerData = *(PULONG)((PUCHAR)Buffer + bufferOffset);
  317. registerData <<= (registerOffset*8);
  318. RegisterWriteCommands[registerNum](extension,
  319. registerNum,
  320. &registerData,
  321. HPS_ULONG_WRITE_MASK(registerOffset,registerLength)
  322. );
  323. bufferOffset += registerLength;
  324. shpcOffset += registerLength;
  325. shpcLength -= registerLength;
  326. }
  327. }
  328. RtlCopyMemory((PUCHAR)extension->HBRB + extension->HBRBRegisterSetOffset,
  329. &extension->RegisterSet,
  330. sizeof(SHPC_REGISTER_SET)
  331. );
  332. HpsUnlockRegisterSet(extension,
  333. irql
  334. );
  335. }
  336. PHPS_DEVICE_EXTENSION
  337. HpsFindExtensionForHbrb(
  338. IN PUCHAR Register,
  339. IN ULONG Length
  340. )
  341. {
  342. PHPS_DEVICE_EXTENSION currentExtension;
  343. FOR_ALL_IN_LIST(HPS_DEVICE_EXTENSION,&HpsDeviceExtensions,currentExtension) {
  344. if (IS_SUBSET(Register,Length,currentExtension->HBRBOffset,currentExtension->HBRBLength)) {
  345. return currentExtension;
  346. }
  347. }
  348. return NULL;
  349. }