Source code of Windows XP (NT5)
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.

908 lines
24 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. pmsapic.c
  5. Abstract:
  6. Implements various SAPIC-ACPI functions.
  7. Author:
  8. Todd Kjos (Hewlett-Packard) 20-Apr-1998
  9. Based on I386 version of pmapic.c:
  10. Jake Oshins (jakeo) 19-May-1997
  11. Environment:
  12. Kernel mode only.
  13. Revision History:
  14. --*/
  15. #include "halp.h"
  16. #include "acpitabl.h"
  17. #include "iosapic.h"
  18. #include "xxacpi.h"
  19. #include "ixsleep.h"
  20. PMAPIC HalpApicTable;
  21. struct _IOAPIC_DEBUG_TABLE
  22. {
  23. PIO_INTR_CONTROL IoIntrControl;
  24. PIO_SAPIC_REGS IoSapicRegs;
  25. } *HalpApicDebugAddresses;
  26. ULONG
  27. DetectAcpiMP(
  28. OUT PBOOLEAN IsConfiguredMp,
  29. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  30. );
  31. VOID
  32. HalpInitMPInfo(
  33. IN PLOADER_PARAMETER_BLOCK LoaderBlock,
  34. IN PMAPIC ApicTable
  35. );
  36. BOOLEAN
  37. HalpVerifyIoSapic(
  38. IN PUCHAR BaseAddress
  39. );
  40. VOID
  41. HalpSaveInterruptControllerState(
  42. VOID
  43. );
  44. VOID
  45. HalpRestoreInterruptControllerState(
  46. VOID
  47. );
  48. VOID
  49. HalpSetInterruptControllerWakeupState(
  50. ULONG Context
  51. );
  52. VOID
  53. HalpSetCPEVectorState(
  54. IN ULONG GlobalInterrupt,
  55. IN UCHAR SapicVector,
  56. IN USHORT DestinationCPU,
  57. IN ULONG Flags
  58. );
  59. VOID
  60. HalpProcessLocalSapic(
  61. IN PLOADER_PARAMETER_BLOCK LoaderBlock,
  62. IN PPROCLOCALSAPIC ProcLocalSapic
  63. );
  64. VOID
  65. HalpProcessIoSapic(
  66. IN PLOADER_PARAMETER_BLOCK LoaderBlock,
  67. IN PIOSAPIC IoSapic
  68. );
  69. VOID
  70. HalpProcessIsaVector(
  71. IN PLOADER_PARAMETER_BLOCK LoaderBlock,
  72. IN PISA_VECTOR IsaVector
  73. );
  74. VOID
  75. HalpProcessPlatformInt(
  76. IN PLOADER_PARAMETER_BLOCK LoaderBlock,
  77. IN PPLATFORM_INTERRUPT PlatformInt
  78. );
  79. extern UCHAR rgzNoApicTable[];
  80. extern UCHAR rgzNoApic[];
  81. extern UCHAR rgzApicNotVerified[];
  82. extern ULONG HalpPicVectorRedirect[];
  83. struct _MPINFO HalpMpInfo;
  84. extern ULONG HalpPicVectorFlags[];
  85. extern ULONG HalpIpiClock;
  86. extern BOOLEAN HalpHiberInProgress;
  87. // from pmdata.c: CPE related.
  88. extern ULONG HalpCPEIntIn[];
  89. extern USHORT HalpCPEDestination[];
  90. extern ULONG HalpCPEVectorFlags[];
  91. extern UCHAR HalpCPEIoSapicVector[];
  92. extern ULONG HalpMaxCPEImplemented;
  93. BOOLEAN HalpPicStateIntact = TRUE;
  94. PIO_INTR_CONTROL HalpIoSapicList = NULL;
  95. #ifdef ALLOC_PRAGMA
  96. #pragma alloc_text(INIT, DetectAcpiMP)
  97. #pragma alloc_text(INIT, HalpInitMPInfo)
  98. #pragma alloc_text(INIT, HalpProcessLocalSapic)
  99. #pragma alloc_text(INIT, HalpProcessIoSapic)
  100. #pragma alloc_text(INIT, HalpProcessIsaVector)
  101. #pragma alloc_text(INIT, HalpProcessPlatformInt)
  102. #pragma alloc_text(PAGELK, HalpVerifyIoSapic)
  103. #pragma alloc_text(PAGELK, HalpSaveInterruptControllerState)
  104. #pragma alloc_text(PAGELK, HalpRestoreInterruptControllerState)
  105. #pragma alloc_text(PAGELK, HalpSetInterruptControllerWakeupState)
  106. #pragma alloc_text(PAGELK, HalpAcpiPicStateIntact)
  107. #endif
  108. ULONG
  109. DetectAcpiMP(
  110. OUT PBOOLEAN IsConfiguredMp,
  111. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  112. )
  113. {
  114. UCHAR ApicVersion, index, processorNumber;
  115. PUCHAR LocalApic;
  116. NTSTATUS status;
  117. //
  118. // Make sure there is an SAPIC Table
  119. //
  120. HalpApicTable = HalpGetAcpiTablePhase0(LoaderBlock, APIC_SIGNATURE);
  121. if (HalpApicTable == NULL) {
  122. HalDisplayString(rgzNoApicTable);
  123. KeBugCheckEx(ACPI_BIOS_ERROR, 0x11, 10, 0, 0);
  124. return(FALSE);
  125. }
  126. HalDebugPrint(( HAL_INFO, "HAL: Found a MADT table at %p\n", HalpApicTable ));
  127. HalDebugPrint(( HAL_INFO, "HAL: Signature: %x Length: %x\n",
  128. HalpApicTable->Header.Signature,
  129. HalpApicTable->Header.Length ));
  130. HalDebugPrint(( HAL_INFO, "HAL: OEMID: %s\n", HalpApicTable->Header.OEMID ));
  131. // We have a SAPIC table. Initialize the interrupt info structure
  132. HalpInitMPInfo(LoaderBlock, HalpApicTable);
  133. if (HalpMpInfo.IoSapicCount == 0) {
  134. //
  135. // There are no IO Sapics.
  136. //
  137. // Should we allow this case on the theory that
  138. // that all the interrupts are connected to LINTx pins on the CPU?
  139. //
  140. HalDebugPrint(( HAL_ERROR, rgzNoApic ));
  141. return (FALSE);
  142. }
  143. if (HalpMpInfo.ProcessorCount == 0) {
  144. KeBugCheckEx(ACPI_BIOS_ERROR, 0x11, 11, 0, 0);
  145. }
  146. //
  147. // Initialize NtProcessorNumber in the order that we are going to process
  148. // them in HalStartNextProcessor. The BSP is 0 and the rest are numbered
  149. // in the order the Local SAPICs appear in the MADT starting at 1.
  150. //
  151. processorNumber = 1;
  152. for (index = 0; index < HalpMpInfo.ProcessorCount; index++) {
  153. if (HalpProcessorInfo[index].LocalApicID == (USHORT)PCR->HalReserved[PROCESSOR_ID_INDEX]) {
  154. HalpProcessorInfo[index].NtProcessorNumber = 0;
  155. } else {
  156. HalpProcessorInfo[index].NtProcessorNumber = processorNumber++;
  157. }
  158. }
  159. *IsConfiguredMp = (HalpMpInfo.ProcessorCount > 1 ? TRUE : FALSE);
  160. return TRUE;
  161. }
  162. #define IO_SAPIC_REGS_SIZE 4096
  163. VOID
  164. HalpInitMPInfo(
  165. IN PLOADER_PARAMETER_BLOCK LoaderBlock,
  166. IN PMAPIC ApicTable
  167. )
  168. /*++
  169. Routine Description:
  170. This routine initializes a HAL specific data structure that is
  171. used by the HAL to simplify access to MP information.
  172. Arguments:
  173. SapicTable Pointer to the SAPIC table.
  174. Return Value:
  175. None
  176. */
  177. {
  178. PAPICTABLE TablePtr;
  179. ULONG i;
  180. HalpMpInfo.ProcessorCount = 0;
  181. HalpMpInfo.IoSapicCount = 0;
  182. // Walk the Multiple Apic table...
  183. TablePtr = (PAPICTABLE) ApicTable->APICTables;
  184. // Loop ends when TraversePtr is off the end of the table...
  185. while ((UINT_PTR)TablePtr <
  186. ((UINT_PTR)ApicTable + ApicTable->Header.Length)) {
  187. if (TablePtr->Type == LOCAL_SAPIC) {
  188. HalpProcessLocalSapic(LoaderBlock, (PPROCLOCALSAPIC)TablePtr);
  189. } else if (TablePtr->Type == IO_SAPIC) {
  190. HalpProcessIoSapic(LoaderBlock, (PIOSAPIC)TablePtr);
  191. } else if (TablePtr->Type == ISA_VECTOR_OVERRIDE) {
  192. HalpProcessIsaVector(LoaderBlock, (PISA_VECTOR)TablePtr);
  193. } else if (TablePtr->Type == PLATFORM_INTERRUPT_SOURCE) {
  194. HalpProcessPlatformInt(LoaderBlock, (PPLATFORM_INTERRUPT)TablePtr);
  195. } else {
  196. HalDebugPrint(( HAL_ERROR, "HAL: Processing MADT - Skip Table %p: Type = %d, Length = %d\n", TablePtr, TablePtr->Type, TablePtr->Length ));
  197. }
  198. (UINT_PTR)TablePtr += TablePtr->Length;
  199. }
  200. //
  201. // Check if there is Interrupt Source Override entry. If there is, force the
  202. // new flags into the SAPIC state. This is done now because of the possibility
  203. // the firmware can place the ISO Vector Override entry ahead of IOSAPIC entry.
  204. //
  205. for (i = 0; i < PIC_VECTORS; i++) {
  206. if (HalpPicVectorFlags[i]) {
  207. HaliSetVectorState( HalpPicVectorRedirect[i],
  208. HalpPicVectorFlags[i]
  209. );
  210. }
  211. }
  212. }
  213. VOID
  214. HalpProcessLocalSapic(
  215. IN PLOADER_PARAMETER_BLOCK LoaderBlock,
  216. IN PPROCLOCALSAPIC ProcLocalSapic
  217. )
  218. {
  219. USHORT LID;
  220. ULONG ProcessorNum;
  221. if (ProcLocalSapic->Length != PROCESSOR_LOCAL_SAPIC_LENGTH) {
  222. HalDebugPrint(( HAL_ERROR,
  223. "HAL: HalpProcessLocalSapic - Invalid Length %p: Expected %d, Found %d\n",
  224. ProcLocalSapic,
  225. PROCESSOR_LOCAL_SAPIC_LENGTH,
  226. ProcLocalSapic->Length ));
  227. return;
  228. }
  229. // Make sure processor is enabled...
  230. if (!(ProcLocalSapic->Flags & PLAF_ENABLED)) {
  231. return;
  232. }
  233. // It is. Bump the count and store the LID value for IPIs
  234. LID = (ProcLocalSapic->APICID << 8) | ProcLocalSapic->APICEID;
  235. HalpProcessorInfo[HalpMpInfo.ProcessorCount].AcpiProcessorID = ProcLocalSapic->ACPIProcessorID;
  236. HalpProcessorInfo[HalpMpInfo.ProcessorCount].LocalApicID = LID;
  237. HalpMpInfo.ProcessorCount++;
  238. HalDebugPrint(( HAL_INFO,
  239. "HAL: Found a processor-local SAPIC: %p LID=%x\n",
  240. ProcLocalSapic,
  241. LID ));
  242. }
  243. VOID
  244. HalpProcessIoSapic(
  245. IN PLOADER_PARAMETER_BLOCK LoaderBlock,
  246. IN PIOSAPIC IoSapic
  247. )
  248. {
  249. ULONG IntiBase,RedirEntries;
  250. PHYSICAL_ADDRESS IoSapicPhys;
  251. PVOID IoSapicBase;
  252. UINT_PTR IoSapicPhysBase;
  253. PIO_SAPIC_REGS SapicRegs;
  254. PIO_INTR_CONTROL IoIntrControl;
  255. ULONG i;
  256. union {
  257. ULONG raw;
  258. SAPIC_VERSION version;
  259. } versionUnion;
  260. if (IoSapic->Length != IO_SAPIC_LENGTH) {
  261. HalDebugPrint(( HAL_ERROR,
  262. "HAL: HalpProcessIoSapic - Invalid Length %p: Expected %d, Found %d\n",
  263. IoSapic,
  264. IO_SAPIC_LENGTH,
  265. IoSapic->Length ));
  266. return;
  267. }
  268. HalDebugPrint(( HAL_INFO, "HAL: Found an IO SAPIC: %p\n", IoSapic ));
  269. // Map IO Sapic Registers...
  270. IntiBase = IoSapic->SystemVectorBase;
  271. IoSapicPhysBase = IoSapic->IOSAPICAddress;
  272. IoSapicPhys.QuadPart = (UINT_PTR)IoSapicPhysBase;
  273. IoSapicBase = HalpMapPhysicalMemory( IoSapicPhys,
  274. ADDRESS_AND_SIZE_TO_SPAN_PAGES(IoSapicPhys.LowPart, IO_SAPIC_REGS_SIZE),
  275. MmNonCached);
  276. ASSERT(IoSapicBase);
  277. SapicRegs = (PIO_SAPIC_REGS)IoSapicBase;
  278. if (!SapicRegs) {
  279. HalDebugPrint(( HAL_ERROR, "HAL: Couldn't map the I/O Sapic\n" ));
  280. return;
  281. }
  282. // Read the IO Sapic version and extract the number of redirection table entries
  283. SapicRegs->RegisterSelect = IO_VERS_REGISTER;
  284. SapicRegs->RegisterWindow = 0;
  285. versionUnion.raw = SapicRegs->RegisterWindow;
  286. //
  287. // CPQMOD_JL001 - Incorrect count - hw provide max rte index not
  288. // count.
  289. //
  290. //RedirEntries = versionUnion.version.MaxRedirEntries;
  291. RedirEntries = versionUnion.version.MaxRedirEntries + 1;
  292. if (HalpVerifyIoSapic((PUCHAR)SapicRegs)) {
  293. // Allocate and fill out a IO Sapic structure
  294. PHYSICAL_ADDRESS physicalAddress;
  295. physicalAddress.QuadPart = (LONGLONG)HalpAllocPhysicalMemory(
  296. LoaderBlock,
  297. ~0,
  298. BYTES_TO_PAGES(sizeof(IO_INTR_CONTROL) + (RedirEntries*sizeof(IOSAPICINTI))),
  299. FALSE );
  300. if (physicalAddress.QuadPart == 0) {
  301. HalDebugPrint(( HAL_ERROR, "HAL: Couldn't allocate memory for the IO Sapic structures\n" ));
  302. return;
  303. }
  304. IoIntrControl = (PIO_INTR_CONTROL)HalpMapPhysicalMemory(
  305. physicalAddress,
  306. ADDRESS_AND_SIZE_TO_SPAN_PAGES(physicalAddress.LowPart, sizeof(IO_INTR_CONTROL) + (RedirEntries*sizeof(IOSAPICINTI))),
  307. MmCached );
  308. ASSERT(IoIntrControl);
  309. IoIntrControl->IntiBase = IntiBase;
  310. IoIntrControl->IntiMax = IntiBase + RedirEntries - 1;
  311. IoIntrControl->RegBaseVirtual = IoSapicBase;
  312. IoIntrControl->RegBasePhysical = IoSapicPhys;
  313. IoIntrControl->IntrMethods = &HalpIoSapicMethods;
  314. IoIntrControl->InterruptAffinity = 0xffffffff;
  315. IoIntrControl->NextCpu = 0;
  316. IoIntrControl->flink = NULL;
  317. for (i = 0; i < RedirEntries; i++) {
  318. IoIntrControl->Inti[i].Vector =
  319. DELIVER_FIXED | ACTIVE_LOW | LEVEL_TRIGGERED;
  320. IoIntrControl->Inti[i].Destination = 0;
  321. IoIntrControl->Inti[i].GlobalVector = 0;
  322. //
  323. // CPQMOD_JL002 - Fix for using the rte and not the
  324. // SystemVector.
  325. //
  326. //IoIntrControl->IntrMethods->MaskEntry(IoIntrControl,IntiBase+i);
  327. IoIntrControl->IntrMethods->MaskEntry(IoIntrControl,i);
  328. }
  329. // Insert structure into list. Since we are running on P0 at
  330. // Phase0 initialization, we can assume that no one else is
  331. // modifying this list therefore no synchronization is needed.
  332. if (HalpIoSapicList == NULL) {
  333. HalpIoSapicList = IoIntrControl;
  334. } else {
  335. PIO_INTR_CONTROL *LastLink;
  336. PIO_INTR_CONTROL IoSapicListEntry;
  337. LastLink = &HalpIoSapicList;
  338. IoSapicListEntry = HalpIoSapicList;
  339. while (IoSapicListEntry != NULL) {
  340. if (IoSapicListEntry->IntiBase > IoIntrControl->IntiMax) {
  341. // Insert new entry before current entry
  342. IoIntrControl->flink = *LastLink;
  343. *LastLink = IoIntrControl;
  344. break;
  345. } else {
  346. LastLink = &IoSapicListEntry->flink;
  347. IoSapicListEntry = IoSapicListEntry->flink;
  348. }
  349. }
  350. if (IoSapicListEntry == NULL) {
  351. // We got to the end of the list. The new entry goes
  352. // after the last entry...
  353. *LastLink = IoIntrControl;
  354. }
  355. }
  356. HalpMpInfo.IoSapicCount++;
  357. } else {
  358. // The Io Sapic is not there, ignore this entry in the table
  359. HalDebugPrint(( HAL_ERROR, rgzApicNotVerified ));
  360. HalpUnmapVirtualAddress(IoSapicBase, ADDRESS_AND_SIZE_TO_SPAN_PAGES(IoSapicBase, IO_SAPIC_REGS_SIZE));
  361. }
  362. }
  363. VOID
  364. HalpProcessIsaVector(
  365. IN PLOADER_PARAMETER_BLOCK LoaderBlock,
  366. IN PISA_VECTOR IsaVector
  367. )
  368. {
  369. if (IsaVector->Length != ISA_VECTOR_OVERRIDE_LENGTH) {
  370. HalDebugPrint(( HAL_ERROR,
  371. "HAL: HalpProcessIsaVector - Invalid Length %p: Expected %d, Found %d\n",
  372. IsaVector,
  373. ISA_VECTOR_OVERRIDE_LENGTH,
  374. IsaVector->Length ));
  375. return;
  376. }
  377. //
  378. // Found an ISA vector redirection entry.
  379. //
  380. HalpPicVectorRedirect[IsaVector->Source] =
  381. IsaVector->GlobalSystemInterruptVector;
  382. HalpPicVectorFlags[IsaVector->Source] = IsaVector->Flags;
  383. HalDebugPrint(( HAL_INFO, "HAL: Found an ISA VECTOR: %p, %x -> %x, flags: %x\n",
  384. IsaVector,
  385. IsaVector->Source,
  386. IsaVector->GlobalSystemInterruptVector,
  387. IsaVector->Flags ));
  388. }
  389. VOID
  390. HalpProcessPlatformInt(
  391. IN PLOADER_PARAMETER_BLOCK LoaderBlock,
  392. IN PPLATFORM_INTERRUPT PlatformInt
  393. )
  394. {
  395. static ULONG currentCPECount = 0;
  396. if (PlatformInt->Length != PLATFORM_INTERRUPT_SOURCE_LENGTH) {
  397. HalDebugPrint(( HAL_ERROR,
  398. "HAL: HalpProcessPlatformInt - Invalid Length %p: Expected %d, Found %d\n",
  399. PlatformInt,
  400. PLATFORM_INTERRUPT_SOURCE_LENGTH,
  401. PlatformInt->Length ));
  402. return;
  403. }
  404. //
  405. // Process a Corrected Platform Error Interrupt Source structure.
  406. //
  407. if (PlatformInt->InterruptType == PLATFORM_INT_CPE) {
  408. //
  409. // Does this platform has more (than what we expected) number of CPE sources?
  410. //
  411. if ( currentCPECount >= HALP_CPE_MAX_INTERRUPT_SOURCES ) {
  412. HalDebugPrint(( HAL_ERROR,
  413. "HAL: Platform Interrupt Source %p skipped due to overflow: %ld >= HALP_CPE_MAX_INTERRUPT_SOURCES\n", PlatformInt, currentCPECount ));
  414. return;
  415. }
  416. //
  417. // Save the input pin number of SAPIC for this CPE source
  418. //
  419. HalpCPEIntIn[currentCPECount] = (ULONG)PlatformInt->GlobalVector;
  420. //
  421. // Save the Flags for this CPE source
  422. //
  423. HalpCPEVectorFlags[currentCPECount] = (ULONG)PlatformInt->Flags;
  424. //
  425. // Save the IO Sapic Vector (that BIOS expects OS to use) for this platform CMC source
  426. //
  427. HalpCPEIoSapicVector[currentCPECount] = (UCHAR)PlatformInt->IOSAPICVector;
  428. // Thierry - WARNING - 09/19/2000
  429. // NT HAL ignores the IO SAPIC vector field for the platform interrupt sources.
  430. // NT imposes the CPEI_VECTOR value for Corrected Machine Errors interrupt vector, for all
  431. // the destination processors. Actually, the current default is to attach all the processors
  432. // IDT[CPEI_VECTOR] with the HAL default ISR - HalpCPEIHandler for the CPE interrupt model.
  433. // We will connect the ISR only for the destination processors after testing if judged valid.
  434. // The rationales are:
  435. // - IOSAPICVector was mostly added in the specs by Intel for IA64 PMI interrupt sources.
  436. // These PMI interrupts are not visible by NT.
  437. // - NT has no infrastructure at this time to support vector registration for FW/chipset
  438. // generated external interrupts visible to NT.
  439. // - Having the FW specifying the vector requires the HAL to control the specified
  440. // value with its current IDT[] related resources usage and defines actions in case
  441. // of conficts.
  442. //
  443. HalDebugPrint(( HAL_INFO, "HAL: CPE source VECTOR: %x. HAL imposes VECTOR: %x\n",
  444. HalpCPEIoSapicVector[currentCPECount],
  445. CPEI_VECTOR ));
  446. HalpCPEIoSapicVector[currentCPECount] = (UCHAR)(CPEI_VECTOR);
  447. //
  448. // Save the Destination Processor (that BIOS expects OS to use) for this CPE source)
  449. //
  450. HalpCPEDestination[currentCPECount] = (USHORT)(
  451. (PlatformInt->APICID << 8) | PlatformInt->ACPIEID);
  452. //
  453. // Force the flags into the SAPIC state
  454. //
  455. HalpSetCPEVectorState( HalpCPEIntIn[currentCPECount],
  456. HalpCPEIoSapicVector[currentCPECount],
  457. HalpCPEDestination[currentCPECount],
  458. HalpCPEVectorFlags[currentCPECount]
  459. );
  460. HalDebugPrint(( HAL_INFO, "HAL: Found an Platform Interrupt VECTOR: %p, %x -> %x, flags: %x\n",
  461. PlatformInt,
  462. PlatformInt->IOSAPICVector,
  463. PlatformInt->GlobalVector,
  464. PlatformInt->Flags ));
  465. //
  466. // Keep track of how many CPE sources are implemented in the platform.
  467. //
  468. HalpMaxCPEImplemented = ++currentCPECount;
  469. }
  470. else if ( ( PlatformInt->InterruptType == PLATFORM_INT_PMI ) ||
  471. ( PlatformInt->InterruptType == PLATFORM_INT_INIT ) ) {
  472. HalpWriteRedirEntry( PlatformInt->GlobalVector,
  473. PlatformInt->IOSAPICVector,
  474. (USHORT)((PlatformInt->APICID <<8) | PlatformInt->ACPIEID),
  475. PlatformInt->Flags,
  476. PlatformInt->InterruptType
  477. );
  478. }
  479. return;
  480. }
  481. BOOLEAN
  482. HalpVerifyIoSapic(
  483. IN PUCHAR BaseAddress
  484. )
  485. /*++
  486. Routine Description:
  487. Verify that an IO Sapic Unit exists at the specified address
  488. Arguments:
  489. BaseAddress - Virtual address of the IO Unit to test.
  490. Return Value:
  491. BOOLEAN - TRUE if a IO Unit was found at the passed address
  492. - FALSE otherwise
  493. --*/
  494. {
  495. union SapicUnion {
  496. ULONG Raw;
  497. struct SapicVersion Ver;
  498. } Temp1, Temp2;
  499. PIO_SAPIC_REGS IoUnitPtr = (PIO_SAPIC_REGS) BaseAddress;
  500. //
  501. // The documented detection mechanism is to write all zeros to
  502. // the Version register. Then read it back. The IO Unit exists if the
  503. // same result is read both times and the Version is valid.
  504. //
  505. IoUnitPtr->RegisterSelect = IO_VERS_REGISTER;
  506. IoUnitPtr->RegisterWindow = 0;
  507. IoUnitPtr->RegisterSelect = IO_VERS_REGISTER;
  508. Temp1.Raw = IoUnitPtr->RegisterWindow;
  509. IoUnitPtr->RegisterSelect = IO_VERS_REGISTER;
  510. IoUnitPtr->RegisterWindow = 0;
  511. IoUnitPtr->RegisterSelect = IO_VERS_REGISTER;
  512. Temp2.Raw = IoUnitPtr->RegisterWindow;
  513. if ( Temp1.Raw == 0 ||
  514. (Temp1.Ver.Version != Temp2.Ver.Version) ||
  515. (Temp1.Ver.MaxRedirEntries != Temp2.Ver.MaxRedirEntries)) {
  516. //
  517. // No IO Unit There
  518. //
  519. HalDebugPrint(( HAL_ERROR, "HAL: No IoSapic at %I64x\n", BaseAddress ));
  520. return (FALSE);
  521. }
  522. HalDebugPrint(( HAL_INFO, "HAL: IoSapic found at %I64x, Max Entries = %d\n", BaseAddress, Temp1.Ver.MaxRedirEntries ));
  523. return (TRUE);
  524. }
  525. VOID
  526. HalpInitApicDebugMappings(
  527. VOID
  528. )
  529. /*++
  530. Routine Description:
  531. This routine is called at the very beginning of phase 1 initialization.
  532. It creates mappings for the APICs using MmMapIoSpace. This will allow
  533. us to access their registers from the debugger.
  534. A much better solution would be to allow us to describe our memory usage to
  535. MM but ....
  536. Arguments:
  537. Return Value:
  538. --*/
  539. {
  540. PHYSICAL_ADDRESS physicalAddress;
  541. PIO_INTR_CONTROL IoIntrControl;
  542. ULONG index;
  543. if (HalpMpInfo.IoSapicCount == 0) {
  544. //
  545. // I doubt this machine is going to get very far without IOAPICs
  546. // but there is certainly nothing for this routine to do.
  547. return;
  548. }
  549. ASSERT(HalpApicDebugAddresses == NULL);
  550. HalpApicDebugAddresses = ExAllocatePool(NonPagedPool,
  551. HalpMpInfo.IoSapicCount * sizeof(*HalpApicDebugAddresses));
  552. if (HalpApicDebugAddresses == NULL) {
  553. return;
  554. }
  555. IoIntrControl = HalpIoSapicList;
  556. for (index = 0; index < HalpMpInfo.IoSapicCount; index++) {
  557. if (IoIntrControl != NULL) {
  558. if (HalpVirtualToPhysical((ULONG_PTR)IoIntrControl, &physicalAddress)) {
  559. HalpApicDebugAddresses[index].IoIntrControl =
  560. MmMapIoSpace(physicalAddress,
  561. sizeof(IO_INTR_CONTROL) +
  562. (IoIntrControl->IntiMax - IoIntrControl->IntiBase + 1) * sizeof(IOSAPICINTI),
  563. MmCached
  564. );
  565. }
  566. HalpApicDebugAddresses[index].IoSapicRegs =
  567. MmMapIoSpace(IoIntrControl->RegBasePhysical,
  568. IO_SAPIC_REGS_SIZE,
  569. MmNonCached
  570. );
  571. IoIntrControl = IoIntrControl->flink;
  572. } else {
  573. HalpApicDebugAddresses[index].IoIntrControl = NULL;
  574. HalpApicDebugAddresses[index].IoSapicRegs = NULL;
  575. }
  576. }
  577. }
  578. VOID
  579. HalpSaveInterruptControllerState(
  580. VOID
  581. )
  582. {
  583. HalDebugPrint(( HAL_ERROR, "HAL: HalpSaveInterruptControllerState - not yet implemented\n"));
  584. HalpHiberInProgress = TRUE;
  585. }
  586. VOID
  587. HalpRestoreInterruptControllerState(
  588. VOID
  589. )
  590. {
  591. //
  592. // Restore the IO APIC state
  593. //
  594. HalDebugPrint(( HAL_ERROR, "HAL: HalpRestoreInterruptControllerState - not yet implemented\n"));
  595. HalpPicStateIntact = TRUE;
  596. }
  597. VOID
  598. HalpSetInterruptControllerWakeupState(
  599. ULONG Context
  600. )
  601. {
  602. HalDebugPrint(( HAL_FATAL_ERROR, "HAL: HalpSetInterruptControllerWakeupState - not yet implemented\n"));
  603. KeBugCheckEx(HAL_INITIALIZATION_FAILED, 0, 0, 0 , 0);
  604. }
  605. BOOLEAN
  606. HalpAcpiPicStateIntact(
  607. VOID
  608. )
  609. {
  610. return HalpPicStateIntact;
  611. }
  612. ULONG
  613. HalpAcpiNumProcessors(
  614. VOID
  615. )
  616. {
  617. return HalpMpInfo.ProcessorCount;
  618. }
  619. VOID
  620. HalpMaskAcpiInterrupt(
  621. VOID
  622. )
  623. {
  624. ULONG inti;
  625. KAFFINITY affinity;
  626. ULONG sciVector = HalpFixedAcpiDescTable.sci_int_vector;
  627. if (sciVector < PIC_VECTORS) {
  628. sciVector = HalpPicVectorRedirect[sciVector];
  629. }
  630. HalpGetSapicInterruptDesc(
  631. Internal,
  632. 0,
  633. sciVector,
  634. &inti,
  635. &affinity
  636. );
  637. HalpDisableRedirEntry(inti);
  638. }
  639. VOID
  640. HalpUnmaskAcpiInterrupt(
  641. VOID
  642. )
  643. {
  644. ULONG inti;
  645. KAFFINITY affinity;
  646. ULONG sciVector = HalpFixedAcpiDescTable.sci_int_vector;
  647. if (sciVector < PIC_VECTORS) {
  648. sciVector = HalpPicVectorRedirect[sciVector];
  649. }
  650. HalpGetSapicInterruptDesc(
  651. Internal,
  652. 0,
  653. sciVector,
  654. &inti,
  655. &affinity
  656. );
  657. HalpEnableRedirEntry(inti);
  658. }
  659. NTSTATUS
  660. HalpGetApicIdByProcessorNumber(
  661. IN UCHAR Processor,
  662. IN OUT USHORT *ApicId
  663. )
  664. /*++
  665. Routine Description:
  666. This function returns an APIC ID for a given processor.
  667. Arguments:
  668. Processor - The logical processor number that is
  669. associated with this APIC ID.
  670. ApicId - pointer to a value to fill in with the APIC ID.
  671. Return Value:
  672. Status.
  673. --*/
  674. {
  675. ULONG index;
  676. for (index = 0; index < HalpMpInfo.ProcessorCount; index++) {
  677. if (HalpProcessorInfo[index].NtProcessorNumber == Processor) {
  678. //
  679. // Return the APIC ID, Extended APIC ID for this
  680. // processor.
  681. //
  682. *ApicId = HalpProcessorInfo[index].LocalApicID;
  683. return STATUS_SUCCESS;
  684. }
  685. }
  686. return STATUS_NOT_FOUND;
  687. }