summaryrefslogtreecommitdiffstats
path: root/private/ntos/nthals/hal0jens/alpha/xxinithl.c
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/nthals/hal0jens/alpha/xxinithl.c
downloadNT4.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/hal0jens/alpha/xxinithl.c')
-rw-r--r--private/ntos/nthals/hal0jens/alpha/xxinithl.c606
1 files changed, 606 insertions, 0 deletions
diff --git a/private/ntos/nthals/hal0jens/alpha/xxinithl.c b/private/ntos/nthals/hal0jens/alpha/xxinithl.c
new file mode 100644
index 000000000..bcef74730
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/alpha/xxinithl.c
@@ -0,0 +1,606 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ xxinithl.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.
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+#include "jxisa.h"
+#include "jnsnrtc.h"
+
+ULONG HalpBusType = MACHINE_TYPE_EISA;
+ULONG HalpMapBufferSize;
+PHYSICAL_ADDRESS HalpMapBufferPhysicalAddress;
+
+typedef
+BOOLEAN
+KBUS_ERROR_ROUTINE (
+ IN struct _EXCEPTION_RECORD *ExceptionRecord,
+ IN struct _KEXCEPTION_FRAME *ExceptionFrame,
+ IN struct _KTRAP_FRAME *TrapFrame
+ );
+
+KBUS_ERROR_ROUTINE HalMachineCheck;
+
+//
+// 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;
+
+//
+// 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
+
+ULONG
+HalpQuerySystemFrequency(
+ ULONG SampleTime
+ );
+
+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;
+
+ if (Phase == 0) {
+
+ //
+ // Phase 0 initialization.
+ //
+
+ //
+ // Set the time increment value.
+ //
+
+ HalpCurrentTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextRateSelect = 0;
+ KeSetTimeIncrement( MAXIMUM_INCREMENT, MINIMUM_INCREMENT );
+
+ HalpMapIoSpace();
+ HalpInitializeInterrupts();
+ HalpCreateDmaStructures();
+ HalpInitializeDisplay(LoaderBlock);
+ HalpCachePcrValues();
+
+ //
+ // Fill in handlers for APIs which this HAL supports
+ //
+
+ HalQuerySystemInformation = HaliQuerySystemInformation;
+ HalSetSystemInformation = HaliSetSystemInformation;
+
+ //
+ // Establish the machine check handler for in the PCR.
+ //
+
+ PCR->MachineCheckError = HalMachineCheck;
+
+ //
+ // 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);
+ }
+
+ //
+ // Now alocate a mapping buffer for buffered DMA.
+ //
+
+ LessThan16Mb = FALSE;
+
+ HalpMapBufferSize = INITIAL_MAP_BUFFER_LARGE_SIZE;
+ HalpMapBufferPhysicalAddress.LowPart =
+ HalpAllocPhysicalMemory (LoaderBlock, MAXIMUM_ISA_PHYSICAL_ADDRESS,
+ HalpMapBufferSize >> PAGE_SHIFT, TRUE);
+ HalpMapBufferPhysicalAddress.HighPart = 0;
+
+ if (!HalpMapBufferPhysicalAddress.LowPart) {
+ HalpMapBufferSize = 0;
+ }
+
+ //
+ // Setup special memory AFTER we've allocated our COMMON BUFFER!
+ //
+
+ HalpInitializeSpecialMemory( LoaderBlock );
+
+ return TRUE;
+
+ } else {
+
+ //
+ // Phase 1 initialization.
+ //
+
+ HalpCalibrateStall();
+
+ //
+ // Initialize the existing bus handlers.
+ //
+
+ HalpRegisterInternalBusHandlers();
+
+ //
+ // Allocate pool for evnironment variable support
+ //
+
+ if (HalpEnvironmentInitialize() != 0) {
+ HalDisplayString(" No pool available for Environment Variables\n");
+ }
+
+ return TRUE;
+
+ }
+}
+
+
+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.
+
+--*/
+
+{
+ return FALSE;
+}
+VOID
+HalpVerifyPrcbVersion ()
+{
+
+}
+
+
+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 ((Count2 - Count1)*(((ULONG)1000)/SampleTime));
+}
+
+
+VOID
+HalpInitializeProcessorParameters(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine initalize the performance 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.
+
+--*/
+{
+
+ HalpClockFrequency = HalpQuerySystemFrequency(1000);
+ HalpClockMegaHertz = (HalpClockFrequency + 500000)/ 1000000;
+
+}
+
+#if 0
+VOID
+HalpGatherProcessorParameterStats(
+ 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
+