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.

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