mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
[HAL:APIC] Code fixes
* Fix some broken code * Add some ASSERTs * Use ApicWriteIORedirectionEntry where appropriate * Use KeQueryInterruptHandler/KeRegisterInterruptHandler to save/restore the old handler instead of saving the KIDTENTRY * Move HalpProfileInterruptHandler to apictimer.c and implement it * Use READ/WRITE_REGISTER macros * Add some symbolic names
This commit is contained in:
parent
ee514e954b
commit
b7a149fcec
5 changed files with 40 additions and 32 deletions
|
@ -94,8 +94,9 @@ ULONG
|
||||||
IOApicRead(UCHAR Register)
|
IOApicRead(UCHAR Register)
|
||||||
{
|
{
|
||||||
/* Select the register, then do the read */
|
/* Select the register, then do the read */
|
||||||
*(volatile UCHAR *)(IOAPIC_BASE + IOAPIC_IOREGSEL) = Register;
|
ASSERT(Register <= 0x3F);
|
||||||
return *(volatile ULONG *)(IOAPIC_BASE + IOAPIC_IOWIN);
|
WRITE_REGISTER_ULONG((PULONG)(IOAPIC_BASE + IOAPIC_IOREGSEL), Register);
|
||||||
|
return READ_REGISTER_ULONG((PULONG)(IOAPIC_BASE + IOAPIC_IOWIN));
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCEINLINE
|
FORCEINLINE
|
||||||
|
@ -103,8 +104,9 @@ VOID
|
||||||
IOApicWrite(UCHAR Register, ULONG Value)
|
IOApicWrite(UCHAR Register, ULONG Value)
|
||||||
{
|
{
|
||||||
/* Select the register, then do the write */
|
/* Select the register, then do the write */
|
||||||
*(volatile UCHAR *)(IOAPIC_BASE + IOAPIC_IOREGSEL) = Register;
|
ASSERT(Register <= 0x3F);
|
||||||
*(volatile ULONG *)(IOAPIC_BASE + IOAPIC_IOWIN) = Value;
|
WRITE_REGISTER_ULONG((PULONG)(IOAPIC_BASE + IOAPIC_IOREGSEL), Register);
|
||||||
|
WRITE_REGISTER_ULONG((PULONG)(IOAPIC_BASE + IOAPIC_IOWIN), Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCEINLINE
|
FORCEINLINE
|
||||||
|
@ -113,6 +115,7 @@ ApicWriteIORedirectionEntry(
|
||||||
UCHAR Index,
|
UCHAR Index,
|
||||||
IOAPIC_REDIRECTION_REGISTER ReDirReg)
|
IOAPIC_REDIRECTION_REGISTER ReDirReg)
|
||||||
{
|
{
|
||||||
|
ASSERT(Index < APIC_MAX_IRQ);
|
||||||
IOApicWrite(IOAPIC_REDTBL + 2 * Index, ReDirReg.Long0);
|
IOApicWrite(IOAPIC_REDTBL + 2 * Index, ReDirReg.Long0);
|
||||||
IOApicWrite(IOAPIC_REDTBL + 2 * Index + 1, ReDirReg.Long1);
|
IOApicWrite(IOAPIC_REDTBL + 2 * Index + 1, ReDirReg.Long1);
|
||||||
}
|
}
|
||||||
|
@ -124,6 +127,7 @@ ApicReadIORedirectionEntry(
|
||||||
{
|
{
|
||||||
IOAPIC_REDIRECTION_REGISTER ReDirReg;
|
IOAPIC_REDIRECTION_REGISTER ReDirReg;
|
||||||
|
|
||||||
|
ASSERT(Index < APIC_MAX_IRQ);
|
||||||
ReDirReg.Long0 = IOApicRead(IOAPIC_REDTBL + 2 * Index);
|
ReDirReg.Long0 = IOApicRead(IOAPIC_REDTBL + 2 * Index);
|
||||||
ReDirReg.Long1 = IOApicRead(IOAPIC_REDTBL + 2 * Index + 1);
|
ReDirReg.Long1 = IOApicRead(IOAPIC_REDTBL + 2 * Index + 1);
|
||||||
|
|
||||||
|
@ -344,7 +348,7 @@ HalpAllocateSystemInterrupt(
|
||||||
Vector = IrqlToTpr(Irql) & 0xF0;
|
Vector = IrqlToTpr(Irql) & 0xF0;
|
||||||
|
|
||||||
/* Find an empty vector */
|
/* Find an empty vector */
|
||||||
while (HalpVectorToIndex[Vector] != 0xFF)
|
while (HalpVectorToIndex[Vector] != APIC_FREE_VECTOR)
|
||||||
{
|
{
|
||||||
Vector++;
|
Vector++;
|
||||||
|
|
||||||
|
@ -372,8 +376,7 @@ HalpAllocateSystemInterrupt(
|
||||||
ReDirReg.Destination = 0;
|
ReDirReg.Destination = 0;
|
||||||
|
|
||||||
/* Initialize entry */
|
/* Initialize entry */
|
||||||
IOApicWrite(IOAPIC_REDTBL + 2 * Irq, ReDirReg.Long0);
|
ApicWriteIORedirectionEntry(Irq, ReDirReg);
|
||||||
IOApicWrite(IOAPIC_REDTBL + 2 * Irq + 1, ReDirReg.Long1);
|
|
||||||
|
|
||||||
return Vector;
|
return Vector;
|
||||||
}
|
}
|
||||||
|
@ -410,17 +413,16 @@ ApicInitializeIOApic(VOID)
|
||||||
ReDirReg.Destination = 0;
|
ReDirReg.Destination = 0;
|
||||||
|
|
||||||
/* Loop all table entries */
|
/* Loop all table entries */
|
||||||
for (Index = 0; Index < 24; Index++)
|
for (Index = 0; Index < APIC_MAX_IRQ; Index++)
|
||||||
{
|
{
|
||||||
/* Initialize entry */
|
/* Initialize entry */
|
||||||
IOApicWrite(IOAPIC_REDTBL + 2 * Index, ReDirReg.Long0);
|
ApicWriteIORedirectionEntry(Index, ReDirReg);
|
||||||
IOApicWrite(IOAPIC_REDTBL + 2 * Index + 1, ReDirReg.Long1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Init the vactor to index table */
|
/* Init the vactor to index table */
|
||||||
for (Vector = 0; Vector <= 255; Vector++)
|
for (Vector = 0; Vector <= 255; Vector++)
|
||||||
{
|
{
|
||||||
HalpVectorToIndex[Vector] = 0xFF;
|
HalpVectorToIndex[Vector] = APIC_FREE_VECTOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// HACK: Allocate all IRQs, should rather do that on demand
|
// HACK: Allocate all IRQs, should rather do that on demand
|
||||||
|
@ -437,7 +439,7 @@ ApicInitializeIOApic(VOID)
|
||||||
ReDirReg.TriggerMode = APIC_TGM_Edge;
|
ReDirReg.TriggerMode = APIC_TGM_Edge;
|
||||||
ReDirReg.Mask = 0;
|
ReDirReg.Mask = 0;
|
||||||
ReDirReg.Destination = ApicRead(APIC_ID);
|
ReDirReg.Destination = ApicRead(APIC_ID);
|
||||||
IOApicWrite(IOAPIC_REDTBL + 2 * APIC_CLOCK_INDEX, ReDirReg.Long0);
|
ApicWriteIORedirectionEntry(APIC_CLOCK_INDEX, ReDirReg);
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
@ -457,9 +459,10 @@ HalpInitializePICs(IN BOOLEAN EnableInterrupts)
|
||||||
ApicInitializeIOApic();
|
ApicInitializeIOApic();
|
||||||
|
|
||||||
/* Manually reserve some vectors */
|
/* Manually reserve some vectors */
|
||||||
|
HalpVectorToIndex[APC_VECTOR] = APIC_RESERVED_VECTOR;
|
||||||
|
HalpVectorToIndex[DISPATCH_VECTOR] = APIC_RESERVED_VECTOR;
|
||||||
HalpVectorToIndex[APIC_CLOCK_VECTOR] = 8;
|
HalpVectorToIndex[APIC_CLOCK_VECTOR] = 8;
|
||||||
HalpVectorToIndex[APC_VECTOR] = 99;
|
HalpVectorToIndex[APIC_SPURIOUS_VECTOR] = APIC_RESERVED_VECTOR;
|
||||||
HalpVectorToIndex[DISPATCH_VECTOR] = 99;
|
|
||||||
|
|
||||||
/* Set interrupt handlers in the IDT */
|
/* Set interrupt handlers in the IDT */
|
||||||
KeRegisterInterruptHandler(APIC_CLOCK_VECTOR, HalpClockInterrupt);
|
KeRegisterInterruptHandler(APIC_CLOCK_VECTOR, HalpClockInterrupt);
|
||||||
|
@ -669,7 +672,7 @@ HalDisableSystemInterrupt(
|
||||||
ReDirReg.Mask = 1;
|
ReDirReg.Mask = 1;
|
||||||
|
|
||||||
/* Write back lower dword */
|
/* Write back lower dword */
|
||||||
IOApicWrite(IOAPIC_REDTBL + 2 * Irql, ReDirReg.Long0);
|
IOApicWrite(IOAPIC_REDTBL + 2 * Index, ReDirReg.Long0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef _M_AMD64
|
#ifndef _M_AMD64
|
||||||
|
@ -704,8 +707,8 @@ HalBeginSystemInterrupt(
|
||||||
/* Get the irq for this vector */
|
/* Get the irq for this vector */
|
||||||
Index = HalpVectorToIndex[Vector];
|
Index = HalpVectorToIndex[Vector];
|
||||||
|
|
||||||
/* Check if its valid */
|
/* Check if it's valid */
|
||||||
if (Index != 0xff)
|
if (Index < APIC_MAX_IRQ)
|
||||||
{
|
{
|
||||||
/* Read the I/O redirection entry */
|
/* Read the I/O redirection entry */
|
||||||
RedirReg = ApicReadIORedirectionEntry(Index);
|
RedirReg = ApicReadIORedirectionEntry(Index);
|
||||||
|
@ -715,6 +718,9 @@ HalBeginSystemInterrupt(
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
/* This should be a reserved vector! */
|
||||||
|
ASSERT(Index == APIC_RESERVED_VECTOR);
|
||||||
|
|
||||||
/* Re-request the interrupt to be handled later */
|
/* Re-request the interrupt to be handled later */
|
||||||
ApicRequestInterrupt(Vector, APIC_TGM_Edge);
|
ApicRequestInterrupt(Vector, APIC_TGM_Edge);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,10 @@
|
||||||
#define TprToIrql(Tpr) (HalVectorToIRQL[Tpr >> 4])
|
#define TprToIrql(Tpr) (HalVectorToIRQL[Tpr >> 4])
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define APIC_MAX_IRQ 24
|
||||||
|
#define APIC_FREE_VECTOR 0xFF
|
||||||
|
#define APIC_RESERVED_VECTOR 0xFE
|
||||||
|
|
||||||
/* The IMCR is supported by two read/writable or write-only I/O ports,
|
/* The IMCR is supported by two read/writable or write-only I/O ports,
|
||||||
22h and 23h, which receive address and data respectively.
|
22h and 23h, which receive address and data respectively.
|
||||||
To access the IMCR, write a value of 70h to I/O port 22h, which selects the IMCR.
|
To access the IMCR, write a value of 70h to I/O port 22h, which selects the IMCR.
|
||||||
|
@ -284,14 +288,14 @@ FORCEINLINE
|
||||||
ULONG
|
ULONG
|
||||||
ApicRead(ULONG Offset)
|
ApicRead(ULONG Offset)
|
||||||
{
|
{
|
||||||
return *(volatile ULONG *)(APIC_BASE + Offset);
|
return READ_REGISTER_ULONG((PULONG)(APIC_BASE + Offset));
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCEINLINE
|
FORCEINLINE
|
||||||
VOID
|
VOID
|
||||||
ApicWrite(ULONG Offset, ULONG Value)
|
ApicWrite(ULONG Offset, ULONG Value)
|
||||||
{
|
{
|
||||||
*(volatile ULONG *)(APIC_BASE + Offset) = Value;
|
WRITE_REGISTER_ULONG((PULONG)(APIC_BASE + Offset), Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
|
|
@ -61,6 +61,13 @@ ApicInitializeTimer(ULONG Cpu)
|
||||||
// KeSetTimeIncrement
|
// KeSetTimeIncrement
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
FASTCALL
|
||||||
|
HalpProfileInterruptHandler(_In_ PKTRAP_FRAME TrapFrame)
|
||||||
|
{
|
||||||
|
KeProfileInterruptWithSource(TrapFrame, ProfileTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* PUBLIC FUNCTIONS ***********************************************************/
|
/* PUBLIC FUNCTIONS ***********************************************************/
|
||||||
|
|
||||||
|
|
|
@ -167,13 +167,6 @@ HalpClockInterruptHandler(IN PKTRAP_FRAME TrapFrame)
|
||||||
KeUpdateSystemTime(TrapFrame, LastIncrement, Irql);
|
KeUpdateSystemTime(TrapFrame, LastIncrement, Irql);
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
|
||||||
FASTCALL
|
|
||||||
HalpProfileInterruptHandler(IN PKTRAP_FRAME TrapFrame)
|
|
||||||
{
|
|
||||||
__debugbreak();
|
|
||||||
}
|
|
||||||
|
|
||||||
ULONG
|
ULONG
|
||||||
NTAPI
|
NTAPI
|
||||||
HalSetTimeIncrement(IN ULONG Increment)
|
HalSetTimeIncrement(IN ULONG Increment)
|
||||||
|
|
|
@ -55,8 +55,7 @@ NTAPI
|
||||||
HalpInitializeTsc(VOID)
|
HalpInitializeTsc(VOID)
|
||||||
{
|
{
|
||||||
ULONG_PTR Flags;
|
ULONG_PTR Flags;
|
||||||
KIDTENTRY OldIdtEntry, *IdtPointer;
|
PVOID PreviousHandler;
|
||||||
PKPCR Pcr = KeGetPcr();
|
|
||||||
UCHAR RegisterA, RegisterB;
|
UCHAR RegisterA, RegisterB;
|
||||||
|
|
||||||
/* Check if the CPU supports RDTSC */
|
/* Check if the CPU supports RDTSC */
|
||||||
|
@ -79,8 +78,7 @@ HalpInitializeTsc(VOID)
|
||||||
HalpWriteCmos(RTC_REGISTER_A, RegisterA);
|
HalpWriteCmos(RTC_REGISTER_A, RegisterA);
|
||||||
|
|
||||||
/* Save old IDT entry */
|
/* Save old IDT entry */
|
||||||
IdtPointer = KiGetIdtEntry(Pcr, HalpRtcClockVector);
|
PreviousHandler = KeQueryInterruptHandler(HalpRtcClockVector);
|
||||||
OldIdtEntry = *IdtPointer;
|
|
||||||
|
|
||||||
/* Set the calibration ISR */
|
/* Set the calibration ISR */
|
||||||
KeRegisterInterruptHandler(HalpRtcClockVector, TscCalibrationISR);
|
KeRegisterInterruptHandler(HalpRtcClockVector, TscCalibrationISR);
|
||||||
|
@ -105,8 +103,8 @@ HalpInitializeTsc(VOID)
|
||||||
/* Disable the timer interrupt */
|
/* Disable the timer interrupt */
|
||||||
HalDisableSystemInterrupt(HalpRtcClockVector, CLOCK_LEVEL);
|
HalDisableSystemInterrupt(HalpRtcClockVector, CLOCK_LEVEL);
|
||||||
|
|
||||||
/* Restore old IDT entry */
|
/* Restore the previous handler */
|
||||||
*IdtPointer = OldIdtEntry;
|
KeRegisterInterruptHandler(HalpRtcClockVector, PreviousHandler);
|
||||||
|
|
||||||
/* Calculate an average, using simplified linear regression */
|
/* Calculate an average, using simplified linear regression */
|
||||||
HalpCpuClockFrequency.QuadPart = DoLinearRegression(NUM_SAMPLES - 1,
|
HalpCpuClockFrequency.QuadPart = DoLinearRegression(NUM_SAMPLES - 1,
|
||||||
|
|
Loading…
Reference in a new issue