Author: tkreuzer Date: Thu Sep 8 08:15:39 2011 New Revision: 53634
URL: http://svn.reactos.org/svn/reactos?rev=53634&view=rev Log: [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
Modified: trunk/reactos/hal/halx86/apic/apic.c trunk/reactos/hal/halx86/apic/apic.h trunk/reactos/hal/halx86/apic/rtctimer.c trunk/reactos/hal/halx86/apic/tsc.c trunk/reactos/hal/halx86/apic/tsccal.S
Modified: trunk/reactos/hal/halx86/apic/apic.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/apic/apic.c?rev=... ============================================================================== --- trunk/reactos/hal/halx86/apic/apic.c [iso-8859-1] (original) +++ trunk/reactos/hal/halx86/apic/apic.c [iso-8859-1] Thu Sep 8 08:15:39 2011 @@ -88,7 +88,7 @@ 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 @@ 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; }
@@ -240,6 +240,12 @@ SpIntRegister.SoftwareEnable = 1; 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 @@
/* 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 @@ 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 @@ 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;
@@ -560,6 +570,14 @@
/* Write back lower dword */ IOApicWrite(IOAPIC_REDTBL + 2 * Irql, ReDirReg.Long0); +} + +VOID +NTAPI +HalpSendEOI(VOID) +{ + /* Write 0 to the EndOfInterruptRegister */ + ApicWrite(APIC_EOI, 0); }
#ifndef _M_AMD64 @@ -592,7 +610,7 @@ /* Restore the old IRQL */ ApicSetCurrentIrql(OldIrql);
- /* Write 0 to the EndOfInterruptRegister for level triggered ints */ + /* Write 0 to the EndOfInterruptRegister */ ApicWrite(APIC_EOI, 0); }
Modified: trunk/reactos/hal/halx86/apic/apic.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/apic/apic.h?rev=... ============================================================================== --- trunk/reactos/hal/halx86/apic/apic.h [iso-8859-1] (original) +++ trunk/reactos/hal/halx86/apic/apic.h [iso-8859-1] Thu Sep 8 08:15:39 2011 @@ -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) */ @@ -108,6 +109,12 @@
enum { + APIC_DF_Flat = 0xFFFFFFFF, + APIC_DF_Cluster = 0x0FFFFFFF +}; + +enum +{ TIMER_DV_DivideBy2 = 0, TIMER_DV_DivideBy4 = 1, TIMER_DV_DivideBy8 = 2, @@ -224,7 +231,7 @@ IOAPIC_ID = 0x00, IOAPIC_VER = 0x01, IOAPIC_ARB = 0x02, - IOAPIC_REDTBL = 0x28 + IOAPIC_REDTBL = 0x10 };
typedef union _IOAPIC_REDIRECTION_REGISTER
Modified: trunk/reactos/hal/halx86/apic/rtctimer.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/apic/rtctimer.c?... ============================================================================== --- trunk/reactos/hal/halx86/apic/rtctimer.c [iso-8859-1] (original) +++ trunk/reactos/hal/halx86/apic/rtctimer.c [iso-8859-1] Thu Sep 8 08:15:39 2011 @@ -83,7 +83,9 @@ /* Release CMOS lock */ HalpReleaseCmosSpinLock();
- // RtcSetClockRate(HalpCurrentRate); + RtcSetClockRate(HalpCurrentRate); + + DPRINT1("Clock initialized\n"); }
VOID @@ -95,7 +97,6 @@
/* Enter trap */ KiEnterInterruptTrap(TrapFrame); -__debugbreak();
/* Start the interrupt */ if (HalBeginSystemInterrupt(CLOCK_LEVEL, PRIMARY_VECTOR_BASE, &Irql))
Modified: trunk/reactos/hal/halx86/apic/tsc.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/apic/tsc.c?rev=5... ============================================================================== --- trunk/reactos/hal/halx86/apic/tsc.c [iso-8859-1] (original) +++ trunk/reactos/hal/halx86/apic/tsc.c [iso-8859-1] Thu Sep 8 08:15:39 2011 @@ -18,7 +18,7 @@
UCHAR TscCalibrationPhase; LARGE_INTEGER TscCalibrationArray[NUM_SAMPLES]; -extern const UCHAR HalpClockVector; +UCHAR HalpRtcClockVector = 0xD1;
/* PRIVATE FUNCTIONS *********************************************************/
@@ -29,6 +29,7 @@ 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 @@ 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;
Modified: trunk/reactos/hal/halx86/apic/tsccal.S URL: http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/apic/tsccal.S?re... ============================================================================== --- trunk/reactos/hal/halx86/apic/tsccal.S [iso-8859-1] (original) +++ trunk/reactos/hal/halx86/apic/tsccal.S [iso-8859-1] Thu Sep 8 08:15:39 2011 @@ -8,6 +8,7 @@
EXTERN _TscCalibrationPhase:BYTE EXTERN _TscCalibrationArray:QWORD +EXTERN _HalpSendEOI@0:PROC
PUBLIC _TscCalibrationISR _TscCalibrationISR: @@ -26,13 +27,25 @@ 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