From c508185cd9c5064a6d29b6180bb240069c7f84a4 Mon Sep 17 00:00:00 2001 From: Timo Kreuzer Date: Thu, 8 Sep 2011 08:15:39 +0000 Subject: [PATCH] [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 --- reactos/hal/halx86/apic/apic.c | 26 ++++++++++++++++++++++---- reactos/hal/halx86/apic/apic.h | 9 ++++++++- reactos/hal/halx86/apic/rtctimer.c | 5 +++-- reactos/hal/halx86/apic/tsc.c | 27 +++++++++++++++++++-------- reactos/hal/halx86/apic/tsccal.S | 17 +++++++++++++++-- 5 files changed, 67 insertions(+), 17 deletions(-) diff --git a/reactos/hal/halx86/apic/apic.c b/reactos/hal/halx86/apic/apic.c index 74fc9f8c82e..d613c5f94d4 100644 --- a/reactos/hal/halx86/apic/apic.c +++ b/reactos/hal/halx86/apic/apic.c @@ -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); } diff --git a/reactos/hal/halx86/apic/apic.h b/reactos/hal/halx86/apic/apic.h index 7ac5aeda43d..c6a43e0c38e 100644 --- a/reactos/hal/halx86/apic/apic.h +++ b/reactos/hal/halx86/apic/apic.h @@ -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 diff --git a/reactos/hal/halx86/apic/rtctimer.c b/reactos/hal/halx86/apic/rtctimer.c index 7ae5de26e7f..dc487bd239a 100644 --- a/reactos/hal/halx86/apic/rtctimer.c +++ b/reactos/hal/halx86/apic/rtctimer.c @@ -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)) diff --git a/reactos/hal/halx86/apic/tsc.c b/reactos/hal/halx86/apic/tsc.c index 14d5c1fba7f..a551b9c3e4a 100644 --- a/reactos/hal/halx86/apic/tsc.c +++ b/reactos/hal/halx86/apic/tsc.c @@ -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; diff --git a/reactos/hal/halx86/apic/tsccal.S b/reactos/hal/halx86/apic/tsccal.S index 08cdeb52134..8b3f49ba2ad 100644 --- a/reactos/hal/halx86/apic/tsccal.S +++ b/reactos/hal/halx86/apic/tsccal.S @@ -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