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.

1835 lines
51 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. xxacpi.c
  5. Abstract:
  6. Implements various ACPI utility functions.
  7. Author:
  8. Jake Oshins (jakeo) 12-Feb-1997
  9. Environment:
  10. Kernel mode only.
  11. Revision History:
  12. Todd Kjos (HP) (v-tkjos) 1-Jun-1998 : Added IA64 support
  13. --*/
  14. #include "halp.h"
  15. #include "acpitabl.h"
  16. #include "xxacpi.h"
  17. #include "pci.h"
  18. //#define DUMP_FADT
  19. VOID
  20. HalAcpiTimerCarry(
  21. VOID
  22. );
  23. VOID
  24. HalaAcpiTimerInit(
  25. #if defined(ACPI64)
  26. ULONG_PTR TimerPort,
  27. #else
  28. ULONG TimerPort,
  29. #endif
  30. BOOLEAN TimerValExt
  31. );
  32. ULONG
  33. HaliAcpiQueryFlags(
  34. VOID
  35. );
  36. VOID
  37. HaliAcpiTimerInit(
  38. // *** TBD should be ULONG_PTR
  39. ULONG TimerPort OPTIONAL,
  40. IN BOOLEAN TimerValExt
  41. );
  42. VOID
  43. HaliAcpiMachineStateInit(
  44. IN PPROCESSOR_INIT ProcInit,
  45. IN PHAL_SLEEP_VAL SleepValues,
  46. OUT PULONG PicVal
  47. );
  48. BOOLEAN
  49. FASTCALL
  50. HalAcpiC1Idle(
  51. OUT PPROCESSOR_IDLE_TIMES IdleTimes
  52. );
  53. BOOLEAN
  54. FASTCALL
  55. HalAcpiC2Idle(
  56. OUT PPROCESSOR_IDLE_TIMES IdleTimes
  57. );
  58. BOOLEAN
  59. FASTCALL
  60. HalAcpiC3ArbdisIdle(
  61. OUT PPROCESSOR_IDLE_TIMES IdleTimes
  62. );
  63. BOOLEAN
  64. FASTCALL
  65. HalAcpiC3WbinvdIdle(
  66. OUT PPROCESSOR_IDLE_TIMES IdleTimes
  67. );
  68. VOID
  69. FASTCALL
  70. HalProcessorThrottle(
  71. IN UCHAR Throttle
  72. );
  73. NTSTATUS
  74. HaliSetWakeAlarm (
  75. IN ULONGLONG WakeSystemTime,
  76. IN PTIME_FIELDS WakeTimeFields OPTIONAL
  77. );
  78. VOID
  79. HaliSetWakeEnable(
  80. IN BOOLEAN Enable
  81. );
  82. VOID
  83. HalpSetInterruptControllerWakeupState(
  84. ULONG Context
  85. );
  86. PVOID
  87. HalpRemapVirtualAddress(
  88. IN PVOID VirtualAddress,
  89. IN PVOID PhysicalAddress,
  90. IN BOOLEAN WriteThrough
  91. );
  92. ULONG
  93. HaliPciInterfaceReadConfig(
  94. IN PVOID Context,
  95. IN UCHAR BusOffset,
  96. IN ULONG Slot,
  97. IN PVOID Buffer,
  98. IN ULONG Offset,
  99. IN ULONG Length
  100. );
  101. ULONG
  102. HaliPciInterfaceWriteConfig(
  103. IN PVOID Context,
  104. IN UCHAR BusOffset,
  105. IN ULONG Slot,
  106. IN PVOID Buffer,
  107. IN ULONG Offset,
  108. IN ULONG Length
  109. );
  110. VOID
  111. HalpNumaInitializeStaticConfiguration(
  112. IN PLOADER_PARAMETER_BLOCK
  113. );
  114. //
  115. // HAL Hack flags
  116. //
  117. typedef enum {
  118. HalHackAddFakeSleepHandlersS1 = 1,
  119. HalHackAddFakeSleepHandlersS2 = 2,
  120. HalHackAddFakeSleepHandlersS3 = 4
  121. } HALHACKFLAGS;
  122. extern HALHACKFLAGS HalpHackFlags = 0;
  123. //
  124. // Externs
  125. //
  126. extern ULONG HalpAcpiFlags;
  127. extern PHYSICAL_ADDRESS HalpAcpiRsdt;
  128. extern SLEEP_STATE_CONTEXT HalpShutdownContext;
  129. extern ULONG HalpPicVectorRedirect[];
  130. //
  131. // Globals
  132. //
  133. ULONG HalpInvalidAcpiTable;
  134. PRSDT HalpAcpiRsdtVA;
  135. PXSDT HalpAcpiXsdtVA;
  136. PIPPT_TABLE HalpPlatformPropertiesTable;
  137. ULONG HalpPlatformPropertiesEfiFlags = 0; // IPPT Flags coming from EFI MDs
  138. //
  139. // This is the dispatch table used by the ACPI driver
  140. //
  141. HAL_ACPI_DISPATCH_TABLE HalAcpiDispatchTable;
  142. PPM_DISPATCH_TABLE PmAcpiDispatchTable = NULL;
  143. NTSTATUS
  144. HalpQueryAcpiResourceRequirements(
  145. IN PIO_RESOURCE_REQUIREMENTS_LIST *Requirements
  146. );
  147. NTSTATUS
  148. HalpBuildAcpiResourceList(
  149. OUT PIO_RESOURCE_REQUIREMENTS_LIST List
  150. );
  151. NTSTATUS
  152. HalpAcpiDetectResourceListSize(
  153. OUT PULONG ResourceListSize
  154. );
  155. VOID
  156. HalpRestoreInterruptControllerState(
  157. VOID
  158. );
  159. ULONG
  160. HalpGetPCIData (
  161. IN PBUS_HANDLER BusHandler,
  162. IN PBUS_HANDLER RootHandler,
  163. IN PCI_SLOT_NUMBER SlotNumber,
  164. IN PVOID Buffer,
  165. IN ULONG Offset,
  166. IN ULONG Length
  167. );
  168. VOID
  169. HalpReadRegistryAndApplyHacks (
  170. VOID
  171. );
  172. #define LOW_MEMORY 0x000100000
  173. #define MAX(a, b) \
  174. ((a) > (b) ? (a) : (b))
  175. #define MIN(a, b) \
  176. ((a) < (b) ? (a) : (b))
  177. // ADRIAO 01/12/98 - We no longer having the HAL declare the IO ports
  178. // specified in the FADT. These will be declared in a future
  179. // defined PNP0Cxx node (for new, in PNP0C02). This is done
  180. // because we cannot know at the hal level what bus the ACPI
  181. // FADT resources refer to. We can only the translated resource info.
  182. // Hence....
  183. #define DECLARE_FADT_RESOURCES_AT_ROOT 0
  184. #ifdef ALLOC_PRAGMA
  185. #pragma alloc_text(INIT, HalpGetAcpiTablePhase0)
  186. #pragma alloc_text(INIT, HalpSetupAcpiPhase0)
  187. #pragma alloc_text(PAGE, HaliInitPowerManagement)
  188. #pragma alloc_text(PAGE, HalpQueryAcpiResourceRequirements)
  189. #pragma alloc_text(PAGE, HalpBuildAcpiResourceList)
  190. #pragma alloc_text(PAGE, HalpGetCrossPartitionIpiInterface)
  191. #pragma alloc_text(PAGE, HalpAcpiDetectResourceListSize)
  192. #pragma alloc_text(PAGE, HalpReadRegistryAndApplyHacks)
  193. #pragma alloc_text(PAGE, HaliAcpiTimerInit)
  194. #pragma alloc_text(PAGE, HaliAcpiMachineStateInit)
  195. #pragma alloc_text(PAGE, HaliAcpiQueryFlags)
  196. #pragma alloc_text(PAGE, HaliSetWakeEnable)
  197. #endif
  198. PVOID
  199. HalpGetAcpiTablePhase0(
  200. IN PLOADER_PARAMETER_BLOCK LoaderBlock,
  201. IN ULONG Signature
  202. )
  203. /*++
  204. Routine Description:
  205. This function returns a pointer to the ACPI table that is
  206. identified by Signature.
  207. Arguments:
  208. Signature - A four byte value that identifies the ACPI table
  209. Return Value:
  210. Pointer to a copy of the table
  211. --*/
  212. {
  213. PRSDT rsdt;
  214. PXSDT xsdt;
  215. ULONG entry, rsdtEntries;
  216. PVOID table;
  217. PHYSICAL_ADDRESS physicalAddr;
  218. PDESCRIPTION_HEADER header;
  219. NTSTATUS status;
  220. ULONG lengthInPages;
  221. ULONG offset;
  222. //
  223. // unless we get the exceptional case where the platform identifies that
  224. // ACPI tables must be explicitly mapped cached, we map the ACPI tables
  225. // noncached. We are relying on the first mapping of this range to have
  226. // the "correct" caching flag, as that is the cachability attribute that
  227. // all subsequent mappings of this range (ie., mapping of additional data
  228. // in the same page from ACPI driver for a memory operation region, etc.).
  229. // This semantic is enforced by the memory manager.
  230. //
  231. MEMORY_CACHING_TYPE acpiTableMappingType = (HalpPlatformPropertiesEfiFlags & HAL_PLATFORM_ACPI_TABLES_CACHED) ?
  232. MmCached : MmNonCached;
  233. physicalAddr.QuadPart = 0;
  234. header = NULL;
  235. if ((HalpAcpiRsdtVA == NULL) && (HalpAcpiXsdtVA == NULL)) {
  236. //
  237. // Find and map the RSDT once. This mapping is reused on
  238. // subsequent calls to this routine.
  239. //
  240. status = HalpAcpiFindRsdtPhase0(LoaderBlock);
  241. if (!(NT_SUCCESS(status))) {
  242. HalDebugPrint(( HAL_INFO, "HAL: *** make sure you are using ntdetect.com v5.0 ***\n" ));
  243. KeBugCheckEx(MISMATCHED_HAL,
  244. 4, 0xac31, 0, 0);
  245. }
  246. xsdt = HalpMapPhysicalMemory(HalpAcpiRsdt, 2, acpiTableMappingType );
  247. if (!xsdt) {
  248. return NULL;
  249. }
  250. //
  251. // Do a sanity check on the RSDT.
  252. //
  253. if ((xsdt->Header.Signature != RSDT_SIGNATURE) &&
  254. (xsdt->Header.Signature != XSDT_SIGNATURE)) {
  255. HalDisplayString("HAL: Bad RSDT pointer\n");
  256. KeBugCheckEx(MISMATCHED_HAL,
  257. 4, 0xac31, 1, 0);
  258. }
  259. //
  260. // Remap the (X)RSDT now that we know how long it is.
  261. //
  262. offset = HalpAcpiRsdt.LowPart & (PAGE_SIZE - 1);
  263. lengthInPages = (offset + xsdt->Header.Length + (PAGE_SIZE - 1))
  264. >> PAGE_SHIFT;
  265. if (lengthInPages != 2) {
  266. HalpUnmapVirtualAddress(xsdt, 2);
  267. xsdt = HalpMapPhysicalMemory(HalpAcpiRsdt, lengthInPages, acpiTableMappingType );
  268. if (!xsdt) {
  269. DbgPrint("HAL: Couldn't remap RSDT\n");
  270. return NULL;
  271. }
  272. }
  273. if (xsdt->Header.Signature == XSDT_SIGNATURE) {
  274. HalpAcpiXsdtVA = xsdt;
  275. } else {
  276. HalpAcpiRsdtVA = (PRSDT)xsdt;
  277. HalpAcpiXsdtVA = NULL;
  278. }
  279. }
  280. xsdt = HalpAcpiXsdtVA;
  281. rsdt = HalpAcpiRsdtVA;
  282. rsdtEntries = xsdt ?
  283. NumTableEntriesFromXSDTPointer(xsdt) :
  284. NumTableEntriesFromRSDTPointer(rsdt);
  285. //
  286. // Look down the pointer in each entry to see if it points to
  287. // the table we are looking for.
  288. //
  289. for (entry = 0; entry < rsdtEntries; entry++) {
  290. physicalAddr.QuadPart = xsdt ?
  291. xsdt->Tables[entry].QuadPart :
  292. rsdt->Tables[entry];
  293. if (header != NULL) {
  294. HalpUnmapVirtualAddress(header, 2);
  295. }
  296. header = HalpMapPhysicalMemory(physicalAddr, 2, acpiTableMappingType );
  297. if (!header) {
  298. return NULL;
  299. }
  300. if (header->Signature == Signature) {
  301. break;
  302. }
  303. }
  304. if (entry == rsdtEntries) {
  305. //
  306. // Signature not found, free the PTR for the last entry
  307. // examined and indicate failure to the caller.
  308. //
  309. HalpUnmapVirtualAddress(header, 2);
  310. return NULL;
  311. }
  312. //
  313. // Make sure we have mapped enough memory to cover the entire
  314. // table.
  315. //
  316. offset = (ULONG)((ULONG_PTR)header & (PAGE_SIZE - 1));
  317. lengthInPages = (header->Length + offset + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
  318. if (lengthInPages != 2) {
  319. HalpUnmapVirtualAddress(header, 2);
  320. header = HalpMapPhysicalMemory( physicalAddr, lengthInPages, acpiTableMappingType );
  321. }
  322. //
  323. // Validate the table's checksum.
  324. // N.B. We expect the checksum to be wrong on some early versions
  325. // of the FADT.
  326. //
  327. if ((header != NULL) &&
  328. ((header->Signature != FADT_SIGNATURE) || (header->Revision > 2))) {
  329. PUCHAR c = (PUCHAR)header + header->Length;
  330. UCHAR s = 0;
  331. if (header->Length) {
  332. do {
  333. s += *--c;
  334. } while (c != (PUCHAR)header);
  335. }
  336. if ((s != 0) || (header->Length == 0)) {
  337. //
  338. // This table is not valid.
  339. //
  340. HalpInvalidAcpiTable = header->Signature;
  341. #if 0
  342. //
  343. // Don't return this table.
  344. //
  345. HalpUnmapVirtualAddress(header, lengthInPages);
  346. return NULL;
  347. #endif
  348. }
  349. }
  350. return header;
  351. }
  352. NTSTATUS
  353. HalpSetupAcpiPhase0(
  354. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  355. )
  356. /*++
  357. Routine Description:
  358. Save some information from the ACPI tables before they get
  359. destroyed.
  360. Arguments:
  361. none
  362. Return Value:
  363. none
  364. --*/
  365. {
  366. NTSTATUS status;
  367. ULONG entry;
  368. PVOID table;
  369. PVOID physicalAddr;
  370. PDESCRIPTION_HEADER header;
  371. ULONG blkSize;
  372. PHYSICAL_ADDRESS rawAddr;
  373. //
  374. // Copy the Fixed Acpi Descriptor Table (FADT) to a permanent
  375. // home.
  376. //
  377. header = HalpGetAcpiTablePhase0(LoaderBlock, FADT_SIGNATURE);
  378. if (header == NULL) {
  379. HalDebugPrint(( HAL_INFO, "HAL: Didn't find the FACP\n" ));
  380. return STATUS_NOT_FOUND;
  381. }
  382. RtlCopyMemory(&HalpFixedAcpiDescTable,
  383. header,
  384. MIN(header->Length, sizeof(HalpFixedAcpiDescTable)));
  385. if (header->Revision < 3) {
  386. KeBugCheckEx(ACPI_BIOS_ERROR, 0x11, 9, header->Revision, 0);
  387. }
  388. // Check for MMIO addresses that need to be mapped.
  389. blkSize = HalpFixedAcpiDescTable.pm1_evt_len;
  390. ASSERT(blkSize);
  391. if ((HalpFixedAcpiDescTable.x_pm1a_evt_blk.AddressSpaceID == AcpiGenericSpaceMemory) &&
  392. (blkSize > 0)) {
  393. rawAddr = HalpFixedAcpiDescTable.x_pm1a_evt_blk.Address;
  394. HalpFixedAcpiDescTable.x_pm1a_evt_blk.Address.QuadPart =
  395. (LONGLONG)HalpMapPhysicalMemory(rawAddr,ADDRESS_AND_SIZE_TO_SPAN_PAGES(rawAddr.LowPart, blkSize),MmNonCached);
  396. }
  397. blkSize = HalpFixedAcpiDescTable.pm1_ctrl_len;
  398. ASSERT(blkSize);
  399. if ((HalpFixedAcpiDescTable.x_pm1a_ctrl_blk.AddressSpaceID == AcpiGenericSpaceMemory) &&
  400. (blkSize > 0)) {
  401. rawAddr = HalpFixedAcpiDescTable.x_pm1a_ctrl_blk.Address;
  402. HalpFixedAcpiDescTable.x_pm1a_ctrl_blk.Address.QuadPart =
  403. (LONGLONG) HalpMapPhysicalMemory(rawAddr,ADDRESS_AND_SIZE_TO_SPAN_PAGES(rawAddr.LowPart, blkSize),MmNonCached);
  404. }
  405. blkSize = HalpFixedAcpiDescTable.pm_tmr_len;
  406. ASSERT(blkSize);
  407. if ((HalpFixedAcpiDescTable.x_pm_tmr_blk.AddressSpaceID == AcpiGenericSpaceMemory) &&
  408. (blkSize > 0)) {
  409. rawAddr = HalpFixedAcpiDescTable.x_pm_tmr_blk.Address;
  410. HalpFixedAcpiDescTable.x_pm_tmr_blk.Address.QuadPart =
  411. (LONGLONG) HalpMapPhysicalMemory(rawAddr,ADDRESS_AND_SIZE_TO_SPAN_PAGES(rawAddr.LowPart, blkSize),MmNonCached);
  412. }
  413. // The rest of these ACPI blocks are optional so test if they exist before mapping them
  414. if (HalpFixedAcpiDescTable.x_pm1b_evt_blk.Address.QuadPart) {
  415. if (HalpFixedAcpiDescTable.x_pm1b_evt_blk.AddressSpaceID == AcpiGenericSpaceMemory) {
  416. blkSize = HalpFixedAcpiDescTable.pm1_evt_len;
  417. rawAddr = HalpFixedAcpiDescTable.x_pm1b_evt_blk.Address;
  418. HalpFixedAcpiDescTable.x_pm1b_evt_blk.Address.QuadPart =
  419. (LONGLONG) HalpMapPhysicalMemory(rawAddr,ADDRESS_AND_SIZE_TO_SPAN_PAGES(rawAddr.LowPart, blkSize),MmNonCached);
  420. }
  421. }
  422. if (HalpFixedAcpiDescTable.x_pm1b_ctrl_blk.Address.QuadPart) {
  423. if (HalpFixedAcpiDescTable.x_pm1b_ctrl_blk.AddressSpaceID == AcpiGenericSpaceMemory) {
  424. blkSize = HalpFixedAcpiDescTable.pm1_ctrl_len;
  425. rawAddr = HalpFixedAcpiDescTable.x_pm1b_ctrl_blk.Address;
  426. HalpFixedAcpiDescTable.x_pm1b_ctrl_blk.Address.QuadPart =
  427. (LONGLONG) HalpMapPhysicalMemory(rawAddr,ADDRESS_AND_SIZE_TO_SPAN_PAGES(rawAddr.LowPart, blkSize),MmNonCached);
  428. }
  429. }
  430. if (HalpFixedAcpiDescTable.x_pm2_ctrl_blk.Address.QuadPart) {
  431. if (HalpFixedAcpiDescTable.x_pm2_ctrl_blk.AddressSpaceID == AcpiGenericSpaceMemory) {
  432. blkSize = HalpFixedAcpiDescTable.pm2_ctrl_len;
  433. rawAddr = HalpFixedAcpiDescTable.x_pm2_ctrl_blk.Address;
  434. HalpFixedAcpiDescTable.x_pm2_ctrl_blk.Address.QuadPart =
  435. (LONGLONG) HalpMapPhysicalMemory(rawAddr,ADDRESS_AND_SIZE_TO_SPAN_PAGES(rawAddr.LowPart, blkSize),MmNonCached);
  436. }
  437. }
  438. if (HalpFixedAcpiDescTable.x_gp0_blk.Address.QuadPart) {
  439. if (HalpFixedAcpiDescTable.x_gp0_blk.AddressSpaceID == AcpiGenericSpaceMemory) {
  440. blkSize = HalpFixedAcpiDescTable.gp0_blk_len;
  441. rawAddr = HalpFixedAcpiDescTable.x_gp0_blk.Address;
  442. HalpFixedAcpiDescTable.x_gp0_blk.Address.QuadPart =
  443. (LONGLONG) HalpMapPhysicalMemory(rawAddr,ADDRESS_AND_SIZE_TO_SPAN_PAGES(rawAddr.LowPart, blkSize),MmNonCached);
  444. }
  445. }
  446. if (HalpFixedAcpiDescTable.x_gp1_blk.Address.QuadPart) {
  447. if (HalpFixedAcpiDescTable.x_gp1_blk.AddressSpaceID == AcpiGenericSpaceMemory) {
  448. blkSize = HalpFixedAcpiDescTable.gp1_blk_len;
  449. rawAddr = HalpFixedAcpiDescTable.x_gp1_blk.Address;
  450. HalpFixedAcpiDescTable.x_gp1_blk.Address.QuadPart =
  451. (LONGLONG) HalpMapPhysicalMemory(rawAddr,ADDRESS_AND_SIZE_TO_SPAN_PAGES(rawAddr.LowPart, blkSize),MmNonCached);
  452. }
  453. }
  454. //
  455. // See if Static Resource Affinity Table is present.
  456. //
  457. HalpNumaInitializeStaticConfiguration(LoaderBlock);
  458. //
  459. // See if Windows Platform Properties Table is present.
  460. //
  461. HalpPlatformPropertiesTable =
  462. HalpGetAcpiTablePhase0(LoaderBlock, IPPT_SIGNATURE);
  463. //
  464. // Enable ACPI counter code since we need it in the boot
  465. // process.
  466. //
  467. HaliAcpiTimerInit(0, FALSE);
  468. //
  469. // Claim a page of memory below 1MB to be used for transitioning
  470. // a sleeping processor back from real mode to protected mode
  471. //
  472. #ifdef IA64
  473. HalDebugPrint(( HAL_INFO, "HAL: WARNING - HalpSetupAcpi - Sleep transitions not yet implemented\n" ));
  474. #else
  475. // check first to see if this has already been done by MP startup code
  476. if (!HalpLowStubPhysicalAddress) {
  477. HalpLowStubPhysicalAddress = (PVOID)HalpAllocPhysicalMemory (LoaderBlock,
  478. LOW_MEMORY, 1, FALSE);
  479. if (HalpLowStubPhysicalAddress) {
  480. HalpLowStub = HalpMapPhysicalMemory(HalpLowStubPhysicalAddress, 1, MmCached);
  481. }
  482. }
  483. //
  484. // Claim a PTE that will be used for cache flushing in states S2 and S3.
  485. //
  486. HalpVirtAddrForFlush = HalpMapPhysicalMemory((PVOID)LOW_MEMORY, 1, MmCached);
  487. HalpPteForFlush = MiGetPteAddress(HalpVirtAddrForFlush);
  488. #endif
  489. return STATUS_SUCCESS;
  490. }
  491. VOID
  492. HaliAcpiTimerInit(
  493. // *** TBD should be ULONG_PTR
  494. IN ULONG TimerPort OPTIONAL,
  495. IN BOOLEAN TimerValExt
  496. )
  497. /*++
  498. Routine Description:
  499. This routine initializes the ACPI timer.
  500. Arguments:
  501. TimerPort - The address in I/O space of the ACPI timer. If this is
  502. 0, then the values from the cached FADT will be used.
  503. TimerValExt - signifies whether the timer is 24 or 32 bits.
  504. --*/
  505. {
  506. #if defined(ACPI64)
  507. ULONG_PTR port = TimerPort;
  508. #else
  509. ULONG port = TimerPort;
  510. #endif
  511. BOOLEAN ext = TimerValExt;
  512. PAGED_CODE();
  513. if (port == 0) {
  514. port = HalpFixedAcpiDescTable.x_pm_tmr_blk.Address.LowPart;
  515. if (HalpFixedAcpiDescTable.flags & TMR_VAL_EXT) {
  516. ext = TRUE;
  517. } else {
  518. ext = FALSE;
  519. }
  520. }
  521. HalaAcpiTimerInit(port,
  522. ext);
  523. }
  524. VOID
  525. HaliAcpiMachineStateInit(
  526. IN PPROCESSOR_INIT ProcInit,
  527. IN PHAL_SLEEP_VAL SleepValues,
  528. OUT PULONG PicVal
  529. )
  530. /*++
  531. Routine Description:
  532. This function is a callback used by the ACPI driver
  533. to notify the HAL with the processor blocks.
  534. Arguments:
  535. --*/
  536. {
  537. POWER_STATE_HANDLER powerState;
  538. SLEEP_STATE_CONTEXT sleepContext;
  539. NTSTATUS status;
  540. PSYSTEM_POWER_STATE_DISABLE_REASON pReasonNoOSPM = NULL;
  541. SYSTEM_POWER_LOGGING_ENTRY PowerLoggingEntry;
  542. PAGED_CODE();
  543. UNREFERENCED_PARAMETER(ProcInit);
  544. *PicVal = 1; // We only support APIC on IA64
  545. RtlZeroMemory (&sleepContext, sizeof (sleepContext));
  546. powerState.Context = NULL;
  547. pReasonNoOSPM = ExAllocatePoolWithTag(
  548. PagedPool,
  549. sizeof(SYSTEM_POWER_STATE_DISABLE_REASON),
  550. HAL_POOL_TAG
  551. );
  552. if (pReasonNoOSPM) {
  553. RtlZeroMemory(pReasonNoOSPM, sizeof(SYSTEM_POWER_STATE_DISABLE_REASON));
  554. pReasonNoOSPM->PowerReasonCode = SPSD_REASON_NONE;
  555. }
  556. //
  557. // Set up fake handlers that do nothing so testing device power
  558. // transitions isn't blocked. Only if hack flag is set, though
  559. //
  560. HalpReadRegistryAndApplyHacks ();
  561. if (HalpHackFlags & HalHackAddFakeSleepHandlersS1) {
  562. powerState.Type = PowerStateSleeping1;
  563. powerState.RtcWake = TRUE;
  564. powerState.Handler = &HaliAcpiFakeSleep;
  565. status = ZwPowerInformation(SystemPowerStateHandler,
  566. &powerState,
  567. sizeof(POWER_STATE_HANDLER),
  568. NULL,
  569. 0);
  570. } else {
  571. if (pReasonNoOSPM) {
  572. pReasonNoOSPM->PowerReasonCode = SPSD_REASON_NOOSPM;
  573. pReasonNoOSPM->AffectedState[PowerStateSleeping1] = TRUE;
  574. }
  575. }
  576. if (HalpHackFlags & HalHackAddFakeSleepHandlersS2) {
  577. powerState.Type = PowerStateSleeping2;
  578. powerState.RtcWake = TRUE;
  579. powerState.Handler = &HaliAcpiFakeSleep;
  580. status = ZwPowerInformation(SystemPowerStateHandler,
  581. &powerState,
  582. sizeof(POWER_STATE_HANDLER),
  583. NULL,
  584. 0);
  585. } else {
  586. if (pReasonNoOSPM) {
  587. pReasonNoOSPM->PowerReasonCode = SPSD_REASON_NOOSPM;
  588. pReasonNoOSPM->AffectedState[PowerStateSleeping2] = TRUE;
  589. }
  590. }
  591. if (HalpHackFlags & HalHackAddFakeSleepHandlersS3) {
  592. powerState.Type = PowerStateSleeping3;
  593. powerState.RtcWake = TRUE;
  594. powerState.Handler = &HaliAcpiFakeSleep;
  595. powerState.Context = ULongToPtr(sleepContext.AsULONG);
  596. status = ZwPowerInformation(SystemPowerStateHandler,
  597. &powerState,
  598. sizeof(POWER_STATE_HANDLER),
  599. NULL,
  600. 0);
  601. } else {
  602. if (pReasonNoOSPM) {
  603. pReasonNoOSPM->PowerReasonCode = SPSD_REASON_NOOSPM;
  604. pReasonNoOSPM->AffectedState[PowerStateSleeping3] = TRUE;
  605. }
  606. }
  607. //
  608. // we do not register support for hibernate
  609. //
  610. if (pReasonNoOSPM) {
  611. pReasonNoOSPM->PowerReasonCode = SPSD_REASON_NOOSPM;
  612. pReasonNoOSPM->AffectedState[PowerStateSleeping4] = TRUE;
  613. }
  614. if (pReasonNoOSPM && pReasonNoOSPM->PowerReasonCode != SPSD_REASON_NONE) {
  615. PowerLoggingEntry.LoggingType = LOGGING_TYPE_SPSD;
  616. PowerLoggingEntry.LoggingEntry = pReasonNoOSPM;
  617. ZwPowerInformation(
  618. SystemPowerLoggingEntry,
  619. &PowerLoggingEntry,
  620. sizeof(PowerLoggingEntry),
  621. NULL,
  622. 0 );
  623. }
  624. //
  625. // For now all we are going to do is register a shutdown handler
  626. // that will call shutdown-restart
  627. //
  628. if (SleepValues[4].Supported) {
  629. powerState.Type = PowerStateShutdownOff;
  630. powerState.RtcWake = FALSE;
  631. powerState.Handler = &HaliAcpiSleep;
  632. sleepContext.bits.Pm1aVal = SleepValues[4].Pm1aVal;
  633. sleepContext.bits.Pm1bVal = SleepValues[4].Pm1bVal;
  634. sleepContext.bits.Flags = SLEEP_STATE_OFF;
  635. HalpShutdownContext = sleepContext;
  636. powerState.Context = ULongToPtr(sleepContext.AsULONG);
  637. status = ZwPowerInformation(SystemPowerStateHandler,
  638. &powerState,
  639. sizeof(POWER_STATE_HANDLER),
  640. NULL,
  641. 0);
  642. ASSERT(NT_SUCCESS(status));
  643. }
  644. }
  645. ULONG
  646. HaliAcpiQueryFlags(
  647. VOID
  648. )
  649. /*++
  650. Routine Description:
  651. This routine is temporary is used to report the presence of the
  652. boot.ini switch
  653. Arguments:
  654. None
  655. Return Value:
  656. TRUE, if switch present
  657. --*/
  658. {
  659. return HalpAcpiFlags;
  660. }
  661. NTSTATUS
  662. HaliInitPowerManagement(
  663. IN PPM_DISPATCH_TABLE PmDriverDispatchTable,
  664. IN OUT PPM_DISPATCH_TABLE *PmHalDispatchTable
  665. )
  666. /*++
  667. Routine Description:
  668. This is called by the ACPI driver to start the PM
  669. code.
  670. Arguments:
  671. PmDriverDispatchTable - table of functions provided
  672. by the ACPI driver for the HAL
  673. PmHalDispatchTable - table of functions provided by
  674. the HAL for the ACPI driver
  675. Return Value:
  676. status
  677. --*/
  678. {
  679. OBJECT_ATTRIBUTES objAttributes;
  680. PCALLBACK_OBJECT callback;
  681. PHYSICAL_ADDRESS pAddr;
  682. UNICODE_STRING callbackName;
  683. NTSTATUS status;
  684. PFACS facs;
  685. PAGED_CODE();
  686. //
  687. // Keep a pointer to the driver's dispatch table.
  688. //
  689. // ASSERT(PmDriverDispatchTable);
  690. // ASSERT(PmDriverDispatchTable->Signature == ACPI_HAL_DISPATCH_SIGNATURE);
  691. PmAcpiDispatchTable = PmDriverDispatchTable;
  692. //
  693. // Fill in the function table
  694. //
  695. HalAcpiDispatchTable.Signature = HAL_ACPI_DISPATCH_SIGNATURE;
  696. HalAcpiDispatchTable.Version = HAL_ACPI_DISPATCH_VERSION;
  697. HalAcpiDispatchTable.HalpAcpiTimerInit = &HaliAcpiTimerInit;
  698. HalAcpiDispatchTable.HalpAcpiTimerInterrupt =
  699. (pHalAcpiTimerInterrupt)&HalAcpiTimerCarry;
  700. HalAcpiDispatchTable.HalpAcpiMachineStateInit = &HaliAcpiMachineStateInit;
  701. HalAcpiDispatchTable.HalpAcpiQueryFlags = &HaliAcpiQueryFlags;
  702. HalAcpiDispatchTable.HalxPicStateIntact = &HalpAcpiPicStateIntact;
  703. HalAcpiDispatchTable.HalxRestorePicState = &HalpRestoreInterruptControllerState;
  704. HalAcpiDispatchTable.HalpSetVectorState = &HaliSetVectorState;
  705. HalAcpiDispatchTable.HalpPciInterfaceReadConfig = &HaliPciInterfaceReadConfig;
  706. HalAcpiDispatchTable.HalpPciInterfaceWriteConfig = &HaliPciInterfaceWriteConfig;
  707. HalAcpiDispatchTable.HalpSetMaxLegacyPciBusNumber = &HalpSetMaxLegacyPciBusNumber;
  708. HalAcpiDispatchTable.HalpIsVectorValid = &HaliIsVectorValid;
  709. *PmHalDispatchTable = (PPM_DISPATCH_TABLE)&HalAcpiDispatchTable;
  710. //
  711. // Fill in Hal's private dispatch table
  712. //
  713. HalSetWakeEnable = HaliSetWakeEnable;
  714. HalSetWakeAlarm = HaliSetWakeAlarm;
  715. //
  716. // Register callback that tells us to make
  717. // anything we need for sleeping non-pageable.
  718. //
  719. RtlInitUnicodeString(&callbackName, L"\\Callback\\PowerState");
  720. InitializeObjectAttributes(
  721. &objAttributes,
  722. &callbackName,
  723. OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
  724. NULL,
  725. NULL
  726. );
  727. ExCreateCallback(&callback,
  728. &objAttributes,
  729. FALSE,
  730. TRUE);
  731. ExRegisterCallback(callback,
  732. (PCALLBACK_FUNCTION)&HalpPowerStateCallback,
  733. NULL);
  734. #if 0
  735. //
  736. // Find the location of the firmware waking vector.
  737. // N.B. If any of this fails, then HalpWakeVector will be NULL
  738. // and we won't support S2 or S3.
  739. //
  740. if (HalpFixedAcpiDescTable.x_firmware_ctrl.Address.QuadPart) {
  741. facs = HalpMapPhysicalMemory(HalpFixedAcpiDescTable.x_firmware_ctrl.Address,
  742. ADDRESS_AND_SIZE_TO_SPAN_PAGES(HalpFixedAcpiDescTable.x_firmware_ctrl.Address.LowPart, sizeof(FACS)),
  743. MmCached);
  744. if (facs) {
  745. if (facs->Signature == FACS_SIGNATURE) {
  746. HalpWakeVector = &facs->x_FirmwareWakingVector;
  747. }
  748. }
  749. }
  750. #endif
  751. return STATUS_SUCCESS;
  752. }
  753. NTSTATUS
  754. HalpQueryAcpiResourceRequirements(
  755. IN PIO_RESOURCE_REQUIREMENTS_LIST *Requirements
  756. )
  757. /*++
  758. Routine Description:
  759. This routine is a temporary stub that tries to detect the presence
  760. of an ACPI controller within the system. This code is meant to be
  761. inserted within NT's root system enumerator.
  762. Arguents:
  763. Requirements - pointer to list of resources
  764. Return Value:
  765. STATUS_SUCCESS - If we found a device object
  766. STATUS_NO_SUCH_DEVICE - If we can't find info about the new PDO
  767. --*/
  768. {
  769. NTSTATUS ntStatus;
  770. PIO_RESOURCE_REQUIREMENTS_LIST resourceList;
  771. ULONG resourceListSize;
  772. PAGED_CODE();
  773. //
  774. // Now figure out the number of resource that we need
  775. //
  776. ntStatus = HalpAcpiDetectResourceListSize(
  777. &resourceListSize
  778. );
  779. //
  780. // Convert this resourceListSize into the number of bytes that we
  781. // must allocate
  782. //
  783. resourceListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) +
  784. ( (resourceListSize - 1) * sizeof(IO_RESOURCE_DESCRIPTOR) );
  785. //
  786. // Allocate the correct number of bytes of the Resource List
  787. //
  788. resourceList = ExAllocatePoolWithTag(
  789. PagedPool,
  790. resourceListSize,
  791. HAL_POOL_TAG
  792. );
  793. //
  794. // This call must have succeeded or we cannot lay claim to ACPI
  795. //
  796. if (resourceList == NULL) {
  797. return STATUS_INSUFFICIENT_RESOURCES;
  798. }
  799. //
  800. // Set up the ListSize in the structure
  801. //
  802. RtlZeroMemory(resourceList, resourceListSize);
  803. resourceList->ListSize = resourceListSize;
  804. //
  805. // Build the ResourceList here
  806. //
  807. ntStatus = HalpBuildAcpiResourceList(resourceList);
  808. //
  809. // Did we build the list okay?
  810. //
  811. if (!NT_SUCCESS(ntStatus)) {
  812. //
  813. // Free memory and exit
  814. //
  815. ExFreePool(resourceList);
  816. return STATUS_NO_SUCH_DEVICE;
  817. }
  818. *Requirements = resourceList;
  819. return ntStatus;
  820. }
  821. NTSTATUS
  822. HalpBuildAcpiResourceList(
  823. OUT PIO_RESOURCE_REQUIREMENTS_LIST List
  824. )
  825. /*++
  826. Routine Description:
  827. This is the routine that builds the ResourceList given the FADT and
  828. an arbitrary number of ResourceDescriptors. We assume that the
  829. ResourceList has been properly allocated and sized
  830. Arguments:
  831. List - The list to fill in
  832. Return Value:
  833. STATUS_SUCCESS if okay
  834. STATUS_UNSUCCESSUL if not
  835. --*/
  836. {
  837. PIO_RESOURCE_DESCRIPTOR partialResource;
  838. ULONG sciVector;
  839. ULONG count = 0;
  840. PAGED_CODE();
  841. ASSERT( List != NULL );
  842. //
  843. // Specify some default values (for now) to determine the Bus Type and
  844. // the bus number
  845. //
  846. List->AlternativeLists = 1;
  847. List->InterfaceType = Isa;
  848. List->BusNumber = 0;
  849. List->List[0].Version = 1;
  850. List->List[0].Revision = 1;
  851. //
  852. // Is there an interrupt resource required?
  853. //
  854. if (HalpFixedAcpiDescTable.sci_int_vector != 0) {
  855. List->List[0].Descriptors[count].Type = CmResourceTypeInterrupt;
  856. List->List[0].Descriptors[count].ShareDisposition = CmResourceShareShared;
  857. List->List[0].Descriptors[count].Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
  858. //
  859. // The latest ACPI 2.0 spec allows the use of GSIVs in sci_int_vector in
  860. // the FADT. If the vector is >= PIC_VECTORS then don't translate,
  861. // otherwise use the translation, if any, specified in the ISO entry in
  862. // the MADT.
  863. //
  864. sciVector = HalpFixedAcpiDescTable.sci_int_vector;
  865. if (sciVector < PIC_VECTORS) {
  866. sciVector = HalpPicVectorRedirect[sciVector];
  867. }
  868. List->List[0].Descriptors[count].u.Interrupt.MinimumVector = sciVector;
  869. List->List[0].Descriptors[count].u.Interrupt.MaximumVector = sciVector;
  870. List->List[0].Count++;
  871. count++;
  872. }
  873. #if DECLARE_FADT_RESOURCES_AT_ROOT
  874. //
  875. // Is there an SMI CMD IO Port?
  876. //
  877. if (HalpFixedAcpiDescTable.smi_cmd_io_port != 0) {
  878. List->List[0].Descriptors[count].Type = CmResourceTypePort;
  879. List->List[0].Descriptors[count].ShareDisposition = CmResourceShareDeviceExclusive;
  880. List->List[0].Descriptors[count].Flags =CM_RESOURCE_PORT_IO;
  881. List->List[0].Descriptors[count].u.Port.MinimumAddress.LowPart =
  882. PtrToUlong(HalpFixedAcpiDescTable.smi_cmd_io_port);
  883. List->List[0].Descriptors[count].u.Port.MaximumAddress.LowPart =
  884. PtrToUlong(HalpFixedAcpiDescTable.smi_cmd_io_port);
  885. List->List[0].Descriptors[count].u.Port.Length = 1;
  886. List->List[0].Descriptors[count].u.Port.Alignment = 1;
  887. List->List[0].Count++;
  888. count++;
  889. }
  890. //
  891. // Is there an PM1A Event Block IO Port?
  892. //
  893. if (HalpFixedAcpiDescTable.pm1a_evt_blk_io_port != 0) {
  894. List->List[0].Descriptors[count].Type = CmResourceTypePort;
  895. List->List[0].Descriptors[count].ShareDisposition = CmResourceShareDeviceExclusive;
  896. List->List[0].Descriptors[count].Flags = CM_RESOURCE_PORT_IO;
  897. List->List[0].Descriptors[count].u.Port.MinimumAddress.LowPart =
  898. HalpFixedAcpiDescTable.pm1a_evt_blk_io_port;
  899. List->List[0].Descriptors[count].u.Port.MaximumAddress.LowPart =
  900. HalpFixedAcpiDescTable.pm1a_evt_blk_io_port + (ULONG) HalpFixedAcpiDescTable.pm1_evt_len - 1;
  901. List->List[0].Descriptors[count].u.Port.Length = (ULONG) HalpFixedAcpiDescTable.pm1_evt_len;
  902. List->List[0].Descriptors[count].u.Port.Alignment = 1;
  903. List->List[0].Count++;
  904. count++;
  905. }
  906. //
  907. // Is there a PM1B Event Block IO Port?
  908. //
  909. if (HalpFixedAcpiDescTable.pm1b_evt_blk_io_port != 0) {
  910. List->List[0].Descriptors[count].Type = CmResourceTypePort;
  911. List->List[0].Descriptors[count].ShareDisposition = CmResourceShareDeviceExclusive;
  912. List->List[0].Descriptors[count].Flags = CM_RESOURCE_PORT_IO;
  913. List->List[0].Descriptors[count].u.Port.MinimumAddress.LowPart =
  914. HalpFixedAcpiDescTable.pm1b_evt_blk_io_port;
  915. List->List[0].Descriptors[count].u.Port.MaximumAddress.LowPart =
  916. HalpFixedAcpiDescTable.pm1b_evt_blk_io_port + (ULONG) HalpFixedAcpiDescTable.pm1_evt_len - 1;
  917. List->List[0].Descriptors[count].u.Port.Length = (ULONG) HalpFixedAcpiDescTable.pm1_evt_len;
  918. List->List[0].Descriptors[count].u.Port.Alignment = 1;
  919. List->List[0].Count++;
  920. count++;
  921. }
  922. //
  923. // Is there a PM1A Control Block IO Port?
  924. //
  925. if (HalpFixedAcpiDescTable.pm1a_ctrl_blk_io_port != 0) {
  926. List->List[0].Descriptors[count].Type = CmResourceTypePort;
  927. List->List[0].Descriptors[count].ShareDisposition = CmResourceShareDeviceExclusive;
  928. List->List[0].Descriptors[count].Flags = CM_RESOURCE_PORT_IO;
  929. List->List[0].Descriptors[count].u.Port.MinimumAddress.LowPart =
  930. HalpFixedAcpiDescTable.pm1a_ctrl_blk_io_port;
  931. List->List[0].Descriptors[count].u.Port.MaximumAddress.LowPart =
  932. HalpFixedAcpiDescTable.pm1a_ctrl_blk_io_port + (ULONG) HalpFixedAcpiDescTable.pm1_ctrl_len - 1;
  933. List->List[0].Descriptors[count].u.Port.Length = (ULONG) HalpFixedAcpiDescTable.pm1_ctrl_len;
  934. List->List[0].Descriptors[count].u.Port.Alignment = 1;
  935. List->List[0].Count++;
  936. count++;
  937. }
  938. //
  939. // Is there a PM1B Control Block IO Port?
  940. //
  941. if (HalpFixedAcpiDescTable.pm1b_ctrl_blk_io_port != 0) {
  942. List->List[0].Descriptors[count].Type = CmResourceTypePort;
  943. List->List[0].Descriptors[count].ShareDisposition = CmResourceShareDeviceExclusive;
  944. List->List[0].Descriptors[count].Flags = CM_RESOURCE_PORT_IO;
  945. List->List[0].Descriptors[count].u.Port.MinimumAddress.LowPart =
  946. HalpFixedAcpiDescTable.pm1b_ctrl_blk_io_port;
  947. List->List[0].Descriptors[count].u.Port.MaximumAddress.LowPart =
  948. HalpFixedAcpiDescTable.pm1b_ctrl_blk_io_port + (ULONG) HalpFixedAcpiDescTable.pm1_ctrl_len - 1;
  949. List->List[0].Descriptors[count].u.Port.Length = (ULONG) HalpFixedAcpiDescTable.pm1_ctrl_len;
  950. List->List[0].Descriptors[count].u.Port.Alignment = 1;
  951. List->List[0].Count++;
  952. count++;
  953. }
  954. //
  955. // Is there a PM2 Control Block IO Port?
  956. //
  957. if (HalpFixedAcpiDescTable.pm2_ctrl_blk_io_port != 0) {
  958. List->List[0].Descriptors[count].Type = CmResourceTypePort;
  959. List->List[0].Descriptors[count].ShareDisposition = CmResourceShareDeviceExclusive;
  960. List->List[0].Descriptors[count].Flags = CM_RESOURCE_PORT_IO;
  961. List->List[0].Descriptors[count].u.Port.MinimumAddress.LowPart =
  962. HalpFixedAcpiDescTable.pm2_ctrl_blk_io_port;
  963. List->List[0].Descriptors[count].u.Port.MaximumAddress.LowPart =
  964. HalpFixedAcpiDescTable.pm2_ctrl_blk_io_port + (ULONG) HalpFixedAcpiDescTable.pm2_ctrl_len - 1;
  965. List->List[0].Descriptors[count].u.Port.Length = (ULONG) HalpFixedAcpiDescTable.pm2_ctrl_len;
  966. List->List[0].Descriptors[count].u.Port.Alignment = 1;
  967. List->List[0].Count++;
  968. count++;
  969. }
  970. //
  971. // Is there a PM Timer Block IO Port?
  972. //
  973. if (HalpFixedAcpiDescTable.pm_tmr_blk_io_port != 0) {
  974. List->List[0].Descriptors[count].Type = CmResourceTypePort;
  975. List->List[0].Descriptors[count].ShareDisposition = CmResourceShareDeviceExclusive;
  976. List->List[0].Descriptors[count].Flags = CM_RESOURCE_PORT_IO;
  977. List->List[0].Descriptors[count].u.Port.MinimumAddress.LowPart =
  978. HalpFixedAcpiDescTable.pm_tmr_blk_io_port;
  979. List->List[0].Descriptors[count].u.Port.MaximumAddress.LowPart =
  980. HalpFixedAcpiDescTable.pm_tmr_blk_io_port + (ULONG) HalpFixedAcpiDescTable.pm_tmr_len - 1;
  981. List->List[0].Descriptors[count].u.Port.Length = (ULONG) HalpFixedAcpiDescTable.pm_tmr_len;
  982. List->List[0].Descriptors[count].u.Port.Alignment = 1;
  983. List->List[0].Count++;
  984. count++;
  985. }
  986. //
  987. // Is there a GP0 Block IO Port?
  988. //
  989. if (HalpFixedAcpiDescTable.gp0_blk_io_port != 0) {
  990. List->List[0].Descriptors[count].Type = CmResourceTypePort;
  991. List->List[0].Descriptors[count].ShareDisposition = CmResourceShareDeviceExclusive;
  992. List->List[0].Descriptors[count].Flags = CM_RESOURCE_PORT_IO;
  993. List->List[0].Descriptors[count].u.Port.MinimumAddress.LowPart =
  994. HalpFixedAcpiDescTable.gp0_blk_io_port;
  995. List->List[0].Descriptors[count].u.Port.MaximumAddress.LowPart =
  996. HalpFixedAcpiDescTable.gp0_blk_io_port + (ULONG) HalpFixedAcpiDescTable.gp0_blk_len - 1;
  997. List->List[0].Descriptors[count].u.Port.Length = (ULONG) HalpFixedAcpiDescTable.gp0_blk_len;
  998. List->List[0].Descriptors[count].u.Port.Alignment = 1;
  999. List->List[0].Count++;
  1000. count++;
  1001. }
  1002. //
  1003. // Is there a GP1 Block IO port?
  1004. //
  1005. if (HalpFixedAcpiDescTable.gp1_blk_io_port != 0) {
  1006. List->List[0].Descriptors[count].Type = CmResourceTypePort;
  1007. List->List[0].Descriptors[count].ShareDisposition = CmResourceShareDeviceExclusive;
  1008. List->List[0].Descriptors[count].Flags = CM_RESOURCE_PORT_IO;
  1009. List->List[0].Descriptors[count].u.Port.MinimumAddress.LowPart =
  1010. HalpFixedAcpiDescTable.gp1_blk_io_port;
  1011. List->List[0].Descriptors[count].u.Port.MaximumAddress.LowPart =
  1012. HalpFixedAcpiDescTable.gp1_blk_io_port + (ULONG) HalpFixedAcpiDescTable.gp1_blk_len - 1;
  1013. List->List[0].Descriptors[count].u.Port.Length = (ULONG) HalpFixedAcpiDescTable.gp1_blk_len;
  1014. List->List[0].Descriptors[count].u.Port.Alignment = 1;
  1015. List->List[0].Count++;
  1016. count++;
  1017. }
  1018. #endif // DECLARE_FADT_RESOURCES_AT_ROOT
  1019. return STATUS_SUCCESS;
  1020. }
  1021. NTSTATUS
  1022. HalpAcpiDetectResourceListSize(
  1023. OUT PULONG ResourceListSize
  1024. )
  1025. /*++
  1026. Routine Description:
  1027. Given a pointer to an FADT, determine the number of
  1028. CM_PARTIAL_RESOURCE_DESCRIPTORS that are required to
  1029. describe all the resource mentioned in the FADT
  1030. Arguments:
  1031. ResourceListSize - Location to store the answer
  1032. Return Value:
  1033. STATUS_SUCCESS if everything went okay
  1034. --*/
  1035. {
  1036. PAGED_CODE();
  1037. //
  1038. // First of all, assume that we need no resources
  1039. //
  1040. *ResourceListSize = 0;
  1041. //
  1042. // Is there an interrupt resource required?
  1043. //
  1044. if (HalpFixedAcpiDescTable.sci_int_vector != 0) {
  1045. *ResourceListSize += 1;
  1046. }
  1047. #if DECLARE_FADT_RESOURCES_AT_ROOT
  1048. //
  1049. // Is there an SMI CMD IO Port?
  1050. //
  1051. if (HalpFixedAcpiDescTable.smi_cmd_io_port != 0) {
  1052. *ResourceListSize += 1;
  1053. }
  1054. //
  1055. // Is there an PM1A Event Block IO Port?
  1056. //
  1057. if (HalpFixedAcpiDescTable.pm1a_evt_blk_io_port != 0) {
  1058. *ResourceListSize += 1;
  1059. }
  1060. //
  1061. // Is there a PM1B Event Block IO Port?
  1062. //
  1063. if (HalpFixedAcpiDescTable.pm1b_evt_blk_io_port != 0) {
  1064. *ResourceListSize += 1;
  1065. }
  1066. //
  1067. // Is there a PM1A Control Block IO Port?
  1068. //
  1069. if (HalpFixedAcpiDescTable.pm1a_ctrl_blk_io_port != 0) {
  1070. *ResourceListSize += 1;
  1071. }
  1072. //
  1073. // Is there a PM1B Control Block IO Port?
  1074. //
  1075. if (HalpFixedAcpiDescTable.pm1b_ctrl_blk_io_port != 0) {
  1076. *ResourceListSize += 1;
  1077. }
  1078. //
  1079. // Is there a PM2 Control Block IO Port?
  1080. //
  1081. if (HalpFixedAcpiDescTable.pm2_ctrl_blk_io_port != 0) {
  1082. *ResourceListSize += 1;
  1083. }
  1084. //
  1085. // Is there a PM Timer Block IO Port?
  1086. //
  1087. if (HalpFixedAcpiDescTable.pm_tmr_blk_io_port != 0) {
  1088. *ResourceListSize += 1;
  1089. }
  1090. //
  1091. // Is there a GP0 Block IO Port?
  1092. //
  1093. if (HalpFixedAcpiDescTable.gp0_blk_io_port != 0) {
  1094. *ResourceListSize += 1;
  1095. }
  1096. //
  1097. // Is there a GP1 Block IO Port?
  1098. //
  1099. if (HalpFixedAcpiDescTable.gp1_blk_io_port != 0) {
  1100. *ResourceListSize += 1;
  1101. }
  1102. #endif // DECALRE_FADT_RESOURCES_AT_ROOT
  1103. return STATUS_SUCCESS;
  1104. }
  1105. /*++
  1106. Routine Description:
  1107. Scans the registry for TestFlags and sets the global
  1108. hackflag to whatever the registry value is, if it
  1109. exists.
  1110. Arguments:
  1111. None
  1112. Return Value:
  1113. None
  1114. --*/
  1115. VOID
  1116. HalpReadRegistryAndApplyHacks (
  1117. VOID
  1118. )
  1119. {
  1120. OBJECT_ATTRIBUTES ObjectAttributes;
  1121. UNICODE_STRING UnicodeString;
  1122. HANDLE BaseHandle = NULL;
  1123. NTSTATUS status;
  1124. KEY_VALUE_PARTIAL_INFORMATION hackflags;
  1125. ULONG resultlength = 0;
  1126. HalpHackFlags = 0;
  1127. RtlInitUnicodeString (&UnicodeString,
  1128. L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\Control\\HAL");
  1129. InitializeObjectAttributes(&ObjectAttributes,
  1130. &UnicodeString,
  1131. OBJ_CASE_INSENSITIVE,
  1132. NULL,
  1133. (PSECURITY_DESCRIPTOR) NULL);
  1134. status = ZwOpenKey (&BaseHandle,
  1135. KEY_READ,
  1136. &ObjectAttributes);
  1137. if (!NT_SUCCESS (status)) {
  1138. return;
  1139. }
  1140. RtlInitUnicodeString (&UnicodeString,
  1141. L"TestFlags");
  1142. status = ZwQueryValueKey (BaseHandle,
  1143. &UnicodeString,
  1144. KeyValuePartialInformation,
  1145. &hackflags,
  1146. sizeof (hackflags),
  1147. &resultlength);
  1148. if (!NT_SUCCESS (status)) {
  1149. return;
  1150. }
  1151. if (hackflags.Type != REG_DWORD || hackflags.DataLength != sizeof (ULONG)) {
  1152. return;
  1153. }
  1154. HalpHackFlags = (ULONG) *hackflags.Data;
  1155. }
  1156. ULONG
  1157. HalpReadGenAddr(
  1158. IN PGEN_ADDR GenAddr
  1159. )
  1160. {
  1161. ULONG i, result = 0, bitWidth, mask = 0;
  1162. //
  1163. // Figure out how wide our target register is.
  1164. //
  1165. bitWidth = GenAddr->BitWidth +
  1166. GenAddr->BitOffset;
  1167. if (bitWidth > 16) {
  1168. bitWidth = 32;
  1169. } else if (bitWidth <= 8) {
  1170. bitWidth = 8;
  1171. } else {
  1172. bitWidth = 16;
  1173. }
  1174. switch (GenAddr->AddressSpaceID) {
  1175. case AcpiGenericSpaceIO:
  1176. ASSERT(!(GenAddr->Address.LowPart & 0Xffff0000));
  1177. ASSERT(GenAddr->Address.HighPart == 0);
  1178. switch (bitWidth) {
  1179. case 8:
  1180. result = READ_PORT_UCHAR((PUCHAR)(UINT_PTR)GenAddr->Address.LowPart);
  1181. break;
  1182. case 16:
  1183. result = READ_PORT_USHORT((PUSHORT)(UINT_PTR)GenAddr->Address.LowPart);
  1184. break;
  1185. case 32:
  1186. result = READ_PORT_ULONG((PULONG)(UINT_PTR)GenAddr->Address.LowPart);
  1187. break;
  1188. default:
  1189. return 0;
  1190. }
  1191. break;
  1192. case AcpiGenericSpaceMemory:
  1193. //
  1194. // This code path depends on the fact that the addresses
  1195. // in these structures have already been converted to
  1196. // virtual addresses.
  1197. //
  1198. switch (bitWidth) {
  1199. case 8:
  1200. result = READ_REGISTER_UCHAR((PUCHAR)GenAddr->Address.QuadPart);
  1201. break;
  1202. case 16:
  1203. result = READ_REGISTER_USHORT((PUSHORT)GenAddr->Address.QuadPart);
  1204. break;
  1205. case 32:
  1206. result = READ_REGISTER_ULONG((PULONG)GenAddr->Address.QuadPart);
  1207. break;
  1208. default:
  1209. return 0;
  1210. }
  1211. break;
  1212. default:
  1213. return 0;
  1214. }
  1215. //
  1216. // If the register is not actually byte-aligned, correct for
  1217. // that.
  1218. //
  1219. if (result && (bitWidth != GenAddr->BitWidth)) {
  1220. result >>= GenAddr->BitOffset;
  1221. result &= ((0x1ul << GenAddr->BitWidth) - 1);
  1222. }
  1223. return result;
  1224. }
  1225. VOID
  1226. HalpWriteGenAddr(
  1227. IN PGEN_ADDR GenAddr,
  1228. IN ULONG Value
  1229. )
  1230. {
  1231. ULONG i, result = 0, bitWidth, data, mask = 0;
  1232. data = 0;
  1233. //
  1234. // Figure out how wide our target register is.
  1235. //
  1236. bitWidth = GenAddr->BitWidth +
  1237. GenAddr->BitOffset;
  1238. if (bitWidth > 16) {
  1239. bitWidth = 32;
  1240. } else if (bitWidth <= 8) {
  1241. bitWidth = 8;
  1242. } else {
  1243. bitWidth = 16;
  1244. }
  1245. switch (GenAddr->AddressSpaceID) {
  1246. case AcpiGenericSpaceIO:
  1247. ASSERT(!(GenAddr->Address.LowPart & 0Xffff0000));
  1248. ASSERT(GenAddr->Address.HighPart == 0);
  1249. switch (bitWidth) {
  1250. case 8:
  1251. ASSERT(!(Value & 0xffffff00));
  1252. if ((GenAddr->BitOffset != 0) ||
  1253. (GenAddr->BitWidth != bitWidth)) {
  1254. data = READ_PORT_UCHAR((PUCHAR)(UINT_PTR)GenAddr->Address.LowPart);
  1255. mask = (UCHAR)~0 >> (8 - GenAddr->BitWidth);
  1256. mask = (UCHAR)~(mask << GenAddr->BitOffset);
  1257. data &= mask;
  1258. data |= (UCHAR)Value << GenAddr->BitOffset;
  1259. } else {
  1260. data = Value;
  1261. }
  1262. WRITE_PORT_UCHAR((PUCHAR)(UINT_PTR)GenAddr->Address.LowPart,
  1263. (UCHAR)data);
  1264. break;
  1265. case 16:
  1266. ASSERT(!(Value & 0xffff0000));
  1267. if ((GenAddr->BitOffset != 0) ||
  1268. (GenAddr->BitWidth != bitWidth)) {
  1269. data = READ_PORT_USHORT((PUSHORT)(UINT_PTR)GenAddr->Address.LowPart);
  1270. mask = (USHORT)~0 >> (16 - GenAddr->BitWidth);
  1271. mask = (USHORT)~(mask << GenAddr->BitOffset);
  1272. data &= mask;
  1273. data |= (USHORT)Value << GenAddr->BitOffset;
  1274. } else {
  1275. data = Value;
  1276. }
  1277. WRITE_PORT_USHORT((PUSHORT)(UINT_PTR)GenAddr->Address.LowPart,
  1278. (USHORT)data);
  1279. break;
  1280. case 32:
  1281. if ((GenAddr->BitOffset != 0) ||
  1282. (GenAddr->BitWidth != bitWidth)) {
  1283. data = READ_PORT_ULONG((PULONG)(UINT_PTR)GenAddr->Address.LowPart);
  1284. mask = (ULONG)~0 >> (32 - GenAddr->BitWidth);
  1285. mask = ~(mask << GenAddr->BitOffset);
  1286. data &= mask;
  1287. data |= Value << GenAddr->BitOffset;
  1288. } else {
  1289. data = Value;
  1290. }
  1291. WRITE_PORT_ULONG((PULONG)(UINT_PTR)GenAddr->Address.LowPart,
  1292. data);
  1293. break;
  1294. default:
  1295. return;
  1296. }
  1297. break;
  1298. case AcpiGenericSpaceMemory:
  1299. //
  1300. // This code path depends on the fact that the addresses
  1301. // in these structures have already been converted to
  1302. // virtual addresses.
  1303. //
  1304. switch (bitWidth) {
  1305. case 8:
  1306. ASSERT(!(Value & 0xffffff00));
  1307. if ((GenAddr->BitOffset != 0) ||
  1308. (GenAddr->BitWidth != bitWidth)) {
  1309. data = READ_REGISTER_UCHAR((PUCHAR)GenAddr->Address.QuadPart);
  1310. mask = (UCHAR)~0 >> (8 - GenAddr->BitWidth);
  1311. mask = (UCHAR)~(mask << GenAddr->BitOffset);
  1312. data &= mask;
  1313. data |= (UCHAR)Value << GenAddr->BitOffset;
  1314. } else {
  1315. data = Value;
  1316. }
  1317. WRITE_REGISTER_UCHAR((PUCHAR)GenAddr->Address.QuadPart,
  1318. (UCHAR)data);
  1319. break;
  1320. case 16:
  1321. ASSERT(!(Value & 0xffff0000));
  1322. if ((GenAddr->BitOffset != 0) ||
  1323. (GenAddr->BitWidth != bitWidth)) {
  1324. data = READ_REGISTER_USHORT((PUSHORT)GenAddr->Address.QuadPart);
  1325. mask = (USHORT)~0 >> (16 - GenAddr->BitWidth);
  1326. mask = (USHORT)~(mask << GenAddr->BitOffset);
  1327. data &= mask;
  1328. data |= (USHORT)Value << GenAddr->BitOffset;
  1329. } else {
  1330. data = Value;
  1331. }
  1332. WRITE_REGISTER_USHORT((PUSHORT)GenAddr->Address.QuadPart,
  1333. (USHORT)data);
  1334. break;
  1335. case 32:
  1336. if ((GenAddr->BitOffset != 0) ||
  1337. (GenAddr->BitWidth != bitWidth)) {
  1338. data = READ_REGISTER_ULONG((PULONG)GenAddr->Address.QuadPart);
  1339. mask = (ULONG)~0 >> (32 - GenAddr->BitWidth);
  1340. mask = ~(mask << GenAddr->BitOffset);
  1341. data &= mask;
  1342. data |= Value << GenAddr->BitOffset;
  1343. } else {
  1344. data = Value;
  1345. }
  1346. WRITE_REGISTER_ULONG((PULONG)GenAddr->Address.QuadPart, data);
  1347. break;
  1348. default:
  1349. return;
  1350. }
  1351. break;
  1352. default:
  1353. return;
  1354. }
  1355. }
  1356. NTSTATUS
  1357. HalpGetPlatformProperties(
  1358. OUT PULONG Properties
  1359. )
  1360. /*++
  1361. Routine Description:
  1362. This function retrieves the platform properties as specified in
  1363. the ACPI-style IPPT table if present on this platform. The table
  1364. itself would've been retrieved earlier.
  1365. Arguments:
  1366. Properties - Pointer to a ULONG that will be updated
  1367. to reflect the platform property flags if present.
  1368. Return Value:
  1369. NTSTATUS - STATUS_SUCCESS indicates the table was present and the
  1370. ULONG pointed to by Properties contains valid data.
  1371. --*/
  1372. {
  1373. ULONG properties = 0;
  1374. NTSTATUS status = STATUS_UNSUCCESSFUL;
  1375. if (HalpPlatformPropertiesTable) {
  1376. //
  1377. // map IPPT flag to HAL_PLATFORM flag. Note that these do not
  1378. // necessarily have to match 1:1.
  1379. //
  1380. if (HalpPlatformPropertiesTable->Flags & IPPT_DISABLE_WRITE_COMBINING) {
  1381. properties |= HAL_PLATFORM_DISABLE_WRITE_COMBINING;
  1382. }
  1383. if (HalpPlatformPropertiesTable->Flags & IPPT_DISABLE_PTCG_TB_FLUSH) {
  1384. properties |= HAL_PLATFORM_DISABLE_PTCG;
  1385. }
  1386. if (HalpPlatformPropertiesTable->Flags & IPPT_DISABLE_UC_MAIN_MEMORY) {
  1387. properties |= HAL_PLATFORM_DISABLE_UC_MAIN_MEMORY;
  1388. }
  1389. status = STATUS_SUCCESS;
  1390. }
  1391. if ( HalpPlatformPropertiesEfiFlags ) {
  1392. properties |= HalpPlatformPropertiesEfiFlags;
  1393. status = STATUS_SUCCESS;
  1394. }
  1395. if (NT_SUCCESS(status)) {
  1396. *Properties = properties;
  1397. }
  1398. return( status );
  1399. }
  1400. NTSTATUS
  1401. HalpGetCrossPartitionIpiInterface(
  1402. OUT HAL_CROSS_PARTITION_IPI_INTERFACE * IpiInterface
  1403. )
  1404. /*++
  1405. Routine Description:
  1406. This function fills in the HAL_CROSS_PARTITION_IPI_INTERFACE
  1407. structure pointed to by the argument with the appropriate hal
  1408. function pointers.
  1409. Arguments:
  1410. IpiInterface - Pointer to HAL_CROSS_PARTITION_IPI_INTERFACE
  1411. structure.
  1412. Return Value:
  1413. NTSTATUS
  1414. --*/
  1415. {
  1416. PAGED_CODE();
  1417. IpiInterface->HalSendCrossPartitionIpi = HalpSendCrossPartitionIpi;
  1418. IpiInterface->HalReserveCrossPartitionInterruptVector =
  1419. HalpReserveCrossPartitionInterruptVector;
  1420. return STATUS_SUCCESS;
  1421. }