NT4/private/ntos/nthals/halfire/ppc/fpints.c
2020-09-30 17:12:29 +02:00

293 lines
8.8 KiB
C

/*
* Copyright (c) 1995 FirePower Systems, Inc.
* DO NOT DISTRIBUTE without permission
*
* $RCSfile: fpints.c $
* $Revision: 1.13 $
* $Date: 1996/07/13 01:15:58 $
* $Locker: $
*/
// TITLE("Manipulate Interrupt Request Level")
//++
//
// Module Name:
//
// FPINTS.C
//
// Abstract:
//
// This module implements the arrays required to handle interrupt
// priorities including generation of the arrays, and anything else
// that is hardware specific interrupt oriented. This is not intended,
// in it's original incarnation, to be an OS policy file, merely a hw one.
//
// The theory of ops is given a set of interrupts ordered by priority,
// that is for any occurance of an interrupt, only those interrupts pre-
// ceding it in the list may now occur. So, if int 5 is the highest
// priority then when it occurrs, no other interrupt will be visible. Any
// lesser interrupt may be interruptable by an int 5. And so on.
//
// Author:
//
// Bill Rees ( FirePOWER )
// Sol Kavy ( FirePOWER )
//
// Environment:
//
// Kernel mode only.
//
// Revision History:
// 16-Jul-95 Created
//
//--
#include "fpdebug.h"
#include "halp.h"
#include "phsystem.h"
#include "fppci.h"
#include "pxpcisup.h"
extern ULONG atoi(PCHAR);
#define MAX_IRQL_NUM 32
#define MAX_VECTORS 32
//
// Note: this is declared poorly in pxsiosup.c and should be
// moved to PCR.
//
extern ULONG registeredInts[];
//
// This array spec's which interrupts go with which devices
// on the host-pci bus ( bus 0, i.e. primary bus ).
// NOTE: 0xff => no device interrupt provided.
//
UCHAR PciDevicePrimaryInts[MAXIMUM_PCI_SLOTS];
/*
* Given an IRQL, provide a register mask that sets allowable interrupts
* and blocks all ints that are set at "lower" priority.
*
* This array is automatically generated from the Vector2Irql array by the
* HalpSetIntPriorityMask() call in fpints.c. For each entry in the V2I array
* that sits at an IRQL or above, it's interrupt bit is or'd into the Irql2Mask
* value. For example, at irql 0, almost every entry in the V2I array has an
* irql greater than 0 ( except for the reserved interrupts ) so the mask value
* in the Irql2Mask array has nearly every bit turned on. Conversely, at IRQL
* 24, only a few interrupts have irql values above 21 ( ints 0, 1, 22, 23,
* 28, 29, 30, 31 )
*
*/
ULONG Irql2Mask[MAX_IRQL_NUM];
/*
* This array matches an IRQL to an Interrupt Vector. Since the array is
* indexed by interrupt vector, there can be a many interrupts to single IRQL
* mapping allowing interrupts to share IRQL settings. IRQLs determine
* relative operational order such that any code operating at any irql, will
* block code from a lower priority from occuring and in turn this same code
* can be interrupted by code trying to run at a higher priority.
*
* So this array becomes a prioritization of interrupts, determining which
* interrupts will block each other or not block each other. In this case,
* a higher number means higher priority hence blocking more interrupts.
*
* explanation on how this array is used is above the Irql2Mask[] declaration.
*
*/
ULONG Vector2Irql[MAX_VECTORS] = {
26, // int 0 (Timer) is IRQL 26 so it blocks most other interrupts:
25, // int 1 (KEYBD) blocks all other ISA devices except RTC.
24, // int 2 is the cascade bit so all interrupts on the cascaded
// interrupt controller ( 8259 ) are higher priority than the
// rest of the interrupts on the master interrupt controller.
15, // int 3 (COM2) is on the master but after the slave ints, so it
// blocks only those ints left on the master chip.
14, // int 4 (COM1) is lower priority than com 2.
13, // int 5 Display:
12, // int 6 Floppy:
11, // int 7 Parallel:
23, // int 8 (RTC): First int on Slave: only ints 0,1,2 are higher pri.
22, // int 9:
21, // int 10 (AUDIO).
20, // int 11:
19, // int 12 Mouse int. Lower than keyboard.
18, // int 13 old scsi
17, // int 14 old enet:
16, // int 15:
00, // reserved: hence lowest priority
00, // reserved: hence lowest priority
00, // reserved: hence lowest priority
00, // reserved: hence lowest priority
00, // int 20 |
00, // int 21 |
00, // int 22 |
00, // int 23 - PCI interrupts configured dynamically from the I2C
00, // int 24 |
00, // int 25 |
00, // int 26 |
00, // reserved: hence lowest priority
28, // int 28(CPU) Set CPU Bus error IRQL to IPI_LEVEL
28, // int 29(PCI) Set PCI Bus error IRQL to IPI_LEVEL
28, // int 30(MEM/VID) Set MEMORY error IRQL to IPI_LEVEL
29 // int 31(IPI) this is the cpu message level: > clock
};
ULONG LX_Vector2Irql[MAX_VECTORS] = {
26, // int 0 (Timer) is IRQL 26 so it blocks most other interrupts:
25, // int 1 (KEYBD) blocks all other ISA devices except RTC.
24, // int 2 is the cascade bit so all interrupts on the cascaded
// interrupt controller ( 8259 ) are higher priority than the
// rest of the interrupts on the master interrupt controller.
15, // int 3 (COM2) is on the master but after the slave ints, so it
// blocks only those ints left on the master chip.
14, // int 4 (COM1) is lower priority than com 2.
13, // int 5 Display:
12, // int 6 Floppy:
11, // int 7 Parallel:
23, // int 8 (RTC): First int on Slave: only ints 0,1,2 are higher pri.
22, // int 9:
21, // int 10 (AUDIO).
20, // int 11:
19, // int 12 Mouse int. Lower than keyboard.
18, // int 13 old scsi
17, // int 14 old enet:
16, // int 15:
00, // reserved: hence lowest priority
00, // reserved: hence lowest priority
00, // reserved: hence lowest priority
00, // reserved: hence lowest priority
23, // int 20 LX: rsrvd ; TX: PCI slot 3
22, // int 21 LX: IDE A ; TX: PCI slot 2
21, // int 22 LX: IDE A ; TX: PCI slot 1
20, // int 23 pci slot 3 IRQL
19, // int 24 pci slot 2 IRQL
18, // int 25 pci slot 1 IRQL scsi
17, // int 26 pci slot 0 IRQL network
00, // reserved: hence lowest priority
28, // int 28(CPU) Set CPU Bus error IRQL to IPI_LEVEL
28, // int 29(PCI) Set PCI Bus error IRQL to IPI_LEVEL
28, // int 30(MEM/VID) Set MEMORY error IRQL to IPI_LEVEL
29 // int 31(IPI) this is the cpu message level: > clock
};
// TX_PROTO & LX_PROTO: must reorder the IRQL table
VOID HalpInitializeVector2Irql(VOID)
{
ULONG irql = 17; // Start the PCI interrupts at irql 17
UCHAR slot;
UCHAR intNum;
for (slot = 1; slot < MAXIMUM_PCI_SLOTS; slot++) {
intNum = PciDevicePrimaryInts[slot];
if ((intNum != INVALID_INT) && (intNum < MAX_VECTORS)) {
Vector2Irql[intNum] = irql;
irql++;
}
}
}
HalpSetIntPriorityMask(VOID)
{
ULONG irql, vec, Value=0;
//
// for each irql, search the Vector2Irql array and generate
// a mask suitable for writing to the mask register to block
// interrupts at the given irql.
//
for (irql = 0; irql < MAX_IRQL_NUM; irql++) {
Irql2Mask[irql] = 0;
for (vec = 0; vec < MAX_VECTORS; vec++) {
//
// Turn on bits for interrupts that are still allowed.
//
if (Vector2Irql[vec] > irql) {
Irql2Mask[irql] |= (1 << vec);
}
}
}
PRNTINTR(HalpDebugPrint("HalpSetIntPriorityMask: Irql2Mask: 0x%x\n",
&Irql2Mask[0]));
return(1);
}
//
// THis array gives the processor affinity for the given interrupt
// vector. Then NT will handle the interrupt on that processor.
//
ULONG Vector2Affinity[MAX_VECTORS];
//
/*++
Routine Description: void HalpInitProcAffinity ()
This function sets the processor affinity for the given interrupt
in the Vector2Affinity array. If the values are wrong, cpu 0 is
set.
Arguments:
pProcnInts - pointer to the PROCNINTS nvram variable.
numProc - number of processors in the system.
Return Value:
void
--*/
void
HalpInitProcAffinity(PCHAR pProcnInts, ULONG NumProc)
{
ULONG vec,proc;
CHAR delim = ';';
if ( NumProc == 1 ) {
for(vec=0; vec < MAX_VECTORS; vec++) {
Vector2Affinity[vec] = 1; // cpu 0 always
}
HDBG(DBG_MPINTS,
HalpDebugPrint("Affinity set to 1 for all vectors\n"););
return;
}
HDBG(DBG_MPINTS,HalpDebugPrint("vector affinity\n"););
// multiprocessor but no PROCNINTS given
// distribute on all processors round robin fashion
if ( pProcnInts == 0 ) {
for(vec=0; vec < MAX_VECTORS; vec++) {
Vector2Affinity[vec] = 1 << (vec%NumProc); // next cpu gets next vec
HDBG(DBG_MPINTS,
HalpDebugPrint("%6d %6d\n",vec,Vector2Affinity[vec]););
}
return;
}
// otherwise go with the env variable PROCNINTS in pProcnInts
for(vec=0; vec < MAX_VECTORS; vec++) {
if ( *pProcnInts == 0 || *pProcnInts == delim )
proc = 0;
else
proc = atoi(pProcnInts);
if ( proc >= NumProc )
proc = (proc % NumProc);
Vector2Affinity[vec] = 1 << proc;
while(*pProcnInts && *pProcnInts != ';')
pProcnInts++; // skip current affinity
if (*pProcnInts == ';')
pProcnInts++; // skip delimiter
HDBG(DBG_MPINTS,
HalpDebugPrint("%6d %6d\n",vec,Vector2Affinity[vec]););
}
return;
}