NT4/private/ntos/nthals/halsnip/mips/xxinitnt.c
2020-09-30 17:12:29 +02:00

346 lines
10 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/xxinitnt.c,v 1.5 1996/03/04 13:29:07 pierre Exp $")
/*++
Copyright (c) 1993 - 1994 Siemens Nixdorf Informationssysteme AG
Copyright (c) 1991 Microsoft Corporation
Module Name:
xxinitnt.c
Abstract:
This module implements the interrupt initialization for a MIPS R3000
or R4000 system.
Environment:
Kernel mode only.
--*/
#include "halp.h"
#include "eisa.h"
extern BOOLEAN HalpCountCompareInterrupt;
//
// Define forward referenced prototypes.
//
VOID
HalpAckExtraClockInterrupt(
VOID
);
VOID
HalpCountInterrupt (
VOID
);
VOID
HalpProgramIntervalTimer (
IN ULONG Interval
);
VOID
HalpProgramExtraTimer (
IN ULONG Interval
);
VOID
HalpProgramExtraTimerPciT (
IN ULONG Interval
);
//
// Put all code for HAL initialization in the INIT section. It will be
// deallocated by memory management when phase 1 initialization is
// completed.
//
#if defined(ALLOC_PRAGMA)
#pragma alloc_text(INIT, HalpInitializeInterrupts)
#pragma alloc_text(INIT, HalpCountInterrupt)
#endif
//
// Define the IRQL mask and level mapping table.
//
// These tables are transfered to the PCR and determine the priority of
// interrupts.
//
// N.B. The two software interrupt levels MUST be the lowest levels.
/*+++
The interrupts bits in the cause Register have the following Hardware Interrupts:
7 6 5 4 3 2 1 0
+-------------------------------+
| x | x | x | x | x | x | x | x |
+-------------------------------+
| | | | | | | |
| | | | | | | +-------- APC LEVEL (Software)
| | | | | | +------------ Dispatch LEVEL (Software)
| | | | | +---------------- central Int0 (proc 0)
| | | | +-------------------- None
| | | +------------------------ None
| | +---------------------------- TIMER (Proc 1 for RM300MP only)
| +-------------------------------- DCU (Proc 1 for RM400MP only - proc 0 for RM400UP only)
+------------------------------------ CountCompare (Profiling)
---*/
//
// On an PCI Desktop or minitower single-processor (ORION), the processor has only 1 central
// interrupt pin, so all should be directed to this interrupt, except the (internal)
// CountCompare interrupt
//
UCHAR
HalpIrqlMask_PCIs[] = {3, 3, 3, 3, 3, 3, 3, 3, // 0000 - 0111 high 4-bits
8, 8, 8, 8, 8, 8, 8, 8, // 1000 - 1111 high 4-bits (CountCompare only!)
0, 1, 2, 2, 3, 3, 3, 3, // 0000 - 0111 low 4-bits
3, 3, 3, 3, 3, 3, 3, 3}; // 1000 - 1111 low 4-bits
UCHAR
HalpIrqlTable_PCIs[] = {0x87, // IRQL 0
0x86, // IRQL 1
0x84, // IRQL 2
0x80, // Int0Dispatch Level
// allow only Irql 8 (profiling & HIGH_LEVEL) ?!
0x80, // IRQL 4
0x80, // IRQL 5
0x80, // IRQL 6
0x80, // IRQL 7
0x00}; // IRQL 8
//
// On a PCI Tower, all the external interrupts are centralised
// on one central pin except DCU on IP6 (because of the extra-timer).
// The internal MP-Agent interrupt is directed on the seventh pin.
//
UCHAR
HalpIrqlMask_PCIm_ExT[] = {3, 3, 6, 6, 7, 7, 7, 7, // 0000 - 0111 high 4-bits
8, 8, 8, 8, 8, 8, 8, 8, // 1000 - 1111 high 4-bits (CountCompare only!)
0, 1, 2, 2, 3, 3, 3, 3, // 0000 - 0111 low 4-bits
3, 3, 3, 3, 3, 3, 3, 3}; // 1000 - 1111 low 4-bits
UCHAR
HalpIrqlTable_PCIm_ExT[] = {0xe7, // IRQL 0
0xe6, // IRQL 1
0xe4, // IRQL 2
0xe0, // Int0Dispatch Level
0xe0, // IRQL 4
0xe0, // IRQL 5
0xc0, // IRQL 6
0x80, // IRQL 7
0x00}; // IRQL 8
//
// On a PCI multi-processor minitower (or mono-processor with MPagent),
// all the external interrupts are centralised
// on one central pin except extra-timer on IP6 (not used if mono).
// The internal MP-Agent interrupt is directed on the seventh pin.
//
UCHAR
HalpIrqlMask_PCIm[] = {3, 5, 3, 5, 7, 7, 7, 7, // 0000 - 0111 high 4-bits
8, 8, 8, 8, 8, 8, 8, 8, // 1000 - 1111 high 4-bits (CountCompare only!)
0, 1, 2, 2, 3, 3, 3, 3, // 0000 - 0111 low 4-bits
3, 3, 3, 3, 3, 3, 3, 3}; // 1000 - 1111 low 4-bits
UCHAR
HalpIrqlTable_PCIm[] = {0xd7, // IRQL 0
0xd6, // IRQL 1
0xd4, // IRQL 2
0xd0, // Int0Dispatch Level
0xd0, // IRQL 4
0xc0, // IRQL 5
0xc0, // IRQL 6
0x80, // IRQL 7
0x00}; // IRQL 8
VOID
HalpCountInterrupt (
VOID
)
/*++
Routine Description:
This function serves as the R4000 count/compare interrupt service
routine early in the system initialization. Its only function is
to field and acknowledge count/compare interrupts during the system
boot process.
Arguments:
None.
Return Value:
None.
--*/
{
extern ULONG HalpProfileInterval;
//
// Acknowledge the R4000 count/compare interrupt.
//
HalpProfileInterval = DEFAULT_PROFILE_INTERVAL;
HalpCountCompareInterrupt = TRUE;
HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
return;
}
BOOLEAN
HalpInitializeInterrupts (
VOID
)
/*++
Routine Description:
This function initializes interrupts for a MIPS R3000 or R4000 system.
Arguments:
None.
Return Value:
A value of TRUE is returned if the initialization is successfully
completed. Otherwise a value of FALSE is returned.
--*/
{
ULONG Index;
PKPRCB Prcb;
//
// Get the address of the processor control block for the current
// processor.
//
Prcb = PCR->Prcb;
if (Prcb->Number == 0) {
//
// Initialize the IRQL translation tables in the PCR. These tables are
// used by the interrupt dispatcher to determine the new IRQL and the
// mask value that is to be loaded into the PSR. They are also used by
// the routines that raise and lower IRQL to load a new mask value into
// the PSR.
//
if (HalpProcessorId != MPAGENT) {
//
// this is a PCI desktop or a single-processor PCI minitower
//
for (Index = 0; Index < sizeof(HalpIrqlMask_PCIs); Index += 1)
PCR->IrqlMask[Index] = HalpIrqlMask_PCIs[Index];
for (Index = 0; Index < sizeof(HalpIrqlTable_PCIs); Index += 1)
PCR->IrqlTable[Index] = HalpIrqlTable_PCIs[Index];
} else {
//
// this is a PCI minitower or PCI tower
//
if (HalpIsTowerPci){
for (Index = 0; Index < sizeof(HalpIrqlMask_PCIm_ExT); Index += 1)
PCR->IrqlMask[Index] = HalpIrqlMask_PCIm_ExT[Index];
for (Index = 0; Index < sizeof(HalpIrqlTable_PCIm_ExT); Index += 1)
PCR->IrqlTable[Index] = HalpIrqlTable_PCIm_ExT[Index];
}else{
for (Index = 0; Index < sizeof(HalpIrqlMask_PCIm); Index += 1)
PCR->IrqlMask[Index] = HalpIrqlMask_PCIm[Index];
for (Index = 0; Index < sizeof(HalpIrqlTable_PCIm); Index += 1)
PCR->IrqlTable[Index] = HalpIrqlTable_PCIm[Index];
}
}
//
// the main system clock is always in the onboard PC core
//
PCR->InterruptRoutine[CLOCK2_LEVEL] = (PKINTERRUPT_ROUTINE)HalpStallInterrupt;
//
// force a CountCompare interrupt
//
HalpWriteCompareRegisterAndClear(100);
//
// If processor 0 is being initialized, then connect the count/compare
// interrupt to the count interrupt routine to handle early count/compare
// interrupts during phase 1 initialization. Otherwise, connect the
// count\compare interrupt to the appropriate interrupt service routine.
//
PCR->InterruptRoutine[PROFILE_LEVEL] = HalpCountInterrupt;
HalpProgramIntervalTimer (MAXIMUM_INCREMENT);
HalpEnableOnboardInterrupt(CLOCK2_LEVEL,Latched); // Enable Timer1,Counter0 interrupt
} else {
//
// MultiProcessorEnvironment Processor N
//
if (HalpIsTowerPci){
for (Index = 0; Index < sizeof(HalpIrqlMask_PCIm_ExT); Index += 1)
PCR->IrqlMask[Index] = HalpIrqlMask_PCIm_ExT[Index];
for (Index = 0; Index < sizeof(HalpIrqlTable_PCIm_ExT); Index += 1)
PCR->IrqlTable[Index] = HalpIrqlTable_PCIm_ExT[Index];
}else{
for (Index = 0; Index < sizeof(HalpIrqlMask_PCIm); Index += 1)
PCR->IrqlMask[Index] = HalpIrqlMask_PCIm[Index];
for (Index = 0; Index < sizeof(HalpIrqlTable_PCIm); Index += 1)
PCR->IrqlTable[Index] = HalpIrqlTable_PCIm[Index];
}
if (Prcb->Number==1){
if (HalpIsTowerPci){
HalpProgramExtraTimerPciT(MAXIMUM_INCREMENT);
}else{
HalpProgramExtraTimer (MAXIMUM_INCREMENT);
PCR->InterruptRoutine[EXTRA_CLOCK_LEVEL] = HalpClockInterrupt1;
}
}
PCR->InterruptRoutine[PROFILE_LEVEL] = HalpProfileInterrupt;
PCR->StallScaleFactor = HalpStallScaleFactor;
}
return TRUE;
}