mirror of https://github.com/lianthony/NT4.0
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
784 lines
16 KiB
/*++
|
|
|
|
Copyright (c) 1993 Digital Equipment Corporation
|
|
|
|
Module Name:
|
|
|
|
ebinitnt.c
|
|
|
|
Abstract:
|
|
|
|
|
|
This module implements the interrupt initialization for a Low Cost Alpha
|
|
(LCA) system. Contains the VLSI 82C106, the 82357 and an EISA bus.
|
|
|
|
Orignally taken from the JENSEN hal code.
|
|
|
|
Author:
|
|
|
|
Wim Colgate (DEC) 26-Oct-1993
|
|
|
|
Environment:
|
|
|
|
Kernel mode only.
|
|
|
|
Revision History:
|
|
|
|
Dick Bissen [DEC] 12-May-1994
|
|
|
|
Correct the IRQ assignments for the EB66 pass2 module. Daytona will not
|
|
be supported on EB66 pass1 modules.
|
|
|
|
Eric Rehm (DEC) 7-Jan-1994
|
|
Intialize PCI Bus information during Phase 1 init.
|
|
|
|
--*/
|
|
|
|
#include "halp.h"
|
|
#include "pcrtc.h"
|
|
#include "eb66def.h"
|
|
#include "halpcsl.h"
|
|
#include "eisa.h"
|
|
#include "pci.h"
|
|
#include "pcip.h"
|
|
#include "iousage.h"
|
|
#include "flash8k.h"
|
|
|
|
#include "fwcallbk.h"
|
|
|
|
#include <ntverp.h> // 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;
|
|
|
|
|
|
|
|
//
|
|
// Define global data for builtin device interrupt enables.
|
|
//
|
|
|
|
USHORT HalpBuiltinInterruptEnable;
|
|
|
|
|
|
//
|
|
//
|
|
//
|
|
BOOLEAN SystemIsEB66P;
|
|
PVOID INTERRUPT_MASK0_QVA;
|
|
PVOID INTERRUPT_MASK1_QVA;
|
|
PVOID INTERRUPT_MASK2_QVA;
|
|
ULONG SIO_INTERRUPT_MASK;
|
|
|
|
// irql mask and tables
|
|
//
|
|
// irql 0 - passive
|
|
// irql 1 - sfw apc level
|
|
// irql 2 - sfw dispatch level
|
|
// irql 3 - device low (All devices except)
|
|
// irql 4 - device high (the serial lines)
|
|
// irql 5 - clock
|
|
// irql 6 - real time
|
|
// 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
|
|
// 1 apc 9
|
|
// 2 dispatch 10 PIC
|
|
// 3 11 keyboard/mouse
|
|
// 4 serial 12 errors
|
|
// 5 clock 13 parallel
|
|
// 6 14 halt
|
|
// 7 nmi 15
|
|
//
|
|
// This is assuming the following prioritization:
|
|
// nmi
|
|
// halt
|
|
// errors
|
|
// clock
|
|
// serial
|
|
// parallel
|
|
// keyboard/mouse
|
|
// pic
|
|
|
|
//
|
|
// This is the HalpIrqlMask for LCA based machines:
|
|
// The LCA interrupt pins:
|
|
//
|
|
// eirq 0 NMI
|
|
// eirq 1 PIC - 82357 interrupts
|
|
// eirq 2 Clock
|
|
|
|
//
|
|
// 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.
|
|
//
|
|
|
|
ULONG HalpBusType = MACHINE_TYPE_ISA;
|
|
|
|
//
|
|
// This is the PCI Memory space that cannot be used by anyone
|
|
// and therefore the HAL says it is reserved for itself
|
|
//
|
|
|
|
ADDRESS_USAGE
|
|
EB66PCIMemorySpace = {
|
|
NULL, CmResourceTypeMemory, PCIUsage,
|
|
{
|
|
__8MB, __32MB - __8MB, // Start=8MB; Length=24Mb (8 through 32)
|
|
0,0
|
|
}
|
|
};
|
|
|
|
//
|
|
// 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(
|
|
);
|
|
|
|
|
|
BOOLEAN
|
|
HalpInitializeInterrupts (
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function initializes interrupts for an Alpha system.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
A value of TRUE is returned if the initialization is successfully
|
|
completed. Otherwise a value of FALSE is returned.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
UCHAR DataByte;
|
|
ULONG DataLong;
|
|
ULONG Index;
|
|
ULONG Irq;
|
|
KIRQL Irql;
|
|
UCHAR Priority;
|
|
ULONG Vector;
|
|
|
|
//
|
|
// 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();
|
|
|
|
//
|
|
// Connect the Stall interrupt vector to the clock. When the
|
|
// profile count is calculated, we then connect the normal
|
|
// clock.
|
|
|
|
|
|
PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpStallInterrupt;
|
|
|
|
//
|
|
// Clear all pending interrupts
|
|
//
|
|
|
|
HalpClearInterrupts();
|
|
|
|
//
|
|
// Start the peridodic interrupt from the RTC
|
|
//
|
|
HalpProgramIntervalTimer(MAXIMUM_RATE_SELECT);
|
|
|
|
//
|
|
// Initialize the EISA and PCI interrupt controllers.
|
|
//
|
|
|
|
HalpInitializePCIInterrupts();
|
|
|
|
//
|
|
// Initialize the 21066 interrupts.
|
|
//
|
|
// N.B. - The 21066 uses the 21064 core and so the 21066 HAL
|
|
// uses 21064 interrupt enable/disable routines.
|
|
//
|
|
|
|
HalpInitialize21064Interrupts();
|
|
|
|
HalpEnable21064SoftwareInterrupt( Irql = APC_LEVEL );
|
|
HalpEnable21064SoftwareInterrupt( Irql = DISPATCH_LEVEL );
|
|
|
|
HalpEnable21064HardwareInterrupt( Irq = 0,
|
|
Irql = DEVICE_LEVEL,
|
|
Vector = PIC_VECTOR,
|
|
Priority = 0 );
|
|
HalpEnable21064HardwareInterrupt( Irq = 1,
|
|
Irql = CLOCK_LEVEL,
|
|
Vector = CLOCK_VECTOR,
|
|
Priority = 0 );
|
|
HalpEnable21064HardwareInterrupt( Irq = 2,
|
|
Irql = HIGH_LEVEL,
|
|
Vector = EISA_NMI_VECTOR,
|
|
Priority = 0 );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
VOID
|
|
HalpClearInterrupts(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function no longer does anything.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
return;
|
|
}
|
|
|
|
|
|
VOID
|
|
HalpSetTimeIncrement(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is responsible for setting the time increment for an LCA
|
|
based machine 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.
|
|
//
|
|
|
|
ULONG HalpProfileCountRate;
|
|
|
|
VOID
|
|
HalpInitializeClockInterrupts(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is called during phase 1 initialization to complete
|
|
the initialization of clock interrupts. For LCA, 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[CLOCK2_LEVEL] = 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 LCA is the default EV4 parity-mode handler.
|
|
//
|
|
|
|
PCR->MachineCheckError = HalMachineCheck;
|
|
|
|
//
|
|
// Clear any error conditions currently pending.
|
|
//jnfix - report correctables one day
|
|
|
|
HalpClearAllErrors( ReportCorrectables = FALSE );
|
|
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
HalpInitializeMachineDependent(
|
|
IN ULONG Phase,
|
|
IN PLOADER_PARAMETER_BLOCK LoaderBlock
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function performs any EV4-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 a pointer to the loader block.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
|
|
if( Phase == 0 ){
|
|
|
|
//
|
|
// Phase 0 Initialization.
|
|
//
|
|
|
|
HalpFlashDriver = HalpInitializeFlashDriver(EB66P_ENVIRONMENT_QVA);
|
|
if (HalpFlashDriver != NULL) {
|
|
//
|
|
// The flash device was found, so we must be running on an
|
|
// EB66P
|
|
//
|
|
SystemIsEB66P = TRUE;
|
|
HalpCMOSRamBase = EB66P_ENVIRONMENT_QVA;
|
|
INTERRUPT_MASK0_QVA = EB66P_INTERRUPT_MASK0_QVA;
|
|
INTERRUPT_MASK1_QVA = EB66P_INTERRUPT_MASK1_QVA;
|
|
INTERRUPT_MASK2_QVA = EB66P_INTERRUPT_MASK2_QVA;
|
|
SIO_INTERRUPT_MASK = EB66P_SIO_INTERRUPT_MASK;
|
|
} else {
|
|
SystemIsEB66P = FALSE;
|
|
INTERRUPT_MASK0_QVA = EB66_INTERRUPT_MASK0_QVA;
|
|
INTERRUPT_MASK1_QVA = EB66_INTERRUPT_MASK1_QVA;
|
|
INTERRUPT_MASK2_QVA = EB66_INTERRUPT_MASK2_QVA;
|
|
SIO_INTERRUPT_MASK = EB66_SIO_INTERRUPT_MASK;
|
|
}
|
|
|
|
HalpRegisterAddressUsage (&EB66PCIMemorySpace);
|
|
|
|
|
|
} else {
|
|
|
|
//
|
|
// Phase 1 Initialization.
|
|
//
|
|
|
|
//
|
|
// Initialize the existing bus handlers.
|
|
//
|
|
|
|
HalpRegisterInternalBusHandlers();
|
|
|
|
//
|
|
// Initialize the PCI Bus.
|
|
//
|
|
|
|
HalpInitializePCIBus (LoaderBlock);
|
|
|
|
//
|
|
// Initialize the profiler.
|
|
//
|
|
|
|
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.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
HalpAcknowledgeClockInterrupt();
|
|
|
|
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
|
|
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_REGISTER_ULONG( EPIC_HAXR1_QVA, 0 );
|
|
// WRITE_REGISTER_ULONG( EPIC_HAXR2_QVA, 0);
|
|
return;
|
|
}
|
|
|
|
|
|
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_LCA_UNCORRECTABLE);
|
|
*RawSystemInfoSize = 0;
|
|
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[] = "EB66";
|
|
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
|
|
|
|
--*/
|
|
{
|
|
PROCESSOR_LCA_UNCORRECTABLE processorFrame;
|
|
|
|
//
|
|
// 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;
|
|
}
|