mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-09-02 12:23:31 +00:00
[HAL]
- Fix I/O APIC register access - set APIC logical id based on Cpu (currently flat model with up to 8 cpus supported) - In HalpInitializeTsc, setup the RTC clock, since the timer is initialized later - in the TSC calibration ISR, send EOI and read RTC register C to get the next interrupt svn path=/trunk/; revision=53634
This commit is contained in:
@@ -88,7 +88,7 @@ FORCEINLINE
|
||||
IOApicRead(UCHAR Register)
|
||||
{
|
||||
/* Select the register, then do the read */
|
||||
*(volatile ULONG *)(IOAPIC_BASE + IOAPIC_IOREGSEL) = Register;
|
||||
*(volatile UCHAR *)(IOAPIC_BASE + IOAPIC_IOREGSEL) = Register;
|
||||
return *(volatile ULONG *)(IOAPIC_BASE + IOAPIC_IOWIN);
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ FORCEINLINE
|
||||
IOApicWrite(UCHAR Register, ULONG Value)
|
||||
{
|
||||
/* Select the register, then do the write */
|
||||
*(volatile ULONG *)(IOAPIC_BASE + IOAPIC_IOREGSEL) = Register;
|
||||
*(volatile UCHAR *)(IOAPIC_BASE + IOAPIC_IOREGSEL) = Register;
|
||||
*(volatile ULONG *)(IOAPIC_BASE + IOAPIC_IOWIN) = Value;
|
||||
}
|
||||
|
||||
@@ -241,6 +241,12 @@ ApicInitializeLocalApic(ULONG Cpu)
|
||||
SpIntRegister.FocusCPUCoreChecking = 0;
|
||||
ApicWrite(APIC_SIVR, SpIntRegister.Long);
|
||||
|
||||
/* Set the mode to flat (max 8 CPUs supported!) */
|
||||
ApicWrite(APIC_DFR, APIC_DF_Flat);
|
||||
|
||||
/* Set logical apic ID */
|
||||
ApicWrite(APIC_LDR, ApicLogicalId(Cpu) << 24);
|
||||
|
||||
/* Set the spurious ISR */
|
||||
KeRegisterInterruptHandler(APIC_SPURIOUS_VECTOR, ApicSpuriousService);
|
||||
|
||||
@@ -409,9 +415,11 @@ ApicInitializeIOApic(VOID)
|
||||
|
||||
/* Enable the timer interrupt */
|
||||
ReDirReg.Vector = APIC_CLOCK_VECTOR;
|
||||
ReDirReg.DestinationMode = APIC_DM_Logical;
|
||||
ReDirReg.DeliveryMode = APIC_MT_Fixed;
|
||||
ReDirReg.DestinationMode = APIC_DM_Physical;
|
||||
ReDirReg.TriggerMode = APIC_TGM_Edge;
|
||||
ReDirReg.Mask = 0;
|
||||
ReDirReg.Destination = ApicRead(APIC_ID);
|
||||
IOApicWrite(IOAPIC_REDTBL + 2 * APIC_CLOCK_INDEX, ReDirReg.Long0);
|
||||
|
||||
}
|
||||
@@ -519,6 +527,7 @@ HalEnableSystemInterrupt(
|
||||
IN KINTERRUPT_MODE InterruptMode)
|
||||
{
|
||||
IOAPIC_REDIRECTION_REGISTER ReDirReg;
|
||||
PKPRCB Prcb = KeGetCurrentPrcb();
|
||||
UCHAR Index;
|
||||
ASSERT(Irql <= HIGH_LEVEL);
|
||||
ASSERT((IrqlToTpr(Irql) & 0xF0) == (Vector & 0xF0));
|
||||
@@ -531,6 +540,7 @@ HalEnableSystemInterrupt(
|
||||
ReDirReg.Vector = Vector;
|
||||
ReDirReg.DeliveryMode = APIC_MT_LowestPriority;
|
||||
ReDirReg.DestinationMode = APIC_DM_Logical;
|
||||
ReDirReg.Destination |= ApicLogicalId(Prcb->Number);
|
||||
ReDirReg.TriggerMode = 1 - InterruptMode;
|
||||
ReDirReg.Mask = FALSE;
|
||||
|
||||
@@ -562,6 +572,14 @@ HalDisableSystemInterrupt(
|
||||
IOApicWrite(IOAPIC_REDTBL + 2 * Irql, ReDirReg.Long0);
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
HalpSendEOI(VOID)
|
||||
{
|
||||
/* Write 0 to the EndOfInterruptRegister */
|
||||
ApicWrite(APIC_EOI, 0);
|
||||
}
|
||||
|
||||
#ifndef _M_AMD64
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
@@ -592,7 +610,7 @@ HalEndSystemInterrupt(
|
||||
/* Restore the old IRQL */
|
||||
ApicSetCurrentIrql(OldIrql);
|
||||
|
||||
/* Write 0 to the EndOfInterruptRegister for level triggered ints */
|
||||
/* Write 0 to the EndOfInterruptRegister */
|
||||
ApicWrite(APIC_EOI, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#define IOAPIC_PHYS_BASE 0xFEC00000
|
||||
#define APIC_CLOCK_INDEX 8
|
||||
|
||||
#define ApicLogicalId(Cpu) ((UCHAR)(1<< Cpu))
|
||||
|
||||
/* APIC Register Address Map */
|
||||
#define APIC_ID 0x0020 /* Local APIC ID Register (R/W) */
|
||||
@@ -106,6 +107,12 @@ enum
|
||||
APIC_DSH_AllExclusingSelf
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
APIC_DF_Flat = 0xFFFFFFFF,
|
||||
APIC_DF_Cluster = 0x0FFFFFFF
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
TIMER_DV_DivideBy2 = 0,
|
||||
@@ -224,7 +231,7 @@ enum
|
||||
IOAPIC_ID = 0x00,
|
||||
IOAPIC_VER = 0x01,
|
||||
IOAPIC_ARB = 0x02,
|
||||
IOAPIC_REDTBL = 0x28
|
||||
IOAPIC_REDTBL = 0x10
|
||||
};
|
||||
|
||||
typedef union _IOAPIC_REDIRECTION_REGISTER
|
||||
|
||||
@@ -83,7 +83,9 @@ HalpInitializeClock(VOID)
|
||||
/* Release CMOS lock */
|
||||
HalpReleaseCmosSpinLock();
|
||||
|
||||
// RtcSetClockRate(HalpCurrentRate);
|
||||
RtcSetClockRate(HalpCurrentRate);
|
||||
|
||||
DPRINT1("Clock initialized\n");
|
||||
}
|
||||
|
||||
VOID
|
||||
@@ -95,7 +97,6 @@ HalpClockInterruptHandler(IN PKTRAP_FRAME TrapFrame)
|
||||
|
||||
/* Enter trap */
|
||||
KiEnterInterruptTrap(TrapFrame);
|
||||
__debugbreak();
|
||||
|
||||
/* Start the interrupt */
|
||||
if (HalBeginSystemInterrupt(CLOCK_LEVEL, PRIMARY_VECTOR_BASE, &Irql))
|
||||
|
||||
@@ -18,7 +18,7 @@ LARGE_INTEGER HalpCpuClockFrequency = {INITIAL_STALL_COUNT * 1000000};
|
||||
|
||||
UCHAR TscCalibrationPhase;
|
||||
LARGE_INTEGER TscCalibrationArray[NUM_SAMPLES];
|
||||
extern const UCHAR HalpClockVector;
|
||||
UCHAR HalpRtcClockVector = 0xD1;
|
||||
|
||||
/* PRIVATE FUNCTIONS *********************************************************/
|
||||
|
||||
@@ -29,6 +29,7 @@ HalpInitializeTsc()
|
||||
ULONG_PTR Flags;
|
||||
KIDTENTRY OldIdtEntry, *IdtPointer;
|
||||
PKPCR Pcr = KeGetPcr();
|
||||
UCHAR RegisterA, RegisterB;
|
||||
|
||||
/* Check if the CPU supports RDTSC */
|
||||
if (!(KeGetCurrentPrcb()->FeatureBits & KF_RDTSC))
|
||||
@@ -40,31 +41,41 @@ HalpInitializeTsc()
|
||||
Flags = __readeflags();
|
||||
_disable();
|
||||
|
||||
__debugbreak();
|
||||
/* Enable the periodic interrupt in the CMOS */
|
||||
RegisterB = HalpReadCmos(RTC_REGISTER_B);
|
||||
HalpWriteCmos(RTC_REGISTER_B, RegisterB | RTC_REG_B_PI);
|
||||
|
||||
/* Initialze the PIT */
|
||||
//HalpInitializePIT();
|
||||
/* Modify register A to get 4096 Hz */
|
||||
RegisterA = HalpReadCmos(RTC_REGISTER_A);
|
||||
RegisterA = (RegisterA & 0xF0) | 9;
|
||||
HalpWriteCmos(RTC_REGISTER_A, RegisterA);
|
||||
|
||||
/* Save old IDT entry */
|
||||
IdtPointer = KiGetIdtEntry(Pcr, HalpClockVector);
|
||||
IdtPointer = KiGetIdtEntry(Pcr, HalpRtcClockVector);
|
||||
OldIdtEntry = *IdtPointer;
|
||||
|
||||
/* Set the calibration ISR */
|
||||
KeRegisterInterruptHandler(HalpClockVector, TscCalibrationISR);
|
||||
KeRegisterInterruptHandler(HalpRtcClockVector, TscCalibrationISR);
|
||||
|
||||
/* Reset TSC value to 0 */
|
||||
__writemsr(MSR_RDTSC, 0);
|
||||
|
||||
/* Enable the timer interupt */
|
||||
HalEnableSystemInterrupt(HalpClockVector, CLOCK_LEVEL, Latched);
|
||||
HalEnableSystemInterrupt(HalpRtcClockVector, CLOCK_LEVEL, Latched);
|
||||
|
||||
/* Read register C, so that the next interrupt can happen */
|
||||
HalpReadCmos(RTC_REGISTER_C);;
|
||||
|
||||
/* Wait for completion */
|
||||
_enable();
|
||||
while (TscCalibrationPhase < NUM_SAMPLES) _ReadWriteBarrier();
|
||||
_disable();
|
||||
|
||||
/* Disable the periodic interrupt in the CMOS */
|
||||
HalpWriteCmos(RTC_REGISTER_B, RegisterB & ~RTC_REG_B_PI);
|
||||
|
||||
/* Disable the timer interupt */
|
||||
HalDisableSystemInterrupt(HalpClockVector, CLOCK_LEVEL);
|
||||
HalDisableSystemInterrupt(HalpRtcClockVector, CLOCK_LEVEL);
|
||||
|
||||
/* Restore old IDT entry */
|
||||
*IdtPointer = OldIdtEntry;
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
EXTERN _TscCalibrationPhase:BYTE
|
||||
EXTERN _TscCalibrationArray:QWORD
|
||||
EXTERN _HalpSendEOI@0:PROC
|
||||
|
||||
PUBLIC _TscCalibrationISR
|
||||
_TscCalibrationISR:
|
||||
@@ -26,13 +27,25 @@ _TscCalibrationISR:
|
||||
jnb _CalibrationISR_Exit
|
||||
|
||||
/* Store the current value */
|
||||
mov dword ptr _TscCalibrationArray[ecx * 2], eax
|
||||
mov dword ptr _TscCalibrationArray[ecx * 2 + 4], edx
|
||||
shl ecx, 3
|
||||
mov dword ptr _TscCalibrationArray[ecx], eax
|
||||
mov dword ptr _TscCalibrationArray[ecx + 4], edx
|
||||
|
||||
/* Advance phase */
|
||||
inc byte ptr ds:[_TscCalibrationPhase]
|
||||
|
||||
_CalibrationISR_Exit:
|
||||
|
||||
/* Read CMOS register C */
|
||||
mov al, HEX(0C)
|
||||
out HEX(70), al
|
||||
jmp $+2
|
||||
in al, HEX(71)
|
||||
jmp $+2
|
||||
|
||||
/* Send EOI */
|
||||
call _HalpSendEOI@0
|
||||
|
||||
pop edx
|
||||
pop ecx
|
||||
pop eax
|
||||
|
||||
Reference in New Issue
Block a user