Leaked source code of windows server 2003
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.
 
 
 
 
 
 

495 lines
12 KiB

//
/**
*** Copyright (C) 1996-97 Intel Corporation. All rights reserved.
***
*** The information and source code contained herein is the exclusive
*** property of Intel Corporation and may not be disclosed, examined
*** or reproduced in whole or in part without explicit written authorization
*** from the company.
**/
/*++
Copyright (c) 1995 Intel Corporation
Module Name:
i64sxint.c copied from simsxint.c
Abstract:
This module implements the routines to manage the
system interrupt and IRQL.
Author:
William K. Cheung (wcheung) 14-Apr-1995
Bernard Lint
M. Jayakumar ([email protected])
Environment:
Kernel mode
Revision History:
Todd Kjos (HP) (v-tkjos) 1-Jun-1998 : Added I/O Sapic support
Thierry Fevrier (HP) (v-thief) 8-Feb-2000 : Profiling support
--*/
#include "halp.h"
#include "iosapic.h"
VOID HalpInitLINT(VOID);
extern KSPIN_LOCK HalpIoSapicLock;
extern PULONG_PTR *HalEOITable[];
PULONG_PTR HalpEOITableP0[MAX_INTR_VECTOR];
VOID
HalpInitializeInterrupts (
VOID
)
/*++
Routine Description:
This function initializes interrupts for an IA64 system.
Arguments:
None.
Return Value:
None.
Note:
In KiInitializeKernel(), PCR.InterruptRoutine[] entries have been first initialized
with the Unexpected Interrupt code then entries index-0, APC_VECTOR, DISPATCH_VECTOR
have been initialized with their respective interrupt handlers.
--*/
{
//
// Turn off LINT0 LINT1 (disable 8259)
//
// We used to call HalpInitLINT here. However it was unnecessary since we
// already called it in HalInitializeProcessor. Also it meant that if a
// CPE occurred prior to this point we would lose it.
//
// interval timer interrupt; 10ms by default
//
HalpInitializeClockInterrupts();
//
// Initialize SpuriousInterrupt
//
HalpSetInternalVector(SAPIC_SPURIOUS_VECTOR, HalpSpuriousHandler);
//
// Initialize CMCI Interrupt
//
// Note that it is possible that HAL_CMC_PRESENT is not set.
// With the current implementation, we always connect the vector to the ISR.
//
HalpSetInternalVector(CMCI_VECTOR, HalpCMCIHandler);
//
// Initialize CPEI Interrupt
//
// Note that it is possible that HAL_CPE_PRESENT is not set.
// With the current implementation, we always connect the vector to the ISR.
//
HalpSetInternalVector(CPEI_VECTOR, HalpCPEIHandler);
//
// Initialiaze MC Rendezvous Interrupt
//
HalpSetInternalVector(MC_RZ_VECTOR, HalpMcRzHandler);
//
// Initialize MC Wakeup Interrupt
//
HalpSetInternalVector(MC_WKUP_VECTOR, HalpMcWkupHandler);
//
// IPI Interrupt
//
HalpSetInternalVector(IPI_VECTOR, HalpIpiInterruptHandler);
//
// profile timer interrupt; turned off initially
//
HalpSetInternalVector(PROFILE_VECTOR, HalpProfileInterrupt);
//
// Performance monitor interrupt
//
HalpSetInternalVector(PERF_VECTOR, HalpPerfInterrupt);
} // HalpInitializeInterrupts()
VOID
HalpInitEOITable(
VOID
)
{
USHORT Index;
ULONG ProcessorNumber;
// Allocate and Initialize EOI table on current processor
ProcessorNumber = PCR->Prcb->Number;
if (ProcessorNumber == 0) {
HalEOITable[ProcessorNumber] = HalpEOITableP0;
} else {
HalEOITable[ProcessorNumber] = ExAllocatePool(NonPagedPool,
MAX_INTR_VECTOR*sizeof(HalEOITable[0]));
}
// For kernel access to eoi table
PCR->EOITable = HalEOITable[ProcessorNumber];
for (Index=0; Index < MAX_INTR_VECTOR; Index++) {
HalEOITable[ProcessorNumber][Index] = 0;
}
}
VOID
HalpWriteEOITable(
IN ULONG Vector,
IN PULONG_PTR EoiAddress,
IN ULONG Number
)
/*++
Routine Description:
This routine updates the EOI table for a processor
Arguments:
Vector - Entry to update (IDT entry)
EoiAddress - Address to write (SAPIC address)
Number - Logical (NT) processor number
Return Value:
None
--*/
{
if (HalEOITable != NULL && HalEOITable[Number] != NULL) {
HalEOITable[Number][Vector] = EoiAddress;
}
}
BOOLEAN
HalEnableSystemInterrupt (
IN ULONG Vector,
IN KIRQL Irql,
IN KINTERRUPT_MODE InterruptMode
)
/*++
Routine Description:
This routine enables the specified system interrupt.
N.B. This routine assumes that the caller has provided any required
synchronization to enable a system interrupt.
Arguments:
Vector - Supplies the vector of the system interrupt that is enabled.
Irql - Supplies the IRQL of the interrupting source.
InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
Latched.
Return Value:
TRUE if the system interrupt was enabled
--*/
{
ULONG Entry, Destination;
ULONG OldLevel;
ULONG Inti;
ULONG LevelAndPolarity;
USHORT ThisCpuApicID;
ULONG InterruptType;
BOOLEAN RetVal = TRUE;
UCHAR IDTEntry;
ASSERT(Vector < (ULONG)((1+HAL_MAXIMUM_PROCESSOR)*0x100-1));
ASSERT(Irql <= HIGH_LEVEL);
HalDebugPrint(( HAL_VERBOSE, "HAL: HalpEnableSystemInterrupt - INTI=0x%x Vector=0x%x IRQL=0x%x\n",
HalpVectorToINTI[Vector],
Vector,
Irql ));
if ( (Inti = HalpVectorToINTI[Vector]) == ~0UL ) {
return FALSE;
}
if (HalpIsInternalInterruptVector(Vector)) {
//
// There is no external device associated with this interrupt,
// but it might be an internal interrupt i.e. one that never
// involves the IOSAPIC.
//
return TRUE;
}
// Make sure the passed-in level matches our settings...
if ((InterruptMode == LevelSensitive && !HalpIsLevelTriggered(Inti)) ||
(InterruptMode != LevelSensitive && HalpIsLevelTriggered(Inti)) ) {
// It doesn't match!
HalDebugPrint(( HAL_INFO, "HAL: HalpEnableSystemInterrupt - Warning device interrupt mode overridden\n"));
}
LevelAndPolarity =
(HalpIsLevelTriggered(Inti) ? LEVEL_TRIGGERED : EDGE_TRIGGERED) |
(HalpIsActiveLow(Inti) ? ACTIVE_LOW : ACTIVE_HIGH);
//
// Block interrupts and synchronize until we're done
//
OldLevel = HalpAcquireHighLevelLock (&HalpIoSapicLock);
ThisCpuApicID = (USHORT)KeGetPcr()->HalReserved[PROCESSOR_ID_INDEX];
// Get Interrupt type
HalpGetRedirEntry(Inti,&Entry,&Destination);
InterruptType = Entry & INT_TYPE_MASK;
IDTEntry = HalVectorToIDTEntry(Vector);
switch (InterruptType) {
case DELIVER_FIXED:
case DELIVER_LOW_PRIORITY:
//
// Normal external interrupt...
// Enable the interrupt in the I/O SAPIC redirection table
//
if (IDTEntry < 16) {
// Reserved vectors: Extint, NMI, IntelReserved
// No vectors in this range can be assigned
ASSERT(0);
RetVal = FALSE;
break;
}
//
// All external interrupts are delivered as Fixed interrupts
// without the "redirectable" bit set (aka Lowest Priority). This
// disallows hardware to redirect the interrupts using the XTP mechanism.
//
Entry = (ULONG)IDTEntry | LevelAndPolarity;
HalpSetRedirEntry ( Inti, Entry, ThisCpuApicID );
break;
case DELIVER_EXTINT:
//
// This is an interrupt that uses the IO Sapic to route PIC
// events. This configuration is not supported in IA64.
//
ASSERT(0);
RetVal = FALSE;
break;
default:
HalDebugPrint(( HAL_ERROR, "HAL: HalEnableSystemInterrupt - Unknown Interrupt Type: %d\n",
InterruptType));
RetVal = FALSE;
break;
} // switch (InterruptType)
HalpReleaseHighLevelLock (&HalpIoSapicLock, OldLevel);
return(RetVal);
}
VOID
HalDisableSystemInterrupt (
IN ULONG Vector,
IN KIRQL Irql
)
/*++
Routine Description:
This routine disables the specified system interrupt.
In the simulation environment, this function does nothing and returns.
N.B. This routine assumes that the caller has provided any required
synchronization to disable a system interrupt.
Arguments:
Vector - Supplies the vector of the system interrupt that is disabled.
Irql - Supplies the IRQL of the interrupting source.
Return Value:
None.
--*/
{
ULONG Entry, Destination;
ULONG OldLevel;
ULONG Inti;
ULONG LevelAndPolarity;
ULONG ThisCpuApicID;
ULONG InterruptType;
ASSERT(Vector < (1+HAL_MAXIMUM_PROCESSOR)*0x100-1);
ASSERT(Irql <= HIGH_LEVEL);
HalDebugPrint(( HAL_INFO, "HAL: HalpDisableSystemInterrupt: INTI=%x Vector=%x IRQL=%x\n",
HalpVectorToINTI[Vector],
Vector,
Irql));
if ( (Inti = HalpVectorToINTI[Vector]) == (ULONG)-1 ) {
//
// There is no external device associated with this interrupt
//
return;
}
//
// Block interrupts and synchronize until we're done
//
OldLevel = HalpAcquireHighLevelLock(&HalpIoSapicLock);
ThisCpuApicID = (USHORT)KeGetPcr()->HalReserved[PROCESSOR_ID_INDEX];
// Get Interrupt Type and Destination
HalpGetRedirEntry(Inti, &Entry, &Destination);
if (ThisCpuApicID != Destination) {
// The interrupt is not enabled on this Cpu
HalpReleaseHighLevelLock (&HalpIoSapicLock, OldLevel);
return;
}
InterruptType = Entry & INT_TYPE_MASK;
switch (InterruptType) {
case DELIVER_FIXED:
//
// Normal external interrupt...
// Disable the interrupt in the I/O SAPIC redirection table
//
if (Vector < 16) {
// Reserved vectors: Extint, NMI, IntelReserved
// No vectors in this range can be assigned
ASSERT(0);
break;
}
HalpDisableRedirEntry (Inti);
break;
case DELIVER_EXTINT:
//
// This is an interrupt that uses the IO Sapic to route PIC
// events. This configuration is not supported in IA64.
//
ASSERT(0);
break;
default:
HalDebugPrint(( HAL_INFO, "HAL: HalDisableSystemInterrupt - Unknown Interrupt Type: %d\n",
InterruptType ));
break;
} // switch (InterruptType)
HalpReleaseHighLevelLock (&HalpIoSapicLock, OldLevel);
}
ULONG
HalpGetProcessorNumberByApicId(
USHORT ApicId
)
/*++
Routine Description:
This routine returns the logical processor number for a given
physical processor id (extended local sapic id)
Arguments:
ApicId -- Extended ID of processor (16 bit id)
Return Value:
Logical (NT) processor number
--*/
{
ULONG index;
for (index = 0; index < HalpMpInfo.ProcessorCount; index++) {
if (ApicId == HalpProcessorInfo[index].LocalApicID) {
return HalpProcessorInfo[index].NtProcessorNumber;
}
}
ASSERT (index < HalpMpInfo.ProcessorCount);
//
// Note: The previous code returned an invalid index (HalpMpInfo.ProcessorCount
// which is 1 greater than the number of processors) we should probably
// just bugcheck here.
//
return 0;
}