/*++ Copyright (c) 1993 Digital Equipment Corporation Module Name: gminitnt.c Abstract: This module implements the platform-specific initialization for a Sable system. Author: Joe Notarangelo 25-Oct-1993 Steve Jenness 28-Oct-1993 (Sable) Environment: Kernel mode only. Revision History: --*/ #include "halp.h" #include "gammartc.h" #include "gamma.h" #include "halpcsl.h" #include "pci.h" #include "pcip.h" #include "isaaddr.h" #include "eisa.h" #include "iousage.h" #include "axp21164.h" #include "siintsup.h" #include "lyintsup.h" #include "xiintsup.h" #include "fwcallbk.h" #include // to get the product build number. // // Include the header containing Error Frame Definitions(in halalpha). // #include "errframe.h" // // Define extern global buffer for the Uncorrectable Error Frame. // declared in halalpha\inithal.c // extern PERROR_FRAME PUncorrectableError; // // Don't change these values unless you know exactly what you are doing // #define HAE0_1_REGISTER_VALUE 0x0 // to address SPARSE PCI MEMORY #define HAE0_2_REGISTER_VALUE 0x0 // to address PCI IO space #define HAE0_3_REGISTER_VALUE 0x0 // For PCI config cycle type #define HAE0_4_REGISTER_VALUE 0x0 // to address DENCE PCI Memory ULONG HalpMemorySlot[4] = { (ULONG)GAMMA_MEM0_CSRS_QVA, (ULONG)GAMMA_MEM1_CSRS_QVA, (ULONG)GAMMA_MEM2_CSRS_QVA, (ULONG)GAMMA_MEM3_CSRS_QVA }; ULONG HalpCPUSlot[4] = { (ULONG)SABLE_CPU0_CSRS_QVA, // we overload SABLE (ULONG)SABLE_CPU1_CSRS_QVA, // with GAMMA values (ULONG)SABLE_CPU2_CSRS_QVA, (ULONG)SABLE_CPU3_CSRS_QVA }; // // Prototypes // VOID HalpInitializeProcessorParameters( VOID ); VOID HalpInitializeHAERegisters( VOID ); VOID HalpSenseCBusSlots( VOID ); // // This is the PCI Memory space that cannot be used by anyone // and therefore the HAL says it is reserved for itself // Block out 8Mb to 144MB // ADDRESS_USAGE SablePCIMemorySpace = { NULL, CmResourceTypeMemory, PCIUsage, { __8MB, (__32MB - __8MB), // Start=8MB; Length=24MB 0,0 } }; // // Define global data for builtin device interrupt enables. // USHORT HalpBuiltinInterruptEnable; // // Define global for saving the T2 Chipset's version // ULONG T2VersionNumber; #if defined(XIO_PASS1) || defined(XIO_PASS2) // // Is the external I/O module present? // BOOLEAN HalpXioPresent = FALSE; #endif // // Is this a Lynx platform? // BOOLEAN HalpLynxPlatform = FALSE; // // How many processors are ready to run? // ULONG HalpProcessors = 0; // irql mask and tables // // irql 0 - passive // irql 1 - sfw apc level // irql 2 - sfw dispatch level // irql 3 - device low // irql 4 - device high // irql 5 - clock // irql 6 - real time, ipi, performance counters // irql 7 - error, mchk, nmi, halt // // // IDT mappings: // For the built-ins, GetInterruptVector will need more info, // or it will have to be built-in to the routines, since // these don't match IRQL levels in any meaningful way. // // 0 passive 8 perf cntr 1 // 1 apc 9 // 2 dispatch 10 PIC // 3 11 // 4 12 errors // 5 clock 13 // 6 perf cntr 0 14 halt // 7 nmi 15 // // This is assuming the following prioritization: // nmi // halt // errors // performance counters // clock // pic // // The hardware interrupt pins are used as follows for Sable // // IRQ_H[0] = Correctable Error // IRQ_H[1] = PCI0/Eisa0 // IRQ_H[2] = Clock/IPI // IRQ_H[3] = PCI1/Eisa1 // This vector has been changed to shadow // // the IPI vector value // // smjfix - This comment doesn't match what is currently happening in the // code. Plus it isn't clear that EISA and ISA entries can // be split apart. // // For information purposes: here is what the IDT division looks like: // // 000-015 Built-ins (we only use 8 entries; NT wants 10) // 016-031 ISA // 048-063 EISA // 080-095 PCI // 112-127 Turbo Channel // 128-255 unused, as are all other holes // // // Define the bus type, this value allows us to distinguish between // EISA and ISA systems. // // smjfix - Why is this here? It is a compile time constant for the // platform. This is useful only if one HAL is being used // for multiple platforms and is being passed from the firmware // or detected. ULONG HalpBusType = MACHINE_TYPE_EISA; // // Define global data used to communicate new clock rates to the clock // interrupt service routine. // ULONG HalpCurrentTimeIncrement; ULONG HalpNextRateSelect; ULONG HalpNextTimeIncrement; ULONG HalpNewTimeIncrement; VOID HalpClearInterrupts( ); // // The correctable interrupt handler: // VOID HalpGammaCorrectableInterrupt( VOID ); // // The Machine check Interrupt handler: // VOID HalpGammaErrorInterrupt( VOID ); BOOLEAN HalpInitializeInterrupts ( VOID ) /*++ Routine Description: This function initializes interrupts for a Sable system. Arguments: None. Return Value: A value of TRUE is returned if the initialization is successfully completed. Otherwise a value of FALSE is returned. --*/ { RATTLER_CONFIG_CSR Config; UCHAR DataByte; ULONG DataLong; ULONG Index; ULONG Irq; KIRQL Irql; PKPRCB Prcb; UCHAR Priority; ULONG Vector; Prcb = PCR->Prcb; // // Initialize interrupt handling for the primary processor and // any system-wide interrupt initialization. // if( Prcb->Number == GAMMA_PRIMARY_PROCESSOR ){ // // Initialize HAL processor parameters based on estimated CPU speed. // This must be done before HalpStallExecution is called. Compute integral // megahertz first to avoid rounding errors due to imprecise cycle clock // period values. // HalpInitializeProcessorParameters(); // // Start the periodic interrupt from the RTC. // HalpProgramIntervalTimer(MAXIMUM_RATE_SELECT); #if !defined(NT_UP) // // Connect the interprocessor interrupt handler. // PCR->InterruptRoutine[EV5_IRQ3_VECTOR] = HalpGammaIpiInterrupt; #endif //NT_UP // // Clear all pending interrupts // HalpClearInterrupts(); // // Initialize SIO interrupts. // if( HalpLynxPlatform ){ HalpInitializeLynxSioInterrupts(); } else { HalpInitializeSableSioInterrupts(); } #if defined(XIO_PASS1) || defined(XIO_PASS2) // // If the XIO module is present, initialize the XIO interrupt // controller, as well. // if( HalpXioPresent ){ HalpInitializeXioInterrupts(); } #endif // // Disable the HALT interrupts. // { Config.all = READ_CPU_REGISTER( &((PRATTLER_CPU_CSRS)HAL_PCR->CpuCsrsQva)->Creg ); Config.EnableSystemInterrupts = 0x09; // Enable Mchk & IPI // // If the XIO module is present, but there are less than 2 // processors in the system, then the primary processor must // handle both SIO and XIO interrupts. Otherwise, the primary // handles the SIO interrupts, and the secondary processor // handles the XIO interrupts (if it is present). // Config.EnableIoInterrupts = 0x1; // Enable CIRQ<0> #if defined(XIO_PASS1) || defined(XIO_PASS2) if( HalpXioPresent && HalpProcessors < 2 ){ Config.EnableAlternateIoInts = 0x2; // Enable CIRQ<1> } else { #endif Config.EnableAlternateIoInts = 0x0; // Disable CIRQ<1> #if defined(XIO_PASS1) || defined(XIO_PASS2) } #endif WRITE_CPU_REGISTER( &((PRATTLER_CPU_CSRS)HAL_PCR->CpuCsrsQva)->Creg, Config.all ); } // // Initialize the 21164 interrupts on the current processor // before enabling the individual interrupts. // HalpInitialize21164Interrupts(); PCR->InterruptRoutine[EV5_IRQ0_VECTOR] = HalpGammaDispatch; PCR->InterruptRoutine[EV5_IRQ1_VECTOR] = HalpGammaCorrectableInterrupt; PCR->InterruptRoutine[EV5_IRQ2_VECTOR] = HalpClockInterrupt; PCR->InterruptRoutine[EV5_MCHK_VECTOR] = HalpGammaErrorInterrupt; // // Allow the interrupts to occur: // HalpStart21164Interrupts(); return TRUE; } //end if Prcb->Number == GAMMA_PRIMARY_PROCESSOR #if !defined(NT_UP) // // Initialize interrupts for the current, secondary processor. // HalpInitialize21164Interrupts(); // // Disable the HALT interrupts. // Disable the Device and Machine check interrupts for secondaries: // { Config.all = READ_CPU_REGISTER( &((PRATTLER_CPU_CSRS)HAL_PCR->CpuCsrsQva)->Creg ); Config.EnableSystemInterrupts = 0x08; // Enable IPI only // // If the XIO module is present, and this is the secondary // processor, enable XIO interrupts on this processor. Otherwise, // disable all I/O interrupt. // Config.EnableIoInterrupts = 0x0; // Disable CIRQ<0> #if defined(XIO_PASS1) || defined(XIO_PASS2) if( HalpXioPresent && Prcb->Number == GAMMA_SECONDARY_PROCESSOR ){ Config.EnableAlternateIoInts = 0x2; // Enable CIRQ<1> } else { #endif Config.EnableAlternateIoInts = 0x0; // Disable CIRQ<1> #if defined(XIO_PASS1) || defined(XIO_PASS2) } #endif WRITE_CPU_REGISTER( &((PRATTLER_CPU_CSRS)HAL_PCR->CpuCsrsQva)->Creg, Config.all ); } // // Clear all pending interrupts // HalpClearInterrupts(); #if defined(XIO_PASS1) || defined(XIO_PASS2) // // If the XIO module is present and this is the secondary processor, // enable XIO interrupts on the secondary processor. // if( HalpXioPresent && Prcb->Number == GAMMA_SECONDARY_PROCESSOR ){ PCR->InterruptRoutine[EV5_IRQ0_VECTOR] = HalpGammaDispatch; } #endif // // Connect the clock and ipi interrupt handlers. // jnfix - For now these are the only interrupts we will accept on // jnfix - secondary processors. Later we will add PCI interrupts // jnfix - and the error interrupts. // PCR->InterruptRoutine[EV5_IRQ2_VECTOR] = HalpSecondaryClockInterrupt; PCR->InterruptRoutine[EV5_IRQ3_VECTOR] = HalpGammaIpiInterrupt; // // Allow the interrupts to occur: // HalpStart21164Interrupts(); #endif //NT_UP return TRUE; } VOID HalpClearInterrupts( ) /*++ Routine Description: This function clears all pending interrupts on the Gamma. Arguments: None. Return Value: None. --*/ { RATTLER_SIC_CSR Sicr; // system interrupt clear register Sicr.all = 0; Sicr.SystemBusErrorInterruptClear0 = 1; // (0) Sicr.SystemBusErrorInterruptClear1 = 1; // (32) Sicr.IntervalTimerInterrupt = 1; // (36) Sicr.SystemEventClear = 1; // (40) Sicr.NodeHaltInterruptClear = 1; // (44) Sicr.InterprocessorInterruptClear = 1; // (48) WRITE_CPU_REGISTER( &((PRATTLER_CPU_CSRS)HAL_PCR->CpuCsrsQva)->Sicr, Sicr.all ); return; } VOID HalpSetTimeIncrement( VOID ) /*++ Routine Description: This routine is responsible for setting the time increment for Sable via a call into the kernel. Arguments: None. Return Value: None. --*/ { // // Set the time increment value. // HalpCurrentTimeIncrement = MAXIMUM_INCREMENT; HalpNextTimeIncrement = MAXIMUM_INCREMENT; HalpNextRateSelect = 0; KeSetTimeIncrement( MAXIMUM_INCREMENT, MINIMUM_INCREMENT ); } // // Define global data used to calibrate and stall processor execution. // // smjfix - Where is this referenced? ULONG HalpProfileCountRate; VOID HalpInitializeClockInterrupts( VOID ) /*++ Routine Description: This function is called during phase 1 initialization to complete the initialization of clock interrupts. For Sable, this function connects the true clock interrupt handler and initializes the values required to handle profile interrupts. Arguments: None. Return Value: None. --*/ { // // Compute the profile interrupt rate. // HalpProfileCountRate = ((1000 * 1000 * 10) / KeQueryTimeIncrement()); // // Set the time increment value and connect the real clock interrupt // routine. // PCR->InterruptRoutine[EV5_IRQ2_VECTOR] = HalpClockInterrupt; return; } VOID HalpEstablishErrorHandler( VOID ) /*++ Routine Description: This routine performs the initialization necessary for the HAL to begin servicing machine checks. Arguments: None. Return Value: None. --*/ { BOOLEAN ReportCorrectables; // // Connect the machine check handler via the PCR. The machine check // handler for Sable is the default EV4 parity-mode handler. // PCR->MachineCheckError = HalMachineCheck; // // Initialize machine check handling for Sable. // HalpInitializeMachineChecks( ReportCorrectables = FALSE ); return; } VOID HalpInitializeMachineDependent( IN ULONG Phase, IN PLOADER_PARAMETER_BLOCK LoaderBlock ) /*++ Routine Description: This function performs any Sable-specific initialization based on the current phase on initialization. Arguments: Phase - Supplies an indicator for phase of initialization, phase 0 or phase 1. LoaderBlock - supplies the loader block passed in via the OsLoader. Return Value: None. --*/ { PKPRCB Prcb; PRESTART_BLOCK RestartBlock; ULONGLONG Value; T2_IOCSR Iocsr; Prcb = PCR->Prcb; if( Prcb->Number == HAL_PRIMARY_PROCESSOR) { if( Phase == 0 ){ // // Phase 0 Initialization. // // // Determine how many processors are ready to run. We use // this information to decide whether to split SIO/XIO // interrupts across two processors or not. // #ifdef NT_UP HalpProcessors = 1; #else HalpProcessors = 0; for( RestartBlock = SYSTEM_BLOCK->RestartBlock; RestartBlock != NULL; RestartBlock = RestartBlock->NextRestartBlock ){ if( RestartBlock->BootStatus.ProcessorReady ){ HalpProcessors++; } } #endif // // Initialize the performance counter. // HalCalibratePerformanceCounter( NULL ); // // Parse the loader block - this sets global for PCI parity check // HalpParseLoaderBlock( LoaderBlock ); // // Re-establish Error Handler to pick up PCI parity changes // HalpEstablishErrorHandler(); // // Determine the T2 Chipset's Version Number. Save Version in Global. // // T2VersionNumber Pass // // 000 1 // 001 2 // Value = READ_T2_REGISTER(&((PT2_CSRS)(T2_CSRS_QVA))->Iocsr); Iocsr = *(PT2_IOCSR)&Value; T2VersionNumber = Iocsr.T2RevisionNumber; HalpInitializeHAERegisters(); HalpSenseCBusSlots(); } else { // // Phase 1 Initialization. // // // Initialize the existing bus handlers. // HalpRegisterInternalBusHandlers(); // // Initialize the PCI bus. // HalpInitializePCIBus(LoaderBlock); // // Initialize profiling for the primary processor. // HalpInitializeProfiler(); } } else { // // Re-establish Error Handler to pick up PCI parity changes // HalpEstablishErrorHandler(); // // Initialize profiling on this secondary processor. // HalpInitializeProfiler(); } return; } VOID HalpStallInterrupt ( VOID ) /*++ Routine Description: This function serves as the stall calibration interrupt service routine. It is executed in response to system clock interrupts during the initialization of the HAL layer. Arguments: None. Return Value: None. --*/ { UCHAR data; RATTLER_SIC_CSR Sic; // // Acknowledge the clock interrupt in the real time clock. // We don't need to do an ACK to the RTC since we're using the // DS1459A RTC's square wave instead of periodic interrupt to // generate the periodic clock. Each processor board has it's own // periodic clock interrupt latch that needs to be cleared. // // This code is MP safe since the Sic is per-processor. RtlZeroMemory( &Sic, sizeof(Sic) ); Sic.IntervalTimerInterrupt = 1; WRITE_CPU_REGISTER( &((PRATTLER_CPU_CSRS)(SABLE_CPU0_CSRS_QVA))->Sicr, *(PULONGLONG)&Sic ); return; } ULONG HalSetTimeIncrement ( IN ULONG DesiredIncrement ) /*++ Routine Description: This function is called to set the clock interrupt rate to the frequency required by the specified time increment value. Arguments: DesiredIncrement - Supplies desired number of 100ns units between clock interrupts. Return Value: The actual time increment in 100ns units. --*/ { ULONG NewTimeIncrement; ULONG NextRateSelect; KIRQL OldIrql; // // Raise IRQL to the highest level, set the new clock interrupt // parameters, lower IRQl, and return the new time increment value. // KeRaiseIrql(HIGH_LEVEL, &OldIrql); if (DesiredIncrement < MINIMUM_INCREMENT) { DesiredIncrement = MINIMUM_INCREMENT; } if (DesiredIncrement > MAXIMUM_INCREMENT) { DesiredIncrement = MAXIMUM_INCREMENT; } // // Find the allowed increment that is less than or equal to // the desired increment. // if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS4) { NewTimeIncrement = RTC_PERIOD_IN_CLUNKS4; NextRateSelect = RTC_RATE_SELECT4; } else if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS3) { NewTimeIncrement = RTC_PERIOD_IN_CLUNKS3; NextRateSelect = RTC_RATE_SELECT3; } else if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS2) { NewTimeIncrement = RTC_PERIOD_IN_CLUNKS2; NextRateSelect = RTC_RATE_SELECT2; } else { NewTimeIncrement = RTC_PERIOD_IN_CLUNKS1; NextRateSelect = RTC_RATE_SELECT1; } HalpNextRateSelect = NextRateSelect; HalpNewTimeIncrement = NewTimeIncrement; KeLowerIrql(OldIrql); return NewTimeIncrement; } // // // VOID HalpInitializeHAERegisters( VOID ) /*++ Routine Description: This function initializes the HAE registers in the T2 chipset. It also register the holes in the PCI memory space if any. Arguments: none Return Value: none --*/ { // // Set Hae0_1, Hae0_2, Hae0_3 and Hae0_4 registers // // IMPORTANT: IF YOU CHANGE THE VALUE OF THE HAE0_1 REGISTERS PLEASE // REMEMBER YOU WILL NEED TO CHANGE: // // PCI_MAX_MEMORY_ADDRESS IN halalpha\sable.h // SablePCIMemorySpace in this file to report holes // // SPARSE SPACE: Hae0_1 // // We set Hae0_1 to 0MB. Which means we have the following // PCI Sparse Memory addresses: // 0 to 8MB VALID. Hae0_1 Not used in address translation // 8 to 16MB Invalid. // 16 to 32MB Invalid. Used for Isa DMA copy for above 16MB // 32 to 128MB VALID. Hae0_1 used in address translation // // All invalid addresses are reported to be used by the hal. // see SablePCIMemorySpace above. // WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Hae0_1, HAE0_1_REGISTER_VALUE ); // PCI IO SPACE: Hae0_2 // // We set Hae0_2 to MB. Which means we have the following // PCI IO addresses: // 0 to 64KB VALID. Hae0_2 Not used in address translation // 64K to 16MB VALID. Hae0_2 is used in the address translation // WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Hae0_2, HAE0_2_REGISTER_VALUE ); if( T2VersionNumber != 0 ) { // PCI CONFIG CYCLE TYPE: Hae0_3 // // We default to zero // WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Hae0_3, HAE0_3_REGISTER_VALUE ); // PCI DENSE MEMORY: Hae0_4 // // We default to zero // WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Hae0_4, HAE0_4_REGISTER_VALUE ); } #if defined(XIO_PASS1) || defined(XIO_PASS2) // // If the XIO module is present, initialize the T4's HAE // registers. // if( HalpXioPresent ){ WRITE_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Hae0_1, HAE0_1_REGISTER_VALUE ); WRITE_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Hae0_2, HAE0_2_REGISTER_VALUE ); WRITE_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Hae0_3, HAE0_3_REGISTER_VALUE ); WRITE_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Hae0_4, HAE0_4_REGISTER_VALUE ); } #endif // // Report that the SPARSE SPACE mapping to the Io subsystem // HalpRegisterAddressUsage (&SablePCIMemorySpace); } VOID HalpResetHAERegisters( VOID ) /*++ Routine Description: This function resets the HAE registers in the chipset to 0. This is routine called during a shutdown so that the prom gets a predictable environment. Arguments: none Return Value: none --*/ { WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Hae0_1, 0 ); WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Hae0_2, 0 ); if( T2VersionNumber != 0) { WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Hae0_3, 0 ); WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Hae0_4, 0 ); } return; } VOID HalpSenseCBusSlots( VOID ) /*++ Routine Description: This function Probes the Cbus looking for slots that are filled. are only 8 Cbus locations we can look at (4 memory, 4 CPU). If we find a module, we will fill in the table at the appropriate location -- if no module is found, then place a zero there. Note: This routine will machine check in an empty slot -- and is expected. Arguments: none Return Value: none --*/ { ULONG i; ULONG CSR; for (i=0; i<4; i++) { if (HalpMemorySlot[i] != 0) { CSR = (ULONG)READ_MEM_REGISTER((PVOID)HalpMemorySlot[i]); if (CSR == 0xffffffff) { HalpMemorySlot[i] = 0; } #if HALDBG if (HalpMemorySlot[i] == 0) { DbgPrint("Memory Slot %d is EMPTY\n", i); } else { DbgPrint("Memory Slot %d is POPULATED\n", i); } #endif } } for (i=0; i<4; i++) { if (HalpCPUSlot[i] != 0) { CSR = (ULONG)READ_CPU_REGISTER((PVOID)HalpCPUSlot[i]); if (CSR == 0xffffffff) { HalpCPUSlot[i] = 0; } #if HALDBG if (HalpCPUSlot[i] == 0) { DbgPrint("CPU Slot %d is EMPTY\n", i); } else { DbgPrint("CPU Slot %d is POPULATED\n", i); } #endif } } } VOID HalpGetMachineDependentErrorFrameSizes( PULONG RawProcessorSize, PULONG RawSystemInfoSize ) /*++ Routine Description: This function returns the size of the system specific structures. Arguments: RawProcessorSize - Pointer to a buffer that will receive the size of the processor specific error information buffer. RawSystemInfoSize - Pointer to a buffer that will receive the size of the system specific error information buffer. Return Value: none --*/ { *RawProcessorSize = sizeof(PROCESSOR_EV5_UNCORRECTABLE); *RawSystemInfoSize = sizeof(GAMMA_UNCORRECTABLE_FRAME); return; } VOID HalpGetSystemInfo(SYSTEM_INFORMATION *SystemInfo) /*++ Routine Description: This function fills in the System information. Arguments: SystemInfo - Pointer to the SYSTEM_INFORMATION buffer that needs to be filled in. Return Value: none --*/ { char systemtype[] = "Gamma"; EXTENDED_SYSTEM_INFORMATION FwExtSysInfo; VenReturnExtendedSystemInformation(&FwExtSysInfo); RtlCopyMemory(SystemInfo->FirmwareRevisionId, FwExtSysInfo.FirmwareVersion, 16); RtlCopyMemory(SystemInfo->SystemType,systemtype, 8); SystemInfo->ClockSpeed = ((1000 * 1000) + (PCR->CycleClockPeriod >> 1)) / PCR->CycleClockPeriod; SystemInfo->SystemRevision = PCR->SystemRevision; RtlCopyMemory(SystemInfo->SystemSerialNumber, PCR->SystemSerialNumber, 16); SystemInfo->SystemVariant = PCR->SystemVariant; SystemInfo->PalMajorVersion = PCR->PalMajorVersion; SystemInfo->PalMinorVersion = PCR->PalMinorVersion; SystemInfo->OsRevisionId = VER_PRODUCTBUILD; // // For now fill in dummy values. // SystemInfo->ModuleVariant = 1UL; SystemInfo->ModuleRevision = 1UL; SystemInfo->ModuleSerialNumber = 0; return; } VOID HalpInitializeUncorrectableErrorFrame ( VOID ) /*++ Routine Description: This function Allocates an Uncorrectable Error frame for this system and initializes the frame with certain constant/global values. This is routine called during machine dependent system Initialization. Arguments: none Return Value: none --*/ { // // If the Uncorrectable error buffer is not set then simply return // if(PUncorrectableError == NULL) return; PUncorrectableError->Signature = ERROR_FRAME_SIGNATURE; PUncorrectableError->FrameType = UncorrectableFrame; // // ERROR_FRAME_VERSION is define in errframe.h and will // change as and when there is a change in the errframe.h. // This Version number helps the service, that reads this // information from the dumpfile, to check if it knows about // this frmae version type to decode. If it doesn't know, it // will dump the entire frame to the EventLog with a message // "Error Frame Version Mismatch". // PUncorrectableError->VersionNumber = ERROR_FRAME_VERSION; // // The sequence number will always be 1 for Uncorrectable errors. // PUncorrectableError->SequenceNumber = 1; // // The PerformanceCounterValue field is not used for Uncorrectable // errors. // PUncorrectableError->PerformanceCounterValue = 0; // // We will fill in the UncorrectableFrame.SystemInfo here. // HalpGetSystemInfo(&PUncorrectableError->UncorrectableFrame.System); PUncorrectableError->UncorrectableFrame.Flags.SystemInformationValid = 1; return; }