WindowsXP-SP1/base/hals/halssc/ia64/simsxint.c
2020-09-30 16:53:49 +02:00

445 lines
9.9 KiB
C
Raw Permalink 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.

//
// No Check-in Source Code.
//
// Do not make this code available to non-Microsoft personnel
// without Intel's express permission
//
/**
*** 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:
simsxint.c
Abstract:
This module implements the routines to manage the
system interrupt and IRQL.
Author:
William K. Cheung (wcheung) 14-Apr-1995
Environment:
Kernel mode
Revision History:
--*/
#include "halp.h"
PULONGLONG HalEOITable[256];
VOID
HalpInitEOITable(
VOID
)
{
USHORT Index;
for (Index=0; Index < 256; Index++) {
HalEOITable[Index] = 0;
}
}
VOID
HalpInitializeInterrupts (
VOID
)
{
ULONG Index;
ULONG InterruptVector;
//
// Interrupt routine table initialization in KiInitializeKernel.
//
//
// interval timer interrupt; 10ms by default
//
InterruptVector = CLOCK_LEVEL << VECTOR_IRQL_SHIFT;
PCR->InterruptRoutine[InterruptVector] = (PKINTERRUPT_ROUTINE)HalpClockInterrupt;
SscConnectInterrupt(SSC_CLOCK_TIMER_INTERRUPT, InterruptVector);
SscSetPeriodicInterruptInterval(
SSC_CLOCK_TIMER_INTERRUPT,
DEFAULT_CLOCK_INTERVAL * 100
);
//
// profile timer interrupt; turned off initially
//
InterruptVector = PROFILE_LEVEL << VECTOR_IRQL_SHIFT;
PCR->InterruptRoutine[InterruptVector] = (PKINTERRUPT_ROUTINE)HalpProfileInterrupt;
SscConnectInterrupt(SSC_PROFILE_TIMER_INTERRUPT, InterruptVector);
SscSetPeriodicInterruptInterval (SSC_PROFILE_TIMER_INTERRUPT, 0);
//
// s/w interrupts; corresponding ISRs provided by kernel.
//
SscConnectInterrupt (SSC_APC_INTERRUPT, APC_VECTOR);
SscConnectInterrupt (SSC_DPC_INTERRUPT, DISPATCH_VECTOR);
}
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
--*/
{
KIRQL OldIrql;
BOOLEAN Result = TRUE;
//
// Raise IRQL to the highest level.
//
KeRaiseIrql (HIGH_LEVEL, &OldIrql);
switch (Irql) {
case DISK_IRQL:
SscConnectInterrupt (SSC_DISK_INTERRUPT, Vector);
break;
case MOUSE_IRQL:
SscConnectInterrupt (SSC_MOUSE_INTERRUPT, Vector);
break;
case KEYBOARD_IRQL:
SscConnectInterrupt (SSC_KEYBOARD_INTERRUPT, Vector);
break;
case SERIAL_IRQL:
SscConnectInterrupt (SSC_SERIAL_INTERRUPT, Vector);
break;
default:
//
// Invalid Device Interrupt Source; only three devices
// defined in the Gambit platform.
//
Result = FALSE;
DbgPrint("HalEnableSystemInterrupt: Invalid Device Interrupt Source");
break;
}
//
// Restore the original IRQL
//
KeLowerIrql (OldIrql);
return (Result);
}
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.
--*/
{
return;
}
ULONG
HalGetInterruptVector(
IN INTERFACE_TYPE InterfaceType,
IN ULONG BusNumber,
IN ULONG BusInterruptLevel,
IN ULONG BusInterruptVector,
OUT PKIRQL Irql,
OUT PKAFFINITY Affinity
)
/*++
Routine Description:
This function returns the system interrupt vector and IRQL level
corresponding to the specified bus interrupt level and/or vector. The
system interrupt vector and IRQL are suitable for use in a subsequent call
to KeInitializeInterrupt.
In the simulation environment, just return the parameters passed in
from the caller - the device driver.
Arguments:
InterfaceType - Supplies the type of bus which the vector is for.
BusNumber - Supplies the bus number for the device.
BusInterruptLevel - Supplies the bus specific interrupt level.
BusInterruptVector - Supplies the bus specific interrupt vector.
Irql - Returns the system request priority.
Affinity - Returns the affinity for the requested vector
Return Value:
Returns the system interrupt vector corresponding to the specified device.
--*/
{
//
// Just return the passed parameters.
//
*Irql = (KIRQL) BusInterruptLevel;
*Affinity = 1;
return( BusInterruptLevel << VECTOR_IRQL_SHIFT );
}
BOOLEAN
HalBeginSystemInterrupt(
IN KIRQL Irql,
IN CCHAR Vector,
OUT PKIRQL OldIrql
)
/*++
Routine Description:
This routine raises the IRQL to the level of the specified
interrupt vector. It is called by the hardware interrupt
handler before any other interrupt service routine code is
executed. The CPU interrupt flag is set on exit.
Arguments:
Irql - Supplies the IRQL to raise to
Vector - Supplies the vector of the interrupt to be
dismissed
OldIrql- Location to return OldIrql
Return Value:
TRUE - Interrupt successfully dismissed and Irql raised.
This routine cannot fail.
--*/
{
return (TRUE);
}
VOID
HalEndSystemInterrupt (
IN KIRQL NewIrql,
IN ULONG Vector
)
/*++
Routine Description:
This routine is used to lower IRQL to the specified value.
The IRQL and PIRQL will be updated accordingly.
NOTE: This routine simulates software interrupt as long as
any pending SW interrupt level is higher than the current
IRQL, even when interrupts are disabled.
Arguments:
NewIrql - the new irql to be set.
Vector - Vector number of the interrupt
Return Value:
None.
--*/
{
return;
}
//
// Almost all of the last 4MB of virtual memory address range are available
// to the HAL to map physical memory. The kernel may use some of these
// PTEs for special purposes.
//
//
// The kernel now uses one PTE in this
// area to map the area from which interrupt messages are to be retrieved.
//
#define HAL_VA_START 0xffd00000
PVOID HalpHeapStart=(PVOID)(KADDRESS_BASE+HAL_VA_START);
PVOID
HalMapPhysicalMemory(
IN PHYSICAL_ADDRESS PhysicalAddress,
IN ULONG NumberPages
)
/*++
Routine Description:
This routine maps physical memory into the area of virtual memory
reserved for the HAL. It does this by directly inserting the PTE
into the Page Table which the OS Loader has provided.
N.B. This routine does *NOT* update the MemoryDescriptorList. The
caller is responsible for either removing the appropriate
physical memory from the list, or creating a new descriptor to
describe it.
Arguments:
PhysicalAddress - Supplies the physical address of the start of the
area of physical memory to be mapped.
NumberPages - Supplies the number of pages contained in the area of
physical memory to be mapped.
Return Value:
PVOID - Virtual address at which the requested block of physical memory
was mapped
NULL - The requested block of physical memory could not be mapped.
--*/
{
PHARDWARE_PTE PTE;
ULONG PagesMapped;
PVOID VirtualAddress;
//
// The OS Loader sets up hyperspace for us, so we know that the Page
// Tables are magically mapped starting at V.A. 0xC0000000.
//
PagesMapped = 0;
while (PagesMapped < NumberPages) {
//
// Look for enough consecutive free ptes to honor mapping
//
PagesMapped = 0;
VirtualAddress = HalpHeapStart;
while (PagesMapped < NumberPages) {
PTE=MiGetPteAddress(VirtualAddress);
if (*(PULONGLONG)PTE != 0) {
//
// Pte is not free, skip up to the next pte and start over
//
HalpHeapStart = (PVOID) ((ULONG_PTR)VirtualAddress + PAGE_SIZE);
break;
}
VirtualAddress = (PVOID) ((ULONG_PTR)VirtualAddress + PAGE_SIZE);
PagesMapped++;
}
}
PagesMapped = 0;
VirtualAddress = (PVOID) ((ULONG_PTR) HalpHeapStart | BYTE_OFFSET (PhysicalAddress.QuadPart));
while (PagesMapped < NumberPages) {
PTE=MiGetPteAddress(HalpHeapStart);
PTE->PageFrameNumber = (PhysicalAddress.QuadPart >> PAGE_SHIFT);
PTE->Valid = 1;
PTE->Write = 1;
// TBD PTE->MemAttribute = 0;
PhysicalAddress.QuadPart = PhysicalAddress.QuadPart + PAGE_SIZE;
HalpHeapStart = (PVOID)((ULONG_PTR)HalpHeapStart + PAGE_SIZE);
++PagesMapped;
}
return(VirtualAddress);
}