reactos/hal/halarm/generic/pic.c
Hermès Bélusca-Maïto 94c25baf85
[HAL][HALARM] The HAL should only use KPCR.
And why the ARM HAL uses KPCR::InterruptRoutine, a field only defined
in *powerpc*/ketypes.h, is beyond me, but OK...

See Timo vs. Alex discussion, explaining that KIPCR is a ReactOS-only
thing: https://reactos.org/archives/public/ros-dev/2008-August/010549.html
2022-05-08 17:21:44 +02:00

342 lines
6.6 KiB
C

/*
* PROJECT: ReactOS HAL
* LICENSE: BSD - See COPYING.ARM in the top level directory
* FILE: hal/halarm/generic/pic.c
* PURPOSE: HAL PIC Management and Control Code
* PROGRAMMERS: ReactOS Portable Systems Group
*/
/* INCLUDES *******************************************************************/
#include <hal.h>
#define NDEBUG
#include <debug.h>
#undef KeGetCurrentIrql
/* GLOBALS ********************************************************************/
ULONG HalpIrqlTable[HIGH_LEVEL + 1] =
{
0xFFFFFFFF, // IRQL 0 PASSIVE_LEVEL
0xFFFFFFFD, // IRQL 1 APC_LEVEL
0xFFFFFFF9, // IRQL 2 DISPATCH_LEVEL
0xFFFFFFD9, // IRQL 3
0xFFFFFF99, // IRQL 4
0xFFFFFF19, // IRQL 5
0xFFFFFE19, // IRQL 6
0xFFFFFC19, // IRQL 7
0xFFFFF819, // IRQL 8
0xFFFFF019, // IRQL 9
0xFFFFE019, // IRQL 10
0xFFFFC019, // IRQL 11
0xFFFF8019, // IRQL 12
0xFFFF0019, // IRQL 13
0xFFFE0019, // IRQL 14
0xFFFC0019, // IRQL 15
0xFFF80019, // IRQL 16
0xFFF00019, // IRQL 17
0xFFE00019, // IRQL 18
0xFFC00019, // IRQL 19
0xFF800019, // IRQL 20
0xFF000019, // IRQL 21
0xFE000019, // IRQL 22
0xFC000019, // IRQL 23
0xF0000019, // IRQL 24
0x80000019, // IRQL 25
0x19, // IRQL 26
0x18, // IRQL 27 PROFILE_LEVEL
0x10, // IRQL 28 CLOCK2_LEVEL
0x00, // IRQL 29 IPI_LEVEL
0x00, // IRQL 30 POWER_LEVEL
0x00, // IRQL 31 HIGH_LEVEL
};
UCHAR HalpMaskTable[HIGH_LEVEL + 1] =
{
PROFILE_LEVEL, // INT 0 WATCHDOG
APC_LEVEL, // INT 1 SOFTWARE INTERRUPT
DISPATCH_LEVEL,// INT 2 COMM RX
IPI_LEVEL, // INT 3 COMM TX
CLOCK2_LEVEL, // INT 4 TIMER 0
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
26,
26
};
/* FUNCTIONS ******************************************************************/
VOID
HalpInitializeInterrupts(VOID)
{
PKPCR Pcr = KeGetPcr();
/* Fill out the IRQL mappings */
RtlCopyMemory(Pcr->IrqlTable, HalpIrqlTable, sizeof(Pcr->IrqlTable));
RtlCopyMemory(Pcr->IrqlMask, HalpMaskTable, sizeof(Pcr->IrqlMask));
}
/* IRQL MANAGEMENT ************************************************************/
/*
* @implemented
*/
ULONG
HalGetInterruptSource(VOID)
{
ULONG InterruptStatus;
/* Get the interrupt status, and return the highest bit set */
InterruptStatus = READ_REGISTER_ULONG(VIC_INT_STATUS);
return 31 - _clz(InterruptStatus);
}
/*
* @implemented
*/
KIRQL
NTAPI
KeGetCurrentIrql(VOID)
{
/* Return the IRQL */
return KeGetPcr()->Irql;
}
/*
* @implemented
*/
KIRQL
NTAPI
KeRaiseIrqlToDpcLevel(VOID)
{
PKPCR Pcr = KeGetPcr();
KIRQL CurrentIrql;
/* Save and update IRQL */
CurrentIrql = Pcr->Irql;
Pcr->Irql = DISPATCH_LEVEL;
#ifdef IRQL_DEBUG
/* Validate correct raise */
if (CurrentIrql > DISPATCH_LEVEL) KeBugCheck(IRQL_NOT_GREATER_OR_EQUAL);
#endif
/* Return the previous value */
return CurrentIrql;
}
/*
* @implemented
*/
KIRQL
NTAPI
KeRaiseIrqlToSynchLevel(VOID)
{
PKPCR Pcr = KeGetPcr();
KIRQL CurrentIrql;
/* Save and update IRQL */
CurrentIrql = Pcr->Irql;
Pcr->Irql = SYNCH_LEVEL;
#ifdef IRQL_DEBUG
/* Validate correct raise */
if (CurrentIrql > SYNCH_LEVEL)
{
/* Crash system */
KeBugCheckEx(IRQL_NOT_GREATER_OR_EQUAL,
CurrentIrql,
SYNCH_LEVEL,
0,
1);
}
#endif
/* Return the previous value */
return CurrentIrql;
}
/*
* @implemented
*/
KIRQL
FASTCALL
KfRaiseIrql(IN KIRQL NewIrql)
{
ARM_STATUS_REGISTER Flags;
PKPCR Pcr = KeGetPcr();
KIRQL CurrentIrql;
ULONG InterruptMask;
/* Disable interrupts */
Flags = KeArmStatusRegisterGet();
_disable();
/* Read current IRQL */
CurrentIrql = Pcr->Irql;
#ifdef IRQL_DEBUG
/* Validate correct raise */
if (CurrentIrql > NewIrql)
{
/* Crash system */
Pcr->Irql = PASSIVE_LEVEL;
KeBugCheck(IRQL_NOT_GREATER_OR_EQUAL);
}
#endif
/* Clear interrupts associated to the old IRQL */
WRITE_REGISTER_ULONG(VIC_INT_CLEAR, 0xFFFFFFFF);
/* Set the new interrupt mask */
InterruptMask = Pcr->IrqlTable[NewIrql];
WRITE_REGISTER_ULONG(VIC_INT_ENABLE, InterruptMask);
/* Set new IRQL */
Pcr->Irql = NewIrql;
/* Restore interrupt state */
if (!Flags.IrqDisable) _enable();
/* Return old IRQL */
return CurrentIrql;
}
/*
* @implemented
*/
VOID
FASTCALL
KfLowerIrql(IN KIRQL NewIrql)
{
ARM_STATUS_REGISTER Flags;
PKPCR Pcr = KeGetPcr();
ULONG InterruptMask;
/* Disableinterrupts */
Flags = KeArmStatusRegisterGet();
_disable();
#ifdef IRQL_DEBUG
/* Validate correct lower */
if (OldIrql > Pcr->Irql)
{
/* Crash system */
Pcr->Irql = HIGH_LEVEL;
KeBugCheck(IRQL_NOT_LESS_OR_EQUAL);
}
#endif
/* Clear interrupts associated to the old IRQL */
WRITE_REGISTER_ULONG(VIC_INT_CLEAR, 0xFFFFFFFF);
/* Set the new interrupt mask */
InterruptMask = Pcr->IrqlTable[NewIrql];
WRITE_REGISTER_ULONG(VIC_INT_ENABLE, InterruptMask);
/* Save the new IRQL and restore interrupt state */
Pcr->Irql = NewIrql;
if (!Flags.IrqDisable) _enable();
}
/* SOFTWARE INTERRUPTS ********************************************************/
/*
* @implemented
*/
VOID
FASTCALL
HalRequestSoftwareInterrupt(IN KIRQL Irql)
{
/* Force a software interrupt */
WRITE_REGISTER_ULONG(VIC_SOFT_INT, 1 << Irql);
}
/*
* @implemented
*/
VOID
FASTCALL
HalClearSoftwareInterrupt(IN KIRQL Irql)
{
/* Clear software interrupt */
WRITE_REGISTER_ULONG(VIC_SOFT_INT_CLEAR, 1 << Irql);
}
/* SYSTEM INTERRUPTS **********************************************************/
/*
* @implemented
*/
BOOLEAN
NTAPI
HalEnableSystemInterrupt(IN ULONG Vector,
IN KIRQL Irql,
IN KINTERRUPT_MODE InterruptMode)
{
UNIMPLEMENTED;
while (TRUE);
return FALSE;
}
/*
* @implemented
*/
VOID
NTAPI
HalDisableSystemInterrupt(IN ULONG Vector,
IN KIRQL Irql)
{
UNIMPLEMENTED;
while (TRUE);
}
/*
* @implemented
*/
BOOLEAN
NTAPI
HalBeginSystemInterrupt(IN KIRQL Irql,
IN ULONG Vector,
OUT PKIRQL OldIrql)
{
UNIMPLEMENTED;
while (TRUE);
return FALSE;
}
/*
* @implemented
*/
VOID
NTAPI
HalEndSystemInterrupt(IN KIRQL OldIrql,
IN PKTRAP_FRAME TrapFrame)
{
UNIMPLEMENTED;
while (TRUE);
}
/* EOF */