445 lines
9.4 KiB
C
445 lines
9.4 KiB
C
|
//
|
|||
|
// 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);
|
|||
|
}
|
|||
|
|