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