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.

863 lines
21 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. pmapic.c
  5. Abstract:
  6. Implements various APIC-ACPI functions.
  7. Author:
  8. Jake Oshins (jakeo) 19-May-1997
  9. Environment:
  10. Kernel mode only.
  11. Revision History:
  12. --*/
  13. #include "halp.h"
  14. #include "acpitabl.h"
  15. #include "apic.inc"
  16. #include "xxacpi.h"
  17. #include "ixsleep.h"
  18. #ifdef DEBUGGING
  19. #include "string.h"
  20. #include "stdlib.h"
  21. #include "stdio.h"
  22. #endif
  23. ULONG
  24. DetectAcpiMP (
  25. OUT PBOOLEAN IsConfiguredMp,
  26. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  27. );
  28. VOID
  29. HalpInitMpInfo (
  30. IN PMAPIC ApicTable,
  31. IN ULONG Phase
  32. );
  33. BOOLEAN
  34. HalpVerifyIOUnit(
  35. IN PUCHAR BaseAddress
  36. );
  37. VOID
  38. HalpMaskAcpiInterrupt(
  39. VOID
  40. );
  41. VOID
  42. HalpUnmaskAcpiInterrupt(
  43. VOID
  44. );
  45. extern UCHAR rgzNoApicTable[];
  46. extern UCHAR rgzNoApic[];
  47. extern UCHAR rgzBadApicVersion[];
  48. extern UCHAR rgzApicNotVerified[];
  49. extern ULONG HalpPicVectorRedirect[];
  50. extern ULONG HalpPicVectorFlags[];
  51. extern USHORT HalpMaxApicInti[];
  52. extern UCHAR HalpIoApicId[];
  53. extern ULONG HalpIpiClock;
  54. extern PVOID *HalpLocalNmiSources;
  55. ULONG HalpIOApicVersion[MAX_IOAPICS];
  56. extern BOOLEAN HalpHiberInProgress;
  57. BOOLEAN HalpPicStateIntact = TRUE;
  58. UCHAR HalpMaxProcs = 0;
  59. #ifdef ALLOC_PRAGMA
  60. #pragma alloc_text(INIT, DetectAcpiMP)
  61. #pragma alloc_text(PAGELK, HalpInitMpInfo)
  62. #pragma alloc_text(PAGELK, HalpVerifyIOUnit)
  63. #pragma alloc_text(PAGELK, HalpSaveInterruptControllerState)
  64. #pragma alloc_text(PAGELK, HalpRestoreInterruptControllerState)
  65. #pragma alloc_text(PAGELK, HalpSetInterruptControllerWakeupState)
  66. #pragma alloc_text(PAGELK, HalpAcpiPicStateIntact)
  67. #pragma alloc_text(PAGELK, HalpGetApicVersion)
  68. #pragma alloc_text(PAGELK, HalpMaskAcpiInterrupt)
  69. #pragma alloc_text(PAGELK, HalpUnmaskAcpiInterrupt)
  70. #endif
  71. ULONG
  72. DetectAcpiMP(
  73. OUT PBOOLEAN IsConfiguredMp,
  74. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  75. )
  76. {
  77. UCHAR ApicVersion, i;
  78. PUCHAR LocalApic;
  79. #ifdef DEBUGGING
  80. CHAR string[100];
  81. #endif
  82. PHYSICAL_ADDRESS physicalAddress;
  83. //
  84. // Initialize MpInfo table
  85. //
  86. RtlZeroMemory (&HalpMpInfoTable, sizeof(MP_INFO));
  87. //
  88. // Set the return Values to the default
  89. //
  90. *IsConfiguredMp = FALSE;
  91. //
  92. // See if there is an APIC Table
  93. //
  94. if ((HalpApicTable = HalpGetAcpiTablePhase0(LoaderBlock, APIC_SIGNATURE)) == NULL) {
  95. HalDisplayString(rgzNoApicTable);
  96. return(FALSE);
  97. }
  98. // We have an APIC table. Initialize a HAL specific MP information
  99. // structure that gets information from the MAPIC table.
  100. #ifdef DEBUGGING
  101. sprintf(string, "Signature: %x Length: %x\n",
  102. HalpApicTable->Header.Signature,
  103. HalpApicTable->Header.Length);
  104. HalDisplayString(string);
  105. sprintf(string, "OEMID: %s\n", HalpApicTable->Header.OEMID);
  106. HalDisplayString(string);
  107. sprintf(string, "Local Apic Address: %x\n", HalpApicTable->LocalAPICAddress);
  108. HalDisplayString(string);
  109. sprintf(string, "Flags: %x\n", HalpApicTable->Flags);
  110. HalDisplayString(string);
  111. #endif
  112. HalpInitMpInfo(HalpApicTable, 0);
  113. // Verify the information in the MAPIC table as best as we can.
  114. if (HalpMpInfoTable.IOApicCount == 0) {
  115. //
  116. // Someone Has a MP Table and no IO Units -- Weird
  117. // We have to assume the BIOS knew what it was doing
  118. // when it built the table. so ..
  119. //
  120. HalDisplayString (rgzNoApic);
  121. return (FALSE);
  122. }
  123. //
  124. // It's an APIC System. It could be a UP System though.
  125. //
  126. if (HalpMpInfoTable.ProcessorCount > 1) {
  127. *IsConfiguredMp = TRUE;
  128. }
  129. HalpMpInfoTable.LocalApicBase = (ULONG) HalpApicTable->LocalAPICAddress;
  130. physicalAddress =
  131. HalpPtrToPhysicalAddress( (PVOID)HalpMpInfoTable.LocalApicBase );
  132. LocalApic = (PUCHAR) HalpMapPhysicalMemoryWriteThrough( physicalAddress,
  133. 1 );
  134. HalpRemapVirtualAddress (
  135. (PVOID) LOCALAPIC,
  136. physicalAddress,
  137. TRUE
  138. );
  139. ApicVersion = (UCHAR) *(LocalApic + LU_VERS_REGISTER);
  140. if (ApicVersion > 0x1f) {
  141. //
  142. // Only known Apics are 82489dx with version 0.x and
  143. // Embedded Apics with version 1.x (where x is don't care)
  144. //
  145. // Return of 0xFF? Can't have an MPS system without a Local Unit.
  146. //
  147. #ifdef DEBUGGING
  148. sprintf(string, "HALMPS: apic version %x, read from %x\n",
  149. ApicVersion, LocalApic + LU_VERS_REGISTER);
  150. HalDisplayString(string);
  151. #endif
  152. HalDisplayString (rgzBadApicVersion);
  153. return (FALSE);
  154. }
  155. for(i=0; i < HalpMpInfoTable.IOApicCount; i++)
  156. {
  157. //
  158. // Verify the existance of the IO Unit
  159. //
  160. if (!(HalpVerifyIOUnit((PUCHAR)HalpMpInfoTable.IoApicBase[i]))) {
  161. HalDisplayString (rgzApicNotVerified);
  162. return (FALSE);
  163. }
  164. }
  165. HalDisplayString("HAL: DetectAPIC: APIC system found - Returning TRUE\n");
  166. return TRUE;
  167. }
  168. VOID
  169. HalpInitMpInfo (
  170. IN PMAPIC ApicTable,
  171. IN ULONG Phase
  172. )
  173. /*++
  174. Routine Description:
  175. This routine initializes a HAL specific data structure that is
  176. used by the HAL to simplify access to MP information.
  177. Arguments:
  178. ApicTable - Pointer to the APIC table.
  179. Phase - indicates which pass we are are doing through the table.
  180. Return Value:
  181. Pointer to the HAL MP information table.
  182. */
  183. {
  184. PUCHAR TraversePtr;
  185. UCHAR CheckSum;
  186. UCHAR apicNo = 0;
  187. ULONG nmiSources = 0;
  188. #ifdef DEBUGGING
  189. CHAR string[100];
  190. #endif
  191. PIO_APIC_UNIT apic;
  192. PHYSICAL_ADDRESS physicalAddress;
  193. PIOAPIC ioApic;
  194. UCHAR totalProcs = 0;
  195. union {
  196. ULONG raw;
  197. APIC_VERSION version;
  198. } versionUnion;
  199. // Walk the MAPIC table.
  200. TraversePtr = (PUCHAR) ApicTable->APICTables;
  201. //
  202. // ACPI machines have embedded APICs.
  203. //
  204. HalpMpInfoTable.ApicVersion = 0x10;
  205. #ifdef DUMP_MAPIC_TABLE
  206. while ((ULONG)TraversePtr <
  207. ((ULONG)ApicTable + ApicTable->Header.Length)) {
  208. sprintf(string, "%08x %08x %08x %08x\n",
  209. *(PULONG)TraversePtr,
  210. *(PULONG)(TraversePtr + 4),
  211. *(PULONG)(TraversePtr + 8),
  212. *(PULONG)(TraversePtr + 12)
  213. );
  214. HalDisplayString(string);
  215. TraversePtr += 16;
  216. }
  217. TraversePtr = (PUCHAR) ApicTable->APICTables;
  218. #endif
  219. if (!(ApicTable->Flags & PCAT_COMPAT)) {
  220. //
  221. // This HAL can't actually handle a machine without 8259's,
  222. // even though it doesn't use them.
  223. //
  224. KeBugCheckEx(MISMATCHED_HAL,
  225. 6, 0, 0, 0);
  226. }
  227. while ((ULONG)TraversePtr <
  228. ((ULONG)ApicTable + ApicTable->Header.Length)) {
  229. if ((((PPROCLOCALAPIC)(TraversePtr))->Type == PROCESSOR_LOCAL_APIC)
  230. && (((PPROCLOCALAPIC)(TraversePtr))->Length == PROCESSOR_LOCAL_APIC_LENGTH)) {
  231. #ifdef DEBUGGING
  232. sprintf(string, "Found a processor-local APIC: %x\n", TraversePtr);
  233. HalDisplayString(string);
  234. #endif
  235. if (Phase == 0) {
  236. if(((PPROCLOCALAPIC)(TraversePtr))->Flags & PLAF_ENABLED) {
  237. //
  238. // This processor is enabled, so keep track of useful stuff.
  239. //
  240. HalpProcLocalApicTable[HalpMpInfoTable.ProcessorCount].NamespaceProcID =
  241. ((PPROCLOCALAPIC)(TraversePtr))->ACPIProcessorID;
  242. HalpProcLocalApicTable[HalpMpInfoTable.ProcessorCount].ApicID =
  243. ((PPROCLOCALAPIC)(TraversePtr))->APICID;
  244. HalpMpInfoTable.ProcessorCount += 1;
  245. }
  246. }
  247. totalProcs++;
  248. HalpMaxProcs = (totalProcs > HalpMaxProcs) ? totalProcs : HalpMaxProcs;
  249. TraversePtr += ((PPROCLOCALAPIC)(TraversePtr))->Length;
  250. } else if ((((PIOAPIC)(TraversePtr))->Type == IO_APIC) &&
  251. (((PIOAPIC)(TraversePtr))->Length == IO_APIC_LENGTH)) {
  252. #ifdef DEBUGGING
  253. sprintf(string, "Found an IO APIC: [%x] %x\n",
  254. HalpMpInfoTable.IOApicCount,
  255. TraversePtr);
  256. HalDisplayString(string);
  257. #endif
  258. ioApic = (PIOAPIC)TraversePtr;
  259. if (Phase == 0) {
  260. //
  261. // Found an IO APIC entry. Record the info from
  262. // the table.
  263. //
  264. apicNo = (UCHAR)HalpMpInfoTable.IOApicCount;
  265. HalpIoApicId[apicNo] = ioApic->IOAPICID;
  266. HalpMpInfoTable.IoApicIntiBase[apicNo] =
  267. ioApic->SystemVectorBase;
  268. HalpMpInfoTable.IoApicPhys[apicNo] =
  269. ioApic->IOAPICAddress;
  270. //
  271. // Get a virtual address for it.
  272. //
  273. physicalAddress = HalpPtrToPhysicalAddress(
  274. (PVOID)ioApic->IOAPICAddress );
  275. HalpMpInfoTable.IoApicBase[apicNo] =
  276. HalpMapPhysicalMemoryWriteThrough( physicalAddress, 1 );
  277. apic = (PIO_APIC_UNIT)HalpMpInfoTable.IoApicBase[apicNo];
  278. if (!apic) {
  279. #ifdef DEBUGGING
  280. sprintf(string, "Couldn't map the I/O apic\n");
  281. HalDisplayString(string);
  282. #endif
  283. return;
  284. }
  285. //
  286. // Dig the number of Intis out of the hardware.
  287. //
  288. apic->RegisterSelect = IO_VERS_REGISTER;
  289. apic->RegisterWindow = 0;
  290. versionUnion.raw = apic->RegisterWindow;
  291. HalpMaxApicInti[apicNo] = versionUnion.version.MaxRedirEntries + 1;
  292. //
  293. // Also store the version so that it can be retrieved by the ACPI driver
  294. //
  295. HalpIOApicVersion[apicNo] = versionUnion.raw;
  296. #ifdef DEBUGGING
  297. sprintf(string, "GSIV base: %x PhysAddr: %x VirtAddr: %x Intis: %x\n",
  298. HalpMpInfoTable.IoApicVectorBase[apicNo],
  299. HalpMpInfoTable.IoApicPhys[apicNo],
  300. HalpMpInfoTable.IoApicBase[apicNo],
  301. HalpMaxApicInti[apicNo]);
  302. HalDisplayString(string);
  303. #endif
  304. HalpMpInfoTable.IOApicCount += 1;
  305. }
  306. TraversePtr += ioApic->Length;
  307. } else if ((((PISA_VECTOR)TraversePtr)->Type == ISA_VECTOR_OVERRIDE) &&
  308. (((PISA_VECTOR)TraversePtr)->Length == ISA_VECTOR_OVERRIDE_LENGTH)) {
  309. #ifdef DEBUGGING
  310. sprintf(string, "Found an ISA VECTOR: %x, %x -> %x, flags: %x\n",
  311. TraversePtr,
  312. ((PISA_VECTOR)TraversePtr)->Source,
  313. ((PISA_VECTOR)TraversePtr)->GlobalSystemInterruptVector,
  314. ((PISA_VECTOR)TraversePtr)->Flags
  315. );
  316. HalDisplayString(string);
  317. #endif
  318. if (Phase == 0) {
  319. //
  320. // Found an ISA vector redirection entry.
  321. //
  322. HalpPicVectorRedirect[((PISA_VECTOR)TraversePtr)->Source] =
  323. ((PISA_VECTOR)TraversePtr)->GlobalSystemInterruptVector;
  324. HalpPicVectorFlags[((PISA_VECTOR)TraversePtr)->Source] =
  325. ((PISA_VECTOR)TraversePtr)->Flags;
  326. }
  327. TraversePtr += ISA_VECTOR_OVERRIDE_LENGTH;
  328. } else if ((((PIO_NMISOURCE)TraversePtr)->Type == IO_NMI_SOURCE) &&
  329. (((PIO_NMISOURCE)TraversePtr)->Length == IO_NMI_SOURCE_LENGTH)) {
  330. if (Phase == 1) {
  331. BOOLEAN found;
  332. USHORT inti;
  333. found = HalpGetApicInterruptDesc(0,
  334. 0,
  335. ((PIO_NMISOURCE)TraversePtr)->GlobalSystemInterruptVector,
  336. &inti);
  337. if (found) {
  338. HalpIntiInfo[inti].Type = INT_TYPE_NMI;
  339. HalpIntiInfo[inti].Level =
  340. (((((((PIO_NMISOURCE)TraversePtr)->Flags & EL_BITS) == EL_EDGE_TRIGGERED) ||
  341. ((PIO_NMISOURCE)TraversePtr)->Flags & EL_BITS) == EL_CONFORMS_WITH_BUS)
  342. ? CFG_EDGE : CFG_LEVEL);
  343. HalpIntiInfo[inti].Polarity =
  344. ((PIO_NMISOURCE)TraversePtr)->Flags & PO_BITS;
  345. }
  346. }
  347. TraversePtr += IO_NMI_SOURCE_LENGTH;
  348. } else if ((((PLOCAL_NMISOURCE)TraversePtr)->Type == LOCAL_NMI_SOURCE) &&
  349. (((PLOCAL_NMISOURCE)TraversePtr)->Length == LOCAL_NMI_SOURCE_LENGTH)) {
  350. if (Phase == 1) {
  351. //
  352. // While running through phase 1, we should catalog local NMI sources.
  353. //
  354. if (!HalpLocalNmiSources) {
  355. //
  356. // Allocate enough pool to point to all the possible local NMI structures.
  357. // Since there are two NMI pins on each processor, this is the number of processors
  358. // times two times the size of a pointer.
  359. //
  360. HalpLocalNmiSources = ExAllocatePoolWithTag(NonPagedPool,
  361. sizeof(PVOID) * HalpMaxProcs * 2,
  362. HAL_POOL_TAG);
  363. RtlZeroMemory(HalpLocalNmiSources,
  364. sizeof(PVOID) * HalpMaxProcs * 2);
  365. }
  366. HalpLocalNmiSources[nmiSources++] = (PVOID)TraversePtr;
  367. }
  368. TraversePtr += LOCAL_NMI_SOURCE_LENGTH;
  369. } else {
  370. #ifdef DEBUGGING
  371. sprintf(string, "%x: %x \n", TraversePtr, *TraversePtr);
  372. HalDisplayString(string);
  373. #endif
  374. //
  375. // Found random bits in the table. Try the next byte and
  376. // see if we can make sense of it.
  377. //
  378. TraversePtr += 1;
  379. }
  380. }
  381. return;
  382. }
  383. BOOLEAN
  384. HalpVerifyIOUnit(
  385. IN PUCHAR BaseAddress
  386. )
  387. /*++
  388. Routine Description:
  389. Verify that an IO Unit exists at the specified address
  390. Arguments:
  391. BaseAddress - Virtual address of the IO Unit to test.
  392. Return Value:
  393. BOOLEAN - TRUE if a IO Unit was found at the passed address
  394. - FALSE otherwise
  395. --*/
  396. {
  397. union ApicUnion {
  398. ULONG Raw;
  399. struct ApicVersion Ver;
  400. } Temp1, Temp2;
  401. struct ApicIoUnit *IoUnitPtr = (struct ApicIoUnit *) BaseAddress;
  402. //
  403. // The documented detection mechanism is to write all zeros to
  404. // the Version register. Then read it back. The IO Unit exists if the
  405. // same result is read both times and the Version is valid.
  406. //
  407. IoUnitPtr->RegisterSelect = IO_VERS_REGISTER;
  408. IoUnitPtr->RegisterWindow = 0;
  409. IoUnitPtr->RegisterSelect = IO_VERS_REGISTER;
  410. Temp1.Raw = IoUnitPtr->RegisterWindow;
  411. IoUnitPtr->RegisterSelect = IO_VERS_REGISTER;
  412. IoUnitPtr->RegisterWindow = 0;
  413. IoUnitPtr->RegisterSelect = IO_VERS_REGISTER;
  414. Temp2.Raw = IoUnitPtr->RegisterWindow;
  415. if ((Temp1.Ver.Version != Temp2.Ver.Version) ||
  416. (Temp1.Ver.MaxRedirEntries != Temp2.Ver.MaxRedirEntries)) {
  417. //
  418. // No IO Unit There
  419. //
  420. return (FALSE);
  421. }
  422. return (TRUE);
  423. }
  424. #ifdef DEBUGGING
  425. struct PcMpTable *PcMpTablePtr, *PcMpDefaultTablePtrs[];
  426. void
  427. ComputeCheckSum(UCHAR This, UCHAR That)
  428. {
  429. }
  430. #endif
  431. VOID
  432. HalpSaveInterruptControllerState(
  433. VOID
  434. )
  435. {
  436. HalpHiberInProgress = TRUE;
  437. }
  438. VOID
  439. HalpRestoreInterruptControllerState(
  440. VOID
  441. )
  442. {
  443. //
  444. // Restore the IO APIC state
  445. //
  446. HalpRestoreIoApicRedirTable();
  447. HalpPicStateIntact = TRUE;
  448. }
  449. VOID
  450. HalpSetInterruptControllerWakeupState(
  451. ULONG Context
  452. )
  453. {
  454. LOADER_PARAMETER_BLOCK LoaderBlock;
  455. SLEEP_STATE_CONTEXT sleepContext;
  456. BOOLEAN IsMpSystem;
  457. ULONG flags;
  458. KIRQL OldIrql;
  459. KPRCB Prcb;
  460. ULONG ii;
  461. USHORT inti;
  462. ULONG localApicId;
  463. ULONG oldProcNumber, oldProcsStarted;
  464. ULONG localApicBase;
  465. sleepContext.AsULONG = Context;
  466. _asm {
  467. pushfd
  468. pop eax
  469. mov flags, eax
  470. cli
  471. }
  472. if (sleepContext.bits.Flags & SLEEP_STATE_RESTART_OTHER_PROCESSORS) {
  473. //
  474. // If you are remapping local apic, io apic and ACPI MAPIC table
  475. // resources, you first have to unmap the current resources!!!
  476. // The BIOS may have created the MAPIC table at a different place or may
  477. // have changed values like processor local APIC IDs. Reparse it.
  478. //
  479. ASSERT(HalpApicTable);
  480. oldProcNumber = HalpMpInfoTable.ProcessorCount;
  481. oldProcsStarted = HalpMpInfoTable.NtProcessors;
  482. localApicBase = HalpMpInfoTable.LocalApicBase;
  483. HalpUnMapIOApics();
  484. RtlZeroMemory (&HalpMpInfoTable, sizeof(MP_INFO));
  485. RtlZeroMemory(HalpProcLocalApicTable,
  486. sizeof(PROC_LOCAL_APIC) * MAX_PROCESSORS);
  487. HalpInitMpInfo(HalpApicTable, 0);
  488. if (HalpMpInfoTable.ProcessorCount != oldProcNumber) {
  489. KeBugCheckEx(HAL_INITIALIZATION_FAILED,
  490. 0x2000,
  491. oldProcNumber,
  492. HalpMpInfoTable.ProcessorCount,
  493. 0);
  494. }
  495. HalpMpInfoTable.NtProcessors = oldProcsStarted;
  496. HalpMpInfoTable.LocalApicBase = localApicBase;
  497. RtlZeroMemory(&LoaderBlock, sizeof(LoaderBlock));
  498. RtlZeroMemory(&Prcb, sizeof(Prcb));
  499. LoaderBlock.Prcb = (ULONG) &Prcb;
  500. }
  501. //
  502. // Initialize minimum global hardware state needed.
  503. //
  504. HalpIpiClock = 0;
  505. HalpInitializeIOUnits();
  506. HalpInitializePICs(FALSE);
  507. HalpSet8259Mask(HalpGlobal8259Mask);
  508. //
  509. // Initialize boot processor's local APIC so it can wake other processors
  510. //
  511. HalpInitializeLocalUnit ();
  512. KeRaiseIrql(HIGH_LEVEL, &OldIrql);
  513. //
  514. // Wake up the other processors
  515. //
  516. if (sleepContext.bits.Flags & SLEEP_STATE_RESTART_OTHER_PROCESSORS) {
  517. //
  518. // Fill in this processor's Apic ID.
  519. //
  520. localApicId = *(PVULONG)(LOCALAPIC + LU_ID_REGISTER);
  521. localApicId &= APIC_ID_MASK;
  522. localApicId >>= APIC_ID_SHIFT;
  523. ((PHALPRCB)KeGetPcr()->Prcb->HalReserved)->PCMPApicID = (UCHAR)localApicId;
  524. //
  525. // Mark this processor as started.
  526. //
  527. for (ii = 0; ii < HalpMpInfoTable.NtProcessors; ii++) {
  528. if (HalpProcLocalApicTable[ii].ApicID ==
  529. ((PHALPRCB)KeGetPcr()->Prcb->HalReserved)->PCMPApicID) {
  530. HalpProcLocalApicTable[ii].Started = TRUE;
  531. HalpProcLocalApicTable[ii].Enumerated = TRUE;
  532. break;
  533. }
  534. }
  535. ASSERT(ii != HalpMpInfoTable.ProcessorCount);
  536. for(ii = 1; ii < HalpMpInfoTable.NtProcessors; ++ii) {
  537. // Set processor number in dummy loader parameter block
  538. Prcb.Number = (UCHAR) ii;
  539. CurTiledCr3LowPart = HalpTiledCr3Addresses[ii].LowPart;
  540. if (!HalStartNextProcessor(&LoaderBlock, &HalpHiberProcState[ii])) {
  541. //
  542. // We could not start a processor. This is a fatal error.
  543. //
  544. KeBugCheckEx(HAL_INITIALIZATION_FAILED,
  545. 0x2001,
  546. oldProcNumber,
  547. HalpMpInfoTable.NtProcessors,
  548. 0);
  549. }
  550. }
  551. }
  552. //
  553. // Enable the clock interrupt.
  554. //
  555. HalpGetApicInterruptDesc(
  556. DEFAULT_PC_BUS,
  557. 0,
  558. HalpPicVectorRedirect[RTC_IRQ],
  559. &inti
  560. );
  561. HalpSetRedirEntry((UCHAR)inti,
  562. HalpIntiInfo[inti].Entry,
  563. HalpIntiInfo[inti].Destinations << DESTINATION_SHIFT);
  564. HalpPicStateIntact = FALSE;
  565. _asm {
  566. mov eax, flags
  567. push eax
  568. popfd
  569. }
  570. }
  571. BOOLEAN
  572. HalpAcpiPicStateIntact(
  573. VOID
  574. )
  575. {
  576. return HalpPicStateIntact;
  577. }
  578. ULONG HalpGetApicVersion(ULONG ApicNo)
  579. {
  580. /*++
  581. Routine Description:
  582. Obtains the contents of the version register
  583. for a particular system IO APIC unit. These contents
  584. are saved by the HAL in HalpInitMpInfo.
  585. Arguments:
  586. ApicNo - the number of the IO APIC Unit whose version we want.
  587. Return Value:
  588. The contents of the version register for the given IO APIC unit.
  589. A 0 is returned if no version can be obtained because the given
  590. APIC number is not valid.
  591. */
  592. // If this APIC has been found by the HAL ...
  593. if (ApicNo < HalpMpInfoTable.IOApicCount) {
  594. // ... return its version
  595. return HalpIOApicVersion[ApicNo];
  596. }
  597. else
  598. {
  599. // Otherwise, return 0.
  600. return 0;
  601. }
  602. }
  603. VOID
  604. HalpMaskAcpiInterrupt(
  605. VOID
  606. )
  607. {
  608. USHORT inti = 0;
  609. ULONG apicEntry;
  610. HalpGetApicInterruptDesc(
  611. DEFAULT_PC_BUS,
  612. 0,
  613. HalpPicVectorRedirect[HalpFixedAcpiDescTable.sci_int_vector],
  614. &inti
  615. );
  616. apicEntry = HalpIntiInfo[inti].Entry;
  617. apicEntry |= INTERRUPT_MASKED;
  618. HalpSetRedirEntry((UCHAR)inti,
  619. apicEntry,
  620. 0);
  621. }
  622. VOID
  623. HalpUnmaskAcpiInterrupt(
  624. VOID
  625. )
  626. {
  627. USHORT inti = 0;
  628. HalpGetApicInterruptDesc(
  629. DEFAULT_PC_BUS,
  630. 0,
  631. HalpPicVectorRedirect[HalpFixedAcpiDescTable.sci_int_vector],
  632. &inti
  633. );
  634. HalpSetRedirEntry((UCHAR)inti,
  635. HalpIntiInfo[inti].Entry,
  636. HalpIntiInfo[inti].Destinations << DESTINATION_SHIFT);
  637. }