summaryrefslogblamecommitdiffstats
path: root/private/ntos/nthals/halsnip/mips/xxinitnt.c
blob: eeb252c3a8ef198e7ed28af394e4dd83dde99dca (plain) (tree)
























































































































































































































































































































































                                                                                                                                              
//#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;
}