diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/nthals/halxlt/alpha/inithal.c | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/ntos/nthals/halxlt/alpha/inithal.c')
-rw-r--r-- | private/ntos/nthals/halxlt/alpha/inithal.c | 1063 |
1 files changed, 1063 insertions, 0 deletions
diff --git a/private/ntos/nthals/halxlt/alpha/inithal.c b/private/ntos/nthals/halxlt/alpha/inithal.c new file mode 100644 index 000000000..d0b4b3539 --- /dev/null +++ b/private/ntos/nthals/halxlt/alpha/inithal.c @@ -0,0 +1,1063 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation +Copyright (c) 1992, 1993 Digital Equipment Corporation + +Module Name: + + inithal.c + +Abstract: + + + This module implements the initialization of the system dependent + functions that define the Hardware Architecture Layer (HAL) for an + Alpha machine + +Author: + + David N. Cutler (davec) 25-Apr-1991 + Miche Baker-Harvey (miche) 18-May-1992 + +Environment: + + Kernel mode only. + +Revision History: + + 28-Jul-1992 Jeff McLeman (mcleman) + Add code to allocate a mapping buffer for buffered DMA + + 14-Jul-1992 Jeff McLeman (mcleman) + Add call to HalpCachePcrValues, which will call the PALcode to + cache values of the PCR that need fast access. + + 10-Jul-1992 Jeff McLeman (mcleman) + Remove reference to initializing the fixed TB entries, since Alpha + does not have fixed TB entries. + + 24-Sep-1993 Joe Notarangelo + Restructured to make this module platform-independent. + +--*/ + +#include "halp.h" +#include "eisa.h" + +// +// Declare the extern variable UncorrectableError declared in +// inithal.c. +// +PERROR_FRAME PUncorrectableError; + +// +// external +// + +ULONG HalDisablePCIParityChecking = 0xffffffff; + +// +// Define HAL spinlocks. +// + +KSPIN_LOCK HalpBeepLock; +KSPIN_LOCK HalpDisplayAdapterLock; +KSPIN_LOCK HalpSystemInterruptLock; + +// +// Mask of all of the processors that are currently active. +// + +KAFFINITY HalpActiveProcessors; + +// +// Mapping of the logical processor numbers to the physical processors. +// + +ULONG HalpLogicalToPhysicalProcessor[HAL_MAXIMUM_PROCESSOR+1]; + +ULONG AlreadySet = 0; + +// +// HalpClockFrequency is the processor cycle counter frequency in units +// of cycles per second (Hertz). It is a large number (e.g., 125,000,000) +// but will still fit in a ULONG. +// +// HalpClockMegaHertz is the processor cycle counter frequency in units +// of megahertz. It is a small number (e.g., 125) and is also the number +// of cycles per microsecond. The assumption here is that clock rates will +// always be an integral number of megahertz. +// +// Having the frequency available in both units avoids multiplications, or +// especially divisions in time critical code. +// + +ULONG HalpClockFrequency; +ULONG HalpClockMegaHertz = DEFAULT_PROCESSOR_FREQUENCY_MHZ; + +ULONGLONG HalpContiguousPhysicalMemorySize; +// +// Use the square wave mode of the PIT to measure the processor +// speed. The timer has a frequency of 1.193MHz. We want a +// square wave with a period of 50ms so we must initialize the +// pit with a count of: +// 50ms*1.193MHz = 59650 cycles +// + +#define TIMER_REF_VALUE 59650 + +VOID +HalpVerifyPrcbVersion( + VOID + ); + +VOID +HalpRecurseLoaderBlock( + IN PCONFIGURATION_COMPONENT_DATA CurrentEntry + ); + +ULONG +HalpQuerySystemFrequency( + ULONG SampleTime + ); + +VOID +HalpAllocateUncorrectableFrame( + VOID + ); + + +BOOLEAN +HalInitSystem ( + IN ULONG Phase, + IN PLOADER_PARAMETER_BLOCK LoaderBlock + ) + +/*++ + +Routine Description: + + This function initializes the Hardware Architecture Layer (HAL) for an + Alpha system. + +Arguments: + + Phase - Supplies the initialization phase (zero or one). + + LoaderBlock - Supplies a pointer to a loader parameter block. + +Return Value: + + A value of TRUE is returned is the initialization was successfully + complete. Otherwise a value of FALSE is returend. + +--*/ + +{ + PKPRCB Prcb; + ULONG BuildType = 0; + + Prcb = PCR->Prcb; + + // + // Perform initialization for the primary processor. + // + + if( Prcb->Number == HAL_PRIMARY_PROCESSOR ){ + + if (Phase == 0) { + +#if HALDBG + + DbgPrint( "HAL/HalInitSystem: Phase = %d\n", Phase ); + DbgBreakPoint(); + HalpDumpMemoryDescriptors( LoaderBlock ); + +#endif //HALDBG + // + // Get the memory Size. + // + HalpContiguousPhysicalMemorySize = HalpGetContiguousMemorySize( + LoaderBlock ); + + + // + // Set second level cache size + // NOTE: Although we set the PCR with the right cache size this + // could be overridden by setting the Registry key + // HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet + // \Control\Session Manager + // \Memory Management\SecondLevelDataCache. + // + // + // + // If the secondlevel cache size is 0 or 512KB then it is + // possible that the firmware is an old one. In which case + // we determine the cache size here. If the value is anything + // other than these then it is a new firmware and probably + // reporting the correct cache size hence use this value. + // + + if(LoaderBlock->u.Alpha.SecondLevelDcacheSize == 0 || + LoaderBlock->u.Alpha.SecondLevelDcacheSize == 512*__1K){ + PCR->SecondLevelCacheSize = HalpGetBCacheSize( + HalpContiguousPhysicalMemorySize + ); + } else { + PCR->SecondLevelCacheSize = + LoaderBlock->u.Alpha.SecondLevelDcacheSize; + } + + + // + // Initialize HAL spinlocks. + // + + KeInitializeSpinLock(&HalpBeepLock); + KeInitializeSpinLock(&HalpDisplayAdapterLock); + KeInitializeSpinLock(&HalpSystemInterruptLock); + + // + // Fill in handlers for APIs which this HAL supports + // + + HalQuerySystemInformation = HaliQuerySystemInformation; + HalSetSystemInformation = HaliSetSystemInformation; + + // + // Phase 0 initialization. + // + + HalpInitializeCia( LoaderBlock ); + + HalpSetTimeIncrement(); + HalpMapIoSpace(); + HalpCreateDmaStructures(LoaderBlock); + HalpEstablishErrorHandler(); + HalpInitializeDisplay(LoaderBlock); + HalpInitializeMachineDependent( Phase, LoaderBlock ); + HalpInitializeInterrupts(); + HalpVerifyPrcbVersion(); + + // + // Set the processor active in the HAL active processor mask. + // + + HalpActiveProcessors = 1 << Prcb->Number; + + // + // Initialize the logical to physical processor mapping + // for the primary processor. + // + + HalpLogicalToPhysicalProcessor[0] = HAL_PRIMARY_PROCESSOR; + + return TRUE; + + } else { + +#if HALDBG + + DbgPrint( "HAL/HalInitSystem: Phase = %d\n", Phase ); + DbgBreakPoint(); + +#endif //HALDBG + + // + // Phase 1 initialization. + // + + HalpInitializeClockInterrupts(); + HalpInitializeMachineDependent( Phase, LoaderBlock ); + + // + // Allocate memory for the uncorrectable frame + // + + HalpAllocateUncorrectableFrame(); + + // + // Initialize the Buffer for Uncorrectable Error. + // + + HalpInitializeUncorrectableErrorFrame(); + + return TRUE; + + } + } + + // + // Perform necessary processor-specific initialization for + // secondary processors. Phase is ignored as this will be called + // only once on each secondary processor. + // + + HalpMapIoSpace(); + HalpInitializeInterrupts(); + HalpInitializeMachineDependent( Phase, LoaderBlock ); + + // + // Set the processor active in the HAL active processor mask. + // + + HalpActiveProcessors |= 1 << Prcb->Number; + +#if HALDBG + + DbgPrint( "Secondary %d is alive\n", Prcb->Number ); + +#endif //HALDBG + + return TRUE; +} + + + +VOID +HalpAllocateUncorrectableFrame( + VOID + ) +/*++ + +Routine Description: + + This function is called after the Phase1 Machine Dependent initialization. + It must be called only after Phase1 machine dependent initialization. + This function allocates the necessary amountof memory for storing the + uncorrectable error frame. This function makes a call to a machine + dependent function 'HalpGetMachineDependentErrorFrameSizes' for + getting the size of the Processor Specific and System Specific error + frame size. The machine dependent code will + know the size of these frames after the machine depedant Phase1 + initialization. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + ULONG RawProcessorFrameSize; + ULONG RawSystemFrameSize; + ULONG EntireErrorFrameSize; + + // + // First get the machine dependent error frame sizes. + // + HalpGetMachineDependentErrorFrameSizes( + &RawProcessorFrameSize, + &RawSystemFrameSize); + + // + // Compute the total size of the error frame + // + EntireErrorFrameSize = sizeof(ERROR_FRAME) + RawProcessorFrameSize + + RawSystemFrameSize; + + // + // Allocate space to store the error frame. + // Not sure if it is OK to use ExAllocatePool at this instant. + // We will give this a try if it doesn't work What do we do??!! + // + + PUncorrectableError = ExAllocatePool(NonPagedPool, + EntireErrorFrameSize); + if(PUncorrectableError == NULL) { + return; + } + + PUncorrectableError->LengthOfEntireErrorFrame = EntireErrorFrameSize; + + // + // if the size is not equal to zero then set the RawInformation pointers + // to point to the right place. If not set the pointer to NULL and set + // size to 0. + // + + // + // make Raw processor info to point right after the error frame. + // + if(RawProcessorFrameSize) { + PUncorrectableError->UncorrectableFrame.RawProcessorInformation = + (PVOID)((PUCHAR)PUncorrectableError + sizeof(ERROR_FRAME) ); + PUncorrectableError->UncorrectableFrame.RawProcessorInformationLength = + RawProcessorFrameSize; + } + else{ + PUncorrectableError->UncorrectableFrame.RawProcessorInformation = + NULL; + PUncorrectableError->UncorrectableFrame.RawProcessorInformationLength = + 0; + } + if(RawSystemFrameSize){ + PUncorrectableError->UncorrectableFrame.RawSystemInformation = + (PVOID)((PUCHAR)PUncorrectableError->UncorrectableFrame. + RawProcessorInformation + RawProcessorFrameSize); + PUncorrectableError->UncorrectableFrame.RawSystemInformationLength = + RawSystemFrameSize; + } + else{ + PUncorrectableError->UncorrectableFrame.RawSystemInformation = + NULL; + PUncorrectableError->UncorrectableFrame.RawSystemInformationLength = + 0; + } +} + + + +VOID +HalpGetProcessorInfo( + PPROCESSOR_INFO pProcessorInfo +) +/*++ + +Routine Description: + + Collects the Processor Information and fills in the buffer. + +Arguments: + + pProcessorInfo - Pointer to the PROCESSOR_INFO structure into which + the processor information will be filled in. + +Return Value: + + None. + +--*/ +{ + PKPRCB Prcb; + + pProcessorInfo->ProcessorType = PCR->ProcessorType; + pProcessorInfo->ProcessorRevision = PCR->ProcessorRevision; + + Prcb = PCR->Prcb; + pProcessorInfo->LogicalProcessorNumber = Prcb->Number; + pProcessorInfo->PhysicalProcessorNumber = + HalpLogicalToPhysicalProcessor[Prcb->Number]; + return; +} + + + +VOID +HalInitializeProcessor ( + IN ULONG Number + ) + +/*++ + +Routine Description: + + This function is called early in the initialization of the kernel + to perform platform dependent initialization for each processor + before the HAL Is fully functional. + + N.B. When this routine is called, the PCR is present but is not + fully initialized. + +Arguments: + + Number - Supplies the number of the processor to initialize. + +Return Value: + + None. + +--*/ + +{ + return; +} + +BOOLEAN +HalStartNextProcessor ( + IN PLOADER_PARAMETER_BLOCK LoaderBlock, + IN PKPROCESSOR_STATE ProcessorState + ) + +/*++ + +Routine Description: + + This function is called to start the next processor. + +Arguments: + + LoaderBlock - Supplies a pointer to the loader parameter block. + + ProcessorState - Supplies a pointer to the processor state to be + used to start the processor. + +Return Value: + + If a processor is successfully started, then a value of TRUE is + returned. Otherwise a value of FALSE is returned. If a value of + TRUE is returned, then the logical processor number is stored + in the processor control block specified by the loader block. + +--*/ + +{ + ULONG LogicalNumber; + PRESTART_BLOCK NextRestartBlock; + ULONG PhysicalNumber; + PKPRCB Prcb; + +#if !defined(NT_UP) + + // + // If the address of the first restart parameter block is NULL, then + // the host system is a uniprocessor system running with old firmware. + // Otherwise, the host system may be a multiprocessor system if more + // than one restart block is present. + // + // N.B. The first restart parameter block must be for the boot master + // and must represent logical processor 0. + // + + NextRestartBlock = SYSTEM_BLOCK->RestartBlock; + if (NextRestartBlock == NULL) { + return FALSE; + } + + // + // Scan the restart parameter blocks for a processor that is ready, + // but not running. If a processor is found, then fill in the restart + // processor state, set the logical processor number, and set start + // in the boot status. + // + + LogicalNumber = 0; + PhysicalNumber = 0; + do { + + // + // If the processor is not ready then we assume that it is not + // present. We must increment the physical processor number but + // the logical processor number does not changed. + // + + if( NextRestartBlock->BootStatus.ProcessorReady == FALSE ){ + + PhysicalNumber += 1; + + } else { + + // + // Check if this processor has already been started. + // If it has not then start it now. + // + + if( NextRestartBlock->BootStatus.ProcessorStart == FALSE ){ + + RtlZeroMemory( &NextRestartBlock->u.Alpha, + sizeof(ALPHA_RESTART_STATE)); + NextRestartBlock->u.Alpha.IntA0 = + ProcessorState->ContextFrame.IntA0; + NextRestartBlock->u.Alpha.IntSp = + ProcessorState->ContextFrame.IntSp; + NextRestartBlock->u.Alpha.ReiRestartAddress = + (ULONG)ProcessorState->ContextFrame.Fir; + Prcb = (PKPRCB)(LoaderBlock->Prcb); + Prcb->Number = (CCHAR)LogicalNumber; + Prcb->RestartBlock = NextRestartBlock; + NextRestartBlock->BootStatus.ProcessorStart = 1; + + HalpLogicalToPhysicalProcessor[LogicalNumber] = PhysicalNumber; + + return TRUE; + + } else { + + // + // Ensure that the logical to physical mapping has been + // established for this processor. + // + + HalpLogicalToPhysicalProcessor[LogicalNumber] = PhysicalNumber; + + } + + LogicalNumber += 1; + PhysicalNumber += 1; + } + + NextRestartBlock = NextRestartBlock->NextRestartBlock; + + } while (NextRestartBlock != NULL); + +#endif // !defined(NT_UP) + + return FALSE; +} + +VOID +HalpVerifyPrcbVersion( + VOID + ) +/*++ + +Routine Description: + + This function verifies that the HAL matches the kernel. If there + is a mismatch the HAL bugchecks the system. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + + PKPRCB Prcb; + + // + // Verify Prcb major version number, and build options are + // all conforming to this binary image + // + + Prcb = KeGetCurrentPrcb(); + +#if DBG + if (!(Prcb->BuildType & PRCB_BUILD_DEBUG)) { + // This checked hal requires a checked kernel + KeBugCheckEx (MISMATCHED_HAL, 2, Prcb->BuildType, PRCB_BUILD_DEBUG, 0); + } +#else + if (Prcb->BuildType & PRCB_BUILD_DEBUG) { + // This free hal requires a free kernel + KeBugCheckEx (MISMATCHED_HAL, 2, Prcb->BuildType, 0, 0); + } +#endif +#ifndef NT_UP + if (Prcb->BuildType & PRCB_BUILD_UNIPROCESSOR) { + // This MP hal requires an MP kernel + KeBugCheckEx (MISMATCHED_HAL, 2, Prcb->BuildType, 0, 0); + } +#endif + if (Prcb->MajorVersion != PRCB_MAJOR_VERSION) { + KeBugCheckEx (MISMATCHED_HAL, + 1, Prcb->MajorVersion, PRCB_MAJOR_VERSION, 0); + } + + +} + + +VOID +HalpParseLoaderBlock( + IN PLOADER_PARAMETER_BLOCK LoaderBlock + ) +{ + + if (LoaderBlock == NULL) { + return; + } + + HalpRecurseLoaderBlock( (PCONFIGURATION_COMPONENT_DATA) + LoaderBlock->ConfigurationRoot); +} + + + +VOID +HalpRecurseLoaderBlock( + IN PCONFIGURATION_COMPONENT_DATA CurrentEntry + ) +/*++ + +Routine Description: + + This routine parses the loader parameter block looking for the PCI + node. Once found, used to determine if PCI parity checking should be + enabled or disabled. Set the default to not disable checking. + +Arguments: + + CurrentEntry - Supplies a pointer to a loader configuration + tree or subtree. + +Return Value: + + None. + +--*/ +{ + + PCONFIGURATION_COMPONENT Component; + PWSTR NameString; + + // + // Quick out + // + + if (AlreadySet) { + return; + } + + if (CurrentEntry) { + Component = &CurrentEntry->ComponentEntry; + + if (Component->Class == AdapterClass && + Component->Type == MultiFunctionAdapter) { + + if (strcmp(Component->Identifier, "PCI") == 0) { + HalDisablePCIParityChecking = Component->Flags.ConsoleOut; + AlreadySet = TRUE; +#if HALDBG + DbgPrint("ARC tree sets PCI parity checking to %s\n", + HalDisablePCIParityChecking ? "OFF" : "ON"); +#endif + return; + } + } + + // + // Process all the Siblings of current entry + // + + HalpRecurseLoaderBlock(CurrentEntry->Sibling); + + // + // Process all the Childeren of current entry + // + + HalpRecurseLoaderBlock(CurrentEntry->Child); + + } +} + + +ULONG +HalpQuerySystemFrequency( + ULONG SampleTime + ) +/*++ + +Routine Description: + + This routine returns the speed at which the system is running in hertz. + The system frequency is calculated by counting the number of processor + cycles that occur during 500ms, using the Programmable Interval Timer + (PIT) as the reference time. The PIT is used to generate a square + wave with a 50ms Period. We use the Speaker counter since we can + enable and disable the count from software. The output of the + speaker is obtained from the SIO NmiStatus register. + +Arguments: + + None. + +Return Value: + + The system frequency in Hertz. + +--*/ +{ + TIMER_CONTROL TimerControlSetup; + TIMER_CONTROL TimerControlReadStatus; + TIMER_STATUS TimerStatus; + NMI_STATUS NmiStatus; + PEISA_CONTROL controlBase; + ULONGLONG Count1; + ULONGLONG Count2; + ULONG NumberOfIntervals; + ULONG SquareWaveState = 0; + +// mdbfix - move this into eisa.h one day +#define SB_READ_STATUS_ONLY 2 + + controlBase = HalpEisaControlBase; + + // + // Disable the speaker counter. + // + + *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus); + + NmiStatus.SpeakerGate = 0; + NmiStatus.SpeakerData = 0; + + // these are MBZ when writing to NMIMISC + NmiStatus.RefreshToggle = 0; + NmiStatus.SpeakerTimer = 0; + NmiStatus.IochkNmi = 0; + + WRITE_PORT_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus)); + + // + // Number of Square Wave transitions to count. + // at 50ms period, count the number of 25ms + // square wave transitions for a sample reference + // time to against which we measure processor cycle count. + // + + NumberOfIntervals = (SampleTime/50) * 2; + + // + // Set the timer for counter 0 in binary mode, square wave output + // + + TimerControlSetup.BcdMode = 0; + TimerControlSetup.Mode = TM_SQUARE_WAVE; + TimerControlSetup.SelectByte = SB_LSB_THEN_MSB; + TimerControlSetup.SelectCounter = SELECT_COUNTER_2; + + // + // Set the counter for a latched read of the status. + // We will poll the PIT for the state of the square + // wave output. + // + + TimerControlReadStatus.BcdMode = 0; + TimerControlReadStatus.Mode = (1 << SELECT_COUNTER_2); + TimerControlReadStatus.SelectByte = SB_READ_STATUS_ONLY; + TimerControlReadStatus.SelectCounter = SELECT_READ_BACK; + + + // + // Write the count value LSB and MSB for a 50ms clock period + // + + WRITE_PORT_UCHAR( &controlBase->CommandMode1, + *(PUCHAR)&TimerControlSetup ); + + WRITE_PORT_UCHAR( &controlBase->SpeakerTone, + TIMER_REF_VALUE & 0xff ); + + WRITE_PORT_UCHAR( &controlBase->SpeakerTone, + (TIMER_REF_VALUE >> 8) & 0xff ); + + // + // Enable the speaker counter but disable the SPKR output signal. + // + + *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus); + + NmiStatus.SpeakerGate = 1; + NmiStatus.SpeakerData = 0; + + // these are MBZ when writing to NMIMISC + NmiStatus.RefreshToggle = 0; + NmiStatus.SpeakerTimer = 0; + NmiStatus.IochkNmi = 0; + + WRITE_PORT_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus)); + + // + // Synchronize with the counter before taking the first + // sample of the Processor Cycle Count (PCC). Since we + // are using the Square Wave Mode, wait until the next + // state change and then observe half a cycle before + // sampling. + // + + // + // observe the low transition of the square wave output. + // + do { + + *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus); + + } while (NmiStatus.SpeakerTimer != SquareWaveState); + + SquareWaveState ^= 1; + + // + // observe the next transition of the square wave output and then + // take the first cycle counter sample. + // + do { + + *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus); + + } while (NmiStatus.SpeakerTimer != SquareWaveState); + + Count1 = __RCC(); + + // + // Wait for the 500ms time period to pass and then take the + // second sample of the PCC. For a 50ms period, we have to + // observe eight wave transitions (25ms each). + // + + do { + + SquareWaveState ^= 1; + + // + // wait for wave transition + // + do { + + *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus); + + } while (NmiStatus.SpeakerTimer != SquareWaveState); + + } while (--NumberOfIntervals); + + Count2 = __RCC(); + + // + // Disable the speaker counter. + // + + *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus); + + NmiStatus.SpeakerGate = 0; + NmiStatus.SpeakerData = 0; + + WRITE_PORT_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus)); + + // + // Calculate the Hz by the number of processor cycles + // elapsed during 1s. + // + // Hz = PCC/SampleTime * 1000ms/s + // = PCC * (1000/SampleTime) + // + + // did the counter wrap? if so add 2^32 + if (Count1 > Count2) { + + Count2 += (ULONGLONG)(1 << 32); + + } + + return (ULONG) ((Count2 - Count1)*(((ULONG)1000)/SampleTime)); +} + + +VOID +HalpInitializeProcessorParameters( + VOID + ) +/*++ + +Routine Description: + + This routine initalize the processor counter parameters + HalpClockFrequency and HalpClockMegaHertz based on the + estimated CPU speed. A 1s reference time is used for + the estimation. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + ULONG MHz; + + HalpClockFrequency = HalpQuerySystemFrequency(1000); + HalpClockMegaHertz = MHz = HalpClockFrequency / 1000000; + + // + // Hotwire HalpClockMegaHertz to match product name! + // + if (MHz > 490) HalpClockMegaHertz = 500; + else if (MHz > 456) HalpClockMegaHertz = 466; + else if (MHz > 423) HalpClockMegaHertz = 433; + else if (MHz > 390) HalpClockMegaHertz = 400; + else if (MHz > 356) HalpClockMegaHertz = 366; + else if (MHz > 323) HalpClockMegaHertz = 333; + else if (MHz > 290) HalpClockMegaHertz = 300; + else; // there must be some mistake... +} + + + + +#if 0 +VOID +HalpGatherPerformanceParameterStats( + VOID + ) + +/*++ + +Routine Description: + + This routine gathers statistics on the method for + estimating the system frequency. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + ULONG Index; + ULONG Hertz[32]; + ULONGLONG Mean = 0; + ULONGLONG Variance = 0; + ULONGLONG TempHertz; + + // + // take 32 samples of estimated CPU speed, + // calculating the mean in the process. + // + DbgPrint("Sample\tFrequency\tMegaHertz\n\n"); + + for (Index = 0; Index < 32; Index++) { + Hertz[Index] = HalpQuerySystemFrequency(500); + Mean += Hertz[Index]; + + DbgPrint( + "%d\t%d\t%d\n", + Index, + Hertz[Index], + (ULONG)((Hertz[Index] + 500000)/1000000) + ); + + } + + // + // calculate the mean + // + + Mean /= 32; + + // + // calculate the variance + // + for (Index = 0; Index < 32; Index++) { + TempHertz = (Mean > Hertz[Index])? + (Mean - Hertz[Index]) : (Hertz[Index] - Mean); + TempHertz = TempHertz*TempHertz; + Variance += TempHertz; + } + + Variance /= 32; + + DbgPrint("\nResults\n\n"); + DbgPrint( + "Mean = %d\nVariance = %d\nMegaHertz (derived) = %d\n", + Mean, + Variance, + (Mean + 500000)/ 1000000 + ); + +} +#endif + |