Windows NT 4.0 source code leak
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.

784 lines
16 KiB

5 years ago
  1. /*++
  2. Copyright (c) 1993 Digital Equipment Corporation
  3. Module Name:
  4. ebinitnt.c
  5. Abstract:
  6. This module implements the interrupt initialization for a Low Cost Alpha
  7. (LCA) system. Contains the VLSI 82C106, the 82357 and an EISA bus.
  8. Orignally taken from the JENSEN hal code.
  9. Author:
  10. Wim Colgate (DEC) 26-Oct-1993
  11. Environment:
  12. Kernel mode only.
  13. Revision History:
  14. Dick Bissen [DEC] 12-May-1994
  15. Correct the IRQ assignments for the EB66 pass2 module. Daytona will not
  16. be supported on EB66 pass1 modules.
  17. Eric Rehm (DEC) 7-Jan-1994
  18. Intialize PCI Bus information during Phase 1 init.
  19. --*/
  20. #include "halp.h"
  21. #include "pcrtc.h"
  22. #include "eb66def.h"
  23. #include "halpcsl.h"
  24. #include "eisa.h"
  25. #include "pci.h"
  26. #include "pcip.h"
  27. #include "iousage.h"
  28. #include "flash8k.h"
  29. #include "fwcallbk.h"
  30. #include <ntverp.h> // to get the product build number.
  31. //
  32. // Include the header containing Error Frame Definitions(in halalpha).
  33. //
  34. #include "errframe.h"
  35. //
  36. // Define extern global buffer for the Uncorrectable Error Frame.
  37. // declared in halalpha\inithal.c
  38. //
  39. extern PERROR_FRAME PUncorrectableError;
  40. //
  41. // Define global data for builtin device interrupt enables.
  42. //
  43. USHORT HalpBuiltinInterruptEnable;
  44. //
  45. //
  46. //
  47. BOOLEAN SystemIsEB66P;
  48. PVOID INTERRUPT_MASK0_QVA;
  49. PVOID INTERRUPT_MASK1_QVA;
  50. PVOID INTERRUPT_MASK2_QVA;
  51. ULONG SIO_INTERRUPT_MASK;
  52. // irql mask and tables
  53. //
  54. // irql 0 - passive
  55. // irql 1 - sfw apc level
  56. // irql 2 - sfw dispatch level
  57. // irql 3 - device low (All devices except)
  58. // irql 4 - device high (the serial lines)
  59. // irql 5 - clock
  60. // irql 6 - real time
  61. // irql 7 - error, mchk, nmi, halt
  62. //
  63. //
  64. // IDT mappings:
  65. // For the built-ins, GetInterruptVector will need more info,
  66. // or it will have to be built-in to the routines, since
  67. // these don't match IRQL levels in any meaningful way.
  68. //
  69. // 0 passive 8
  70. // 1 apc 9
  71. // 2 dispatch 10 PIC
  72. // 3 11 keyboard/mouse
  73. // 4 serial 12 errors
  74. // 5 clock 13 parallel
  75. // 6 14 halt
  76. // 7 nmi 15
  77. //
  78. // This is assuming the following prioritization:
  79. // nmi
  80. // halt
  81. // errors
  82. // clock
  83. // serial
  84. // parallel
  85. // keyboard/mouse
  86. // pic
  87. //
  88. // This is the HalpIrqlMask for LCA based machines:
  89. // The LCA interrupt pins:
  90. //
  91. // eirq 0 NMI
  92. // eirq 1 PIC - 82357 interrupts
  93. // eirq 2 Clock
  94. //
  95. // For information purposes: here is what the IDT division looks like:
  96. //
  97. // 000-015 Built-ins (we only use 8 entries; NT wants 10)
  98. // 016-031 ISA
  99. // 048-063 EISA
  100. // 080-095 PCI
  101. // 112-127 Turbo Channel
  102. // 128-255 unused, as are all other holes
  103. //
  104. //
  105. // Define the bus type, this value allows us to distinguish between
  106. // EISA and ISA systems.
  107. //
  108. ULONG HalpBusType = MACHINE_TYPE_ISA;
  109. //
  110. // This is the PCI Memory space that cannot be used by anyone
  111. // and therefore the HAL says it is reserved for itself
  112. //
  113. ADDRESS_USAGE
  114. EB66PCIMemorySpace = {
  115. NULL, CmResourceTypeMemory, PCIUsage,
  116. {
  117. __8MB, __32MB - __8MB, // Start=8MB; Length=24Mb (8 through 32)
  118. 0,0
  119. }
  120. };
  121. //
  122. // Define global data used to communicate new clock rates to the clock
  123. // interrupt service routine.
  124. //
  125. ULONG HalpCurrentTimeIncrement;
  126. ULONG HalpNextRateSelect;
  127. ULONG HalpNextTimeIncrement;
  128. ULONG HalpNewTimeIncrement;
  129. VOID
  130. HalpClearInterrupts(
  131. );
  132. BOOLEAN
  133. HalpInitializeInterrupts (
  134. VOID
  135. )
  136. /*++
  137. Routine Description:
  138. This function initializes interrupts for an Alpha system.
  139. Arguments:
  140. None.
  141. Return Value:
  142. A value of TRUE is returned if the initialization is successfully
  143. completed. Otherwise a value of FALSE is returned.
  144. --*/
  145. {
  146. UCHAR DataByte;
  147. ULONG DataLong;
  148. ULONG Index;
  149. ULONG Irq;
  150. KIRQL Irql;
  151. UCHAR Priority;
  152. ULONG Vector;
  153. //
  154. // Initialize HAL processor parameters based on estimated CPU speed.
  155. // This must be done before HalpStallExecution is called. Compute integral
  156. // megahertz first to avoid rounding errors due to imprecise cycle clock
  157. // period values.
  158. //
  159. HalpInitializeProcessorParameters();
  160. //
  161. // Connect the Stall interrupt vector to the clock. When the
  162. // profile count is calculated, we then connect the normal
  163. // clock.
  164. PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpStallInterrupt;
  165. //
  166. // Clear all pending interrupts
  167. //
  168. HalpClearInterrupts();
  169. //
  170. // Start the peridodic interrupt from the RTC
  171. //
  172. HalpProgramIntervalTimer(MAXIMUM_RATE_SELECT);
  173. //
  174. // Initialize the EISA and PCI interrupt controllers.
  175. //
  176. HalpInitializePCIInterrupts();
  177. //
  178. // Initialize the 21066 interrupts.
  179. //
  180. // N.B. - The 21066 uses the 21064 core and so the 21066 HAL
  181. // uses 21064 interrupt enable/disable routines.
  182. //
  183. HalpInitialize21064Interrupts();
  184. HalpEnable21064SoftwareInterrupt( Irql = APC_LEVEL );
  185. HalpEnable21064SoftwareInterrupt( Irql = DISPATCH_LEVEL );
  186. HalpEnable21064HardwareInterrupt( Irq = 0,
  187. Irql = DEVICE_LEVEL,
  188. Vector = PIC_VECTOR,
  189. Priority = 0 );
  190. HalpEnable21064HardwareInterrupt( Irq = 1,
  191. Irql = CLOCK_LEVEL,
  192. Vector = CLOCK_VECTOR,
  193. Priority = 0 );
  194. HalpEnable21064HardwareInterrupt( Irq = 2,
  195. Irql = HIGH_LEVEL,
  196. Vector = EISA_NMI_VECTOR,
  197. Priority = 0 );
  198. return TRUE;
  199. }
  200. VOID
  201. HalpClearInterrupts(
  202. )
  203. /*++
  204. Routine Description:
  205. This function no longer does anything.
  206. Arguments:
  207. None.
  208. Return Value:
  209. None.
  210. --*/
  211. {
  212. return;
  213. }
  214. VOID
  215. HalpSetTimeIncrement(
  216. VOID
  217. )
  218. /*++
  219. Routine Description:
  220. This routine is responsible for setting the time increment for an LCA
  221. based machine via a call into the kernel.
  222. Arguments:
  223. None.
  224. Return Value:
  225. None.
  226. --*/
  227. {
  228. //
  229. // Set the time increment value.
  230. //
  231. HalpCurrentTimeIncrement = MAXIMUM_INCREMENT;
  232. HalpNextTimeIncrement = MAXIMUM_INCREMENT;
  233. HalpNextRateSelect = 0;
  234. KeSetTimeIncrement( MAXIMUM_INCREMENT, MINIMUM_INCREMENT );
  235. }
  236. //
  237. // Define global data used to calibrate and stall processor execution.
  238. //
  239. ULONG HalpProfileCountRate;
  240. VOID
  241. HalpInitializeClockInterrupts(
  242. VOID
  243. )
  244. /*++
  245. Routine Description:
  246. This function is called during phase 1 initialization to complete
  247. the initialization of clock interrupts. For LCA, this function
  248. connects the true clock interrupt handler and initializes the values
  249. required to handle profile interrupts.
  250. Arguments:
  251. None.
  252. Return Value:
  253. None.
  254. --*/
  255. {
  256. //
  257. // Compute the profile interrupt rate.
  258. //
  259. HalpProfileCountRate = ((1000 * 1000 * 10) / KeQueryTimeIncrement());
  260. //
  261. // Set the time increment value and connect the real clock interrupt
  262. // routine.
  263. //
  264. PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpClockInterrupt;
  265. return;
  266. }
  267. VOID
  268. HalpEstablishErrorHandler(
  269. VOID
  270. )
  271. /*++
  272. Routine Description:
  273. This routine performs the initialization necessary for the HAL to
  274. begin servicing machine checks.
  275. Arguments:
  276. None.
  277. Return Value:
  278. None.
  279. --*/
  280. {
  281. BOOLEAN ReportCorrectables;
  282. //
  283. // Connect the machine check handler via the PCR. The machine check
  284. // handler for LCA is the default EV4 parity-mode handler.
  285. //
  286. PCR->MachineCheckError = HalMachineCheck;
  287. //
  288. // Clear any error conditions currently pending.
  289. //jnfix - report correctables one day
  290. HalpClearAllErrors( ReportCorrectables = FALSE );
  291. return;
  292. }
  293. VOID
  294. HalpInitializeMachineDependent(
  295. IN ULONG Phase,
  296. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  297. )
  298. /*++
  299. Routine Description:
  300. This function performs any EV4-specific initialization based on
  301. the current phase on initialization.
  302. Arguments:
  303. Phase - Supplies an indicator for phase of initialization, phase 0 or
  304. phase 1.
  305. LoaderBlock - supplies a pointer to the loader block.
  306. Return Value:
  307. None.
  308. --*/
  309. {
  310. if( Phase == 0 ){
  311. //
  312. // Phase 0 Initialization.
  313. //
  314. HalpFlashDriver = HalpInitializeFlashDriver(EB66P_ENVIRONMENT_QVA);
  315. if (HalpFlashDriver != NULL) {
  316. //
  317. // The flash device was found, so we must be running on an
  318. // EB66P
  319. //
  320. SystemIsEB66P = TRUE;
  321. HalpCMOSRamBase = EB66P_ENVIRONMENT_QVA;
  322. INTERRUPT_MASK0_QVA = EB66P_INTERRUPT_MASK0_QVA;
  323. INTERRUPT_MASK1_QVA = EB66P_INTERRUPT_MASK1_QVA;
  324. INTERRUPT_MASK2_QVA = EB66P_INTERRUPT_MASK2_QVA;
  325. SIO_INTERRUPT_MASK = EB66P_SIO_INTERRUPT_MASK;
  326. } else {
  327. SystemIsEB66P = FALSE;
  328. INTERRUPT_MASK0_QVA = EB66_INTERRUPT_MASK0_QVA;
  329. INTERRUPT_MASK1_QVA = EB66_INTERRUPT_MASK1_QVA;
  330. INTERRUPT_MASK2_QVA = EB66_INTERRUPT_MASK2_QVA;
  331. SIO_INTERRUPT_MASK = EB66_SIO_INTERRUPT_MASK;
  332. }
  333. HalpRegisterAddressUsage (&EB66PCIMemorySpace);
  334. } else {
  335. //
  336. // Phase 1 Initialization.
  337. //
  338. //
  339. // Initialize the existing bus handlers.
  340. //
  341. HalpRegisterInternalBusHandlers();
  342. //
  343. // Initialize the PCI Bus.
  344. //
  345. HalpInitializePCIBus (LoaderBlock);
  346. //
  347. // Initialize the profiler.
  348. //
  349. HalpInitializeProfiler();
  350. }
  351. return;
  352. }
  353. VOID
  354. HalpStallInterrupt (
  355. VOID
  356. )
  357. /*++
  358. Routine Description:
  359. This function serves as the stall calibration interrupt service
  360. routine. It is executed in response to system clock interrupts
  361. during the initialization of the HAL layer.
  362. Arguments:
  363. None.
  364. Return Value:
  365. None.
  366. --*/
  367. {
  368. HalpAcknowledgeClockInterrupt();
  369. return;
  370. }
  371. ULONG
  372. HalSetTimeIncrement (
  373. IN ULONG DesiredIncrement
  374. )
  375. /*++
  376. Routine Description:
  377. This function is called to set the clock interrupt rate to the frequency
  378. required by the specified time increment value.
  379. Arguments:
  380. DesiredIncrement - Supplies desired number of 100ns units between clock
  381. interrupts.
  382. Return Value:
  383. The actual time increment in 100ns units.
  384. --*/
  385. {
  386. ULONG NewTimeIncrement;
  387. ULONG NextRateSelect;
  388. KIRQL OldIrql;
  389. //
  390. // Raise IRQL to the highest level, set the new clock interrupt
  391. // parameters, lower IRQl, and return the new time increment value.
  392. //
  393. KeRaiseIrql(HIGH_LEVEL, &OldIrql);
  394. if (DesiredIncrement < MINIMUM_INCREMENT) {
  395. DesiredIncrement = MINIMUM_INCREMENT;
  396. }
  397. if (DesiredIncrement > MAXIMUM_INCREMENT) {
  398. DesiredIncrement = MAXIMUM_INCREMENT;
  399. }
  400. //
  401. // Find the allowed increment that is less than or equal to
  402. // the desired increment.
  403. //
  404. if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS4) {
  405. NewTimeIncrement = RTC_PERIOD_IN_CLUNKS4;
  406. NextRateSelect = RTC_RATE_SELECT4;
  407. } else if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS3) {
  408. NewTimeIncrement = RTC_PERIOD_IN_CLUNKS3;
  409. NextRateSelect = RTC_RATE_SELECT3;
  410. } else if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS2) {
  411. NewTimeIncrement = RTC_PERIOD_IN_CLUNKS2;
  412. NextRateSelect = RTC_RATE_SELECT2;
  413. } else {
  414. NewTimeIncrement = RTC_PERIOD_IN_CLUNKS1;
  415. NextRateSelect = RTC_RATE_SELECT1;
  416. }
  417. HalpNextRateSelect = NextRateSelect;
  418. HalpNewTimeIncrement = NewTimeIncrement;
  419. KeLowerIrql(OldIrql);
  420. return NewTimeIncrement;
  421. }
  422. VOID
  423. HalpResetHAERegisters(
  424. VOID
  425. )
  426. /*++
  427. Routine Description:
  428. This function resets the HAE registers in the chipset to 0.
  429. This is routine called during a shutdown so that the prom
  430. gets a predictable environment.
  431. Arguments:
  432. none
  433. Return Value:
  434. none
  435. --*/
  436. {
  437. // WRITE_REGISTER_ULONG( EPIC_HAXR1_QVA, 0 );
  438. // WRITE_REGISTER_ULONG( EPIC_HAXR2_QVA, 0);
  439. return;
  440. }
  441. VOID
  442. HalpGetMachineDependentErrorFrameSizes(
  443. PULONG RawProcessorSize,
  444. PULONG RawSystemInfoSize
  445. )
  446. /*++
  447. Routine Description:
  448. This function returns the size of the system specific structures.
  449. Arguments:
  450. RawProcessorSize - Pointer to a buffer that will receive the
  451. size of the processor specific error information buffer.
  452. RawSystemInfoSize - Pointer to a buffer that will receive the
  453. size of the system specific error information buffer.
  454. Return Value:
  455. none
  456. --*/
  457. {
  458. *RawProcessorSize = sizeof(PROCESSOR_LCA_UNCORRECTABLE);
  459. *RawSystemInfoSize = 0;
  460. return;
  461. }
  462. VOID
  463. HalpGetSystemInfo(SYSTEM_INFORMATION *SystemInfo)
  464. /*++
  465. Routine Description:
  466. This function fills in the System information.
  467. Arguments:
  468. SystemInfo - Pointer to the SYSTEM_INFORMATION buffer that needs
  469. to be filled in.
  470. Return Value:
  471. none
  472. --*/
  473. {
  474. char systemtype[] = "EB66";
  475. EXTENDED_SYSTEM_INFORMATION FwExtSysInfo;
  476. VenReturnExtendedSystemInformation(&FwExtSysInfo);
  477. RtlCopyMemory(SystemInfo->FirmwareRevisionId,
  478. FwExtSysInfo.FirmwareVersion,
  479. 16);
  480. RtlCopyMemory(SystemInfo->SystemType,systemtype, 8);
  481. SystemInfo->ClockSpeed =
  482. ((1000 * 1000) + (PCR->CycleClockPeriod >> 1)) / PCR->CycleClockPeriod;
  483. SystemInfo->SystemRevision = PCR->SystemRevision;
  484. RtlCopyMemory(SystemInfo->SystemSerialNumber,
  485. PCR->SystemSerialNumber,
  486. 16);
  487. SystemInfo->SystemVariant = PCR->SystemVariant;
  488. SystemInfo->PalMajorVersion = PCR->PalMajorVersion;
  489. SystemInfo->PalMinorVersion = PCR->PalMinorVersion;
  490. SystemInfo->OsRevisionId = VER_PRODUCTBUILD;
  491. //
  492. // For now fill in dummy values.
  493. //
  494. SystemInfo->ModuleVariant = 1UL;
  495. SystemInfo->ModuleRevision = 1UL;
  496. SystemInfo->ModuleSerialNumber = 0;
  497. return;
  498. }
  499. VOID
  500. HalpInitializeUncorrectableErrorFrame (
  501. VOID
  502. )
  503. /*++
  504. Routine Description:
  505. This function Allocates an Uncorrectable Error frame for this
  506. system and initializes the frame with certain constant/global
  507. values.
  508. This is routine called during machine dependent system
  509. Initialization.
  510. Arguments:
  511. none
  512. Return Value:
  513. none
  514. --*/
  515. {
  516. PROCESSOR_LCA_UNCORRECTABLE processorFrame;
  517. //
  518. // If the Uncorrectable error buffer is not set then simply return
  519. //
  520. if(PUncorrectableError == NULL)
  521. return;
  522. PUncorrectableError->Signature = ERROR_FRAME_SIGNATURE;
  523. PUncorrectableError->FrameType = UncorrectableFrame;
  524. //
  525. // ERROR_FRAME_VERSION is define in errframe.h and will
  526. // change as and when there is a change in the errframe.h.
  527. // This Version number helps the service, that reads this
  528. // information from the dumpfile, to check if it knows about
  529. // this frmae version type to decode. If it doesn't know, it
  530. // will dump the entire frame to the EventLog with a message
  531. // "Error Frame Version Mismatch".
  532. //
  533. PUncorrectableError->VersionNumber = ERROR_FRAME_VERSION;
  534. //
  535. // The sequence number will always be 1 for Uncorrectable errors.
  536. //
  537. PUncorrectableError->SequenceNumber = 1;
  538. //
  539. // The PerformanceCounterValue field is not used for Uncorrectable
  540. // errors.
  541. //
  542. PUncorrectableError->PerformanceCounterValue = 0;
  543. //
  544. // We will fill in the UncorrectableFrame.SystemInfo here.
  545. //
  546. HalpGetSystemInfo(&PUncorrectableError->UncorrectableFrame.System);
  547. PUncorrectableError->UncorrectableFrame.Flags.SystemInformationValid = 1;
  548. return;
  549. }