[ros-diffs] [tkreuzer] 53611: [HAL] Start implementing APIC support, which is needed for both SMP and x64. It will use the local APIC + I/O APIC for interrupt control, the RTC instead of the PIT for the timer ...

tkreuzer at svn.reactos.org tkreuzer at svn.reactos.org
Tue Sep 6 21:01:51 UTC 2011


Author: tkreuzer
Date: Tue Sep  6 21:01:49 2011
New Revision: 53611

URL: http://svn.reactos.org/svn/reactos?rev=53611&view=rev
Log:
[HAL]
Start implementing APIC support, which is needed for both SMP and x64. It will use the local APIC + I/O APIC for interrupt control, the RTC instead of the PIT for the timer interrupt (PIT doesn't always work with I/O APIC), the APIC timer for profiling and finally the TSC for the performance counter and KeStallExecutionProcessor.
The code is incomplete and doesn't work yet

Added:
    trunk/reactos/hal/halx86/apic/   (with props)
    trunk/reactos/hal/halx86/apic/apic.c   (with props)
    trunk/reactos/hal/halx86/apic/apic.h   (with props)
    trunk/reactos/hal/halx86/apic/apictimer.c   (with props)
    trunk/reactos/hal/halx86/apic/apictrap.S   (with props)
    trunk/reactos/hal/halx86/apic/rtctimer.c   (with props)
    trunk/reactos/hal/halx86/apic/tsc.c   (with props)
    trunk/reactos/hal/halx86/apic/tsc.h   (with props)
    trunk/reactos/hal/halx86/apic/tsccal.S   (with props)

Propchange: trunk/reactos/hal/halx86/apic/
------------------------------------------------------------------------------
--- bugtraq:logregex (added)
+++ bugtraq:logregex Tue Sep  6 21:01:49 2011
@@ -1,0 +1,2 @@
+([Ii]ssue|[Bb]ug)s? #?(\d+)(,? ?#?(\d+))*(,? ?(and |or )?#?(\d+))?
+(\d+)

Propchange: trunk/reactos/hal/halx86/apic/
------------------------------------------------------------------------------
    bugtraq:message = See issue #%BUGID% for more details.

Propchange: trunk/reactos/hal/halx86/apic/
------------------------------------------------------------------------------
    bugtraq:url = http://www.reactos.org/bugzilla/show_bug.cgi?id=%BUGID%

Propchange: trunk/reactos/hal/halx86/apic/
------------------------------------------------------------------------------
    tsvn:logminsize = 10

Added: trunk/reactos/hal/halx86/apic/apic.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/apic/apic.c?rev=53611&view=auto
==============================================================================
--- trunk/reactos/hal/halx86/apic/apic.c (added)
+++ trunk/reactos/hal/halx86/apic/apic.c [iso-8859-1] Tue Sep  6 21:01:49 2011
@@ -1,0 +1,693 @@
+/*
+ * PROJECT:         ReactOS HAL
+ * LICENSE:         GNU GPL - See COPYING in the top level directory
+ * FILE:            hal/halx86/generic/apic.c
+ * PURPOSE:         HAL APIC Management and Control Code
+ * PROGRAMMERS:     Timo Kreuzer (timo.kreuzer at reactos.org)
+ * REFERENCES:      http://www.joseflores.com/docs/ExploringIrql.html
+ *                  http://www.codeproject.com/KB/system/soviet_kernel_hack.aspx
+ *                  http://bbs.unixmap.net/thread-2022-1-1.html
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <hal.h>
+#define NDEBUG
+#include <debug.h>
+
+#include "apic.h"
+
+/* GLOBALS ********************************************************************/
+
+UCHAR HalpVectorToIndex[256];
+
+#ifndef _M_AMD64
+static const UCHAR
+HalpIRQLtoTPR[32] =
+{
+    0x00, /*  0 PASSIVE_LEVEL */
+    0x3d, /*  1 APC_LEVEL */
+    0x41, /*  2 DISPATCH_LEVEL */
+    0x41, /*  3 \  */
+    0x51, /*  4  \ */
+    0x61, /*  5  | */
+    0x71, /*  6  | */
+    0x81, /*  7  | */
+    0x91, /*  8  | */
+    0xa1, /*  9  | */
+    0xb1, /* 10  | */
+    0xb1, /* 11  | */
+    0xb1, /* 12  | */
+    0xb1, /* 13  | */
+    0xb1, /* 14  | */
+    0xb1, /* 15 DEVICE IRQL */
+    0xb1, /* 16  | */
+    0xb1, /* 17  | */
+    0xb1, /* 18  | */
+    0xb1, /* 19  | */
+    0xb1, /* 20  | */
+    0xb1, /* 21  | */
+    0xb1, /* 22  | */
+    0xb1, /* 23  | */
+    0xb1, /* 24  | */
+    0xb1, /* 25  / */
+    0xb1, /* 26 /  */
+    0xc1, /* 27 PROFILE_LEVEL */
+    0xd1, /* 28 CLOCK2_LEVEL */
+    0xe1, /* 29 IPI_LEVEL */
+    0xef, /* 30 POWER_LEVEL */
+    0xff, /* 31 HIGH_LEVEL */
+};
+
+static const KIRQL
+HalVectorToIRQL[16] =
+{
+       0, /* 00 PASSIVE_LEVEL */
+    0xff, /* 10 */
+    0xff, /* 20 */
+       1, /* 3D APC_LEVEL */
+       2, /* 41 DISPATCH_LEVEL */
+       4, /* 50 \ */
+       5, /* 60  \ */
+       6, /* 70  | */
+       7, /* 80 DEVICE IRQL */
+       8, /* 90  | */
+       9, /* A0  / */
+      10, /* B0 /  */
+      27, /* C1 PROFILE_LEVEL */
+      28, /* D1 CLOCK2_LEVEL */
+      29, /* E1 IPI_LEVEL / EF POWER_LEVEL */
+      31, /* FF HIGH_LEVEL */
+};
+#endif
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+ULONG
+FORCEINLINE
+IOApicRead(UCHAR Register)
+{
+    /* Select the register, then do the read */
+    *(volatile ULONG *)(IOAPIC_BASE + IOAPIC_IOREGSEL) = Register;
+    return *(volatile ULONG *)(IOAPIC_BASE + IOAPIC_IOWIN);
+}
+
+VOID
+FORCEINLINE
+IOApicWrite(UCHAR Register, ULONG Value)
+{
+    /* Select the register, then do the write */
+    *(volatile ULONG *)(IOAPIC_BASE + IOAPIC_IOREGSEL) = Register;
+    *(volatile ULONG *)(IOAPIC_BASE + IOAPIC_IOWIN) = Value;
+}
+
+KIRQL
+FORCEINLINE
+ApicGetProcessorIrql(VOID)
+{
+    /* Read the TPR and convert it to an IRQL */
+    return TprToIrql(ApicRead(APIC_PPR));
+}
+
+KIRQL
+FORCEINLINE
+ApicGetCurrentIrql(VOID)
+{
+    /* Read the TPR and convert it to an IRQL */
+    return TprToIrql(ApicRead(APIC_TPR));
+}
+
+VOID
+FORCEINLINE
+ApicSetCurrentIrql(KIRQL Irql)
+{
+    /* Convert IRQL and write the TPR */
+    ApicWrite(APIC_TPR, IrqlToTpr(Irql));
+}
+
+UCHAR
+FASTCALL
+HalpIrqToVector(UCHAR Irq)
+{
+    IOAPIC_REDIRECTION_REGISTER ReDirReg;
+
+    /* Read low dword of the redirection entry */
+    ReDirReg.Long0 = IOApicRead(IOAPIC_REDTBL + 2 * Irq);
+
+    /* Return the vector */
+    return (UCHAR)ReDirReg.Vector;
+}
+
+KIRQL
+FASTCALL
+HalpVectorToIrql(UCHAR Vector)
+{
+    return TprToIrql(Vector >> 2);
+}
+
+UCHAR
+FASTCALL
+HalpVectorToIrq(UCHAR Vector)
+{
+    return HalpVectorToIndex[Vector];
+}
+
+VOID
+NTAPI
+HalpInitializeLegacyPIC(VOID)
+{
+    I8259_ICW1 Icw1;
+    I8259_ICW2 Icw2;
+    I8259_ICW3 Icw3;
+    I8259_ICW4 Icw4;
+
+    /* Initialize ICW1 for master, interval 8, edge-triggered mode with ICW4 */
+    Icw1.NeedIcw4 = TRUE;
+    Icw1.OperatingMode = Cascade;
+    Icw1.Interval = Interval8;
+    Icw1.InterruptMode = EdgeTriggered;
+    Icw1.Init = TRUE;
+    Icw1.InterruptVectorAddress = 0;
+    __outbyte(PIC1_CONTROL_PORT, Icw1.Bits);
+
+    /* ICW2 - interrupt vector offset */
+    Icw2.Bits = PRIMARY_VECTOR_BASE;
+    __outbyte(PIC1_DATA_PORT, Icw2.Bits);
+
+    /* Connect slave to IRQ 2 */
+    Icw3.Bits = 0;
+    Icw3.SlaveIrq2 = TRUE;
+    __outbyte(PIC1_DATA_PORT, Icw3.Bits);
+
+    /* Enable 8086 mode, non-automatic EOI, non-buffered mode, non special fully nested mode */
+    Icw4.SystemMode = New8086Mode;
+    Icw4.EoiMode = NormalEoi;
+    Icw4.BufferedMode = NonBuffered;
+    Icw4.SpecialFullyNestedMode = FALSE;
+    Icw4.Reserved = 0;
+    __outbyte(PIC1_DATA_PORT, Icw4.Bits);
+
+    /* Mask all interrupts */
+    __outbyte(PIC1_DATA_PORT, 0xFF);
+
+    /* Initialize ICW1 for slave, interval 8, edge-triggered mode with ICW4 */
+    Icw1.NeedIcw4 = TRUE;
+    Icw1.InterruptMode = EdgeTriggered;
+    Icw1.OperatingMode = Cascade;
+    Icw1.Interval = Interval8;
+    Icw1.Init = TRUE;
+    Icw1.InterruptVectorAddress = 0; /* This is only used in MCS80/85 mode */
+    __outbyte(PIC2_CONTROL_PORT, Icw1.Bits);
+
+    /* Set interrupt vector base */
+    Icw2.Bits = PRIMARY_VECTOR_BASE + 8;
+    __outbyte(PIC2_DATA_PORT, Icw2.Bits);
+
+    /* Slave ID */
+    Icw3.Bits = 0;
+    Icw3.SlaveId = 2;
+    __outbyte(PIC2_DATA_PORT, Icw3.Bits);
+
+    /* Enable 8086 mode, non-automatic EOI, non-buffered mode, non special fully nested mode */
+    Icw4.SystemMode = New8086Mode;
+    Icw4.EoiMode = NormalEoi;
+    Icw4.BufferedMode = NonBuffered;
+    Icw4.SpecialFullyNestedMode = FALSE;
+    Icw4.Reserved = 0;
+    __outbyte(PIC2_DATA_PORT, Icw4.Bits);
+
+    /* Mask all interrupts */
+    __outbyte(PIC2_DATA_PORT, 0xFF);
+}
+
+
+VOID
+ApicInitializeLocalApic(ULONG Cpu)
+{
+    APIC_BASE_ADRESS_REGISTER BaseRegister;
+    APIC_SPURIOUS_INERRUPT_REGISTER SpIntRegister;
+    LVT_REGISTER LvtEntry;
+
+    /* Enable the APIC if it wasn't yet */
+    BaseRegister.Long = __readmsr(MSR_APIC_BASE);
+    BaseRegister.Enable = 1;
+    BaseRegister.BootStrapCPUCore = (Cpu == 0);
+    __writemsr(MSR_APIC_BASE, BaseRegister.Long);
+
+    DPRINT1("ApicBase for Cpu %u PhysicalAddress = %p\n", Cpu, BaseRegister.BaseAddress);
+    DPRINT1("ApicVersion = 0x%lx\n", ApicRead(0x30));
+
+    /* Set spurious vector and SoftwareEnable to 1 */
+    SpIntRegister.Long = ApicRead(APIC_SIVR);
+    SpIntRegister.Vector = APIC_SPURIOUS_VECTOR;
+    SpIntRegister.SoftwareEnable = 1;
+    SpIntRegister.FocusCPUCoreChecking = 0;
+    ApicWrite(APIC_SIVR, SpIntRegister.Long);
+
+    /* Set the spurious ISR */
+    KeRegisterInterruptHandler(APIC_SPURIOUS_VECTOR, ApicSpuriousService);
+
+    /* Create a template LVT */
+    LvtEntry.Long = 0;
+    LvtEntry.Vector = 0xFF;
+    LvtEntry.MessageType = APIC_MT_Fixed;
+    LvtEntry.DeliveryStatus = 0;
+    LvtEntry.RemoteIRR = 0;
+    LvtEntry.TriggerMode = APIC_TGM_Edge;
+    LvtEntry.Mask = 1;
+    LvtEntry.TimerMode = 0;
+
+    /* Initalize and mask LVTs */
+    ApicWrite(APIC_TMRLVTR, LvtEntry.Long);
+    ApicWrite(APIC_THRMLVTR, LvtEntry.Long);
+    ApicWrite(APIC_PCLVTR, LvtEntry.Long);
+    ApicWrite(APIC_EXT0LVTR, LvtEntry.Long);
+    ApicWrite(APIC_EXT1LVTR, LvtEntry.Long);
+    ApicWrite(APIC_EXT2LVTR, LvtEntry.Long);
+    ApicWrite(APIC_EXT3LVTR, LvtEntry.Long);
+
+    /* LINT0 */
+    LvtEntry.Vector = APIC_SPURIOUS_VECTOR;
+    LvtEntry.MessageType = APIC_MT_ExtInt;
+    ApicWrite(APIC_LINT0, LvtEntry.Long);
+
+    /* Enable LINT1 (NMI) */
+    LvtEntry.Mask = 0;
+    LvtEntry.Vector = APIC_NMI_VECTOR;
+    LvtEntry.MessageType = APIC_MT_NMI;
+    LvtEntry.TriggerMode = APIC_TGM_Level;
+    ApicWrite(APIC_LINT1, LvtEntry.Long);
+
+    /* Enable error LVTR */
+    LvtEntry.Vector = APIC_ERROR_VECTOR;
+    LvtEntry.MessageType = APIC_MT_Fixed;
+    ApicWrite(APIC_ERRLVTR, LvtEntry.Long);
+
+    DPRINT1("Error code = 0x%lx\n", ApicRead(0x280));
+}
+
+VOID
+NTAPI
+ApicInitializeProcessor(
+    IN ULONG ProcessorNumber,
+    IN PLOADER_PARAMETER_BLOCK LoaderBlock)
+{
+    DPRINT1("ApicInitializeProcessor(%ld)\n", ProcessorNumber);
+
+    /* Initialize the local APIC for this cpu */
+    ApicInitializeLocalApic(ProcessorNumber);
+
+    /* Initialize the timer */
+    ApicInitializeTimer(ProcessorNumber);
+
+}
+
+VOID
+FORCEINLINE
+ApicWriteIORedirectionEntry(
+    UCHAR Index,
+    IOAPIC_REDIRECTION_REGISTER ReDirReg)
+{
+    IOApicWrite(IOAPIC_REDTBL + 2 * Index, ReDirReg.Long0);
+    IOApicWrite(IOAPIC_REDTBL + 2 * Index + 1, ReDirReg.Long1);
+}
+
+IOAPIC_REDIRECTION_REGISTER
+FORCEINLINE
+ApicReadIORedirectionEntry(
+    UCHAR Index)
+{
+    IOAPIC_REDIRECTION_REGISTER ReDirReg;
+
+    ReDirReg.Long0 = IOApicRead(IOAPIC_REDTBL + 2 * Index);
+    ReDirReg.Long1 = IOApicRead(IOAPIC_REDTBL + 2 * Index + 1);
+
+    return ReDirReg;
+}
+
+UCHAR
+NTAPI
+HalpAllocateSystemInterrupt(
+    IN UCHAR Irq,
+    IN KIRQL Irql)
+{
+    IOAPIC_REDIRECTION_REGISTER ReDirReg;
+    IN UCHAR Vector;
+
+    /* Start with low vector */
+    Vector = IrqlToTpr(Irql);
+
+    /* Find an empty vector */
+    while (HalpVectorToIndex[Vector] != 0xFF)
+    {
+        Vector++;
+
+        /* Check if we went over the edge */
+        if (TprToIrql(Vector) > Irql)
+        {
+            /* Nothing free, return failure */
+            return 0;
+        }
+    }
+
+    /* Save irq in the table */
+    HalpVectorToIndex[Vector] = Irq;
+
+    /* Setup a redirection entry */
+    ReDirReg.Vector = Vector;
+    ReDirReg.DeliveryMode = APIC_MT_LowestPriority;
+    ReDirReg.DestinationMode = APIC_DM_Logical;
+    ReDirReg.DeliveryStatus = 0;
+    ReDirReg.Polarity = 0;
+    ReDirReg.RemoteIRR = 0;
+    ReDirReg.TriggerMode = APIC_TGM_Edge;
+    ReDirReg.Mask = 1;
+    ReDirReg.Reserved = 0;
+    ReDirReg.Destination = 0;
+
+    /* Initialize entry */
+    IOApicWrite(IOAPIC_REDTBL + 2 * Irq, ReDirReg.Long0);
+    IOApicWrite(IOAPIC_REDTBL + 2 * Irq + 1, ReDirReg.Long1);
+
+    return Vector;
+}
+
+VOID
+NTAPI
+ApicInitializeIOApic(VOID)
+{
+    PHARDWARE_PTE Pte;
+    IOAPIC_REDIRECTION_REGISTER ReDirReg;
+    UCHAR Index;
+    ULONG Vector;
+
+    /* Map the I/O Apic page */
+    Pte = HalAddressToPte(IOAPIC_BASE);
+    Pte->PageFrameNumber = IOAPIC_PHYS_BASE / PAGE_SIZE;
+    Pte->Valid = 1;
+    Pte->Write = 1;
+    Pte->Owner = 1;
+    Pte->CacheDisable = 1;
+    Pte->Global = 1;
+    _ReadWriteBarrier();
+
+    /* Setup a redirection entry */
+    ReDirReg.Vector = 0xFF;
+    ReDirReg.DeliveryMode = APIC_MT_Fixed;
+    ReDirReg.DestinationMode = APIC_DM_Physical;
+    ReDirReg.DeliveryStatus = 0;
+    ReDirReg.Polarity = 0;
+    ReDirReg.RemoteIRR = 0;
+    ReDirReg.TriggerMode = APIC_TGM_Edge;
+    ReDirReg.Mask = 1;
+    ReDirReg.Reserved = 0;
+    ReDirReg.Destination = 0;
+
+    /* Loop all table entries */
+    for (Index = 0; Index < 24; Index++)
+    {
+        /* Initialize entry */
+        IOApicWrite(IOAPIC_REDTBL + 2 * Index, ReDirReg.Long0);
+        IOApicWrite(IOAPIC_REDTBL + 2 * Index + 1, ReDirReg.Long1);
+    }
+
+    /* Init the vactor to index table */
+    for (Vector = 0; Vector <= 255; Vector++)
+    {
+        HalpVectorToIndex[Vector] = 0xFF;
+    }
+
+    // HACK: Allocate all IRQs, should rather do that on demand
+    for (Index = 0; Index <= 15; Index++)
+    {
+        /* Map the IRQs to IRQLs like with the PIC */
+        HalpAllocateSystemInterrupt(Index, 27 - Index);
+    }
+
+    /* Enable the timer interrupt */
+    ReDirReg.Vector = APIC_CLOCK_VECTOR;
+    ReDirReg.DestinationMode = APIC_DM_Logical;
+    ReDirReg.TriggerMode = APIC_TGM_Edge;
+    ReDirReg.Mask = 0;
+    IOApicWrite(IOAPIC_REDTBL + 2 * APIC_CLOCK_INDEX, ReDirReg.Long0);
+
+}
+
+VOID
+NTAPI
+HalpInitializePICs(IN BOOLEAN EnableInterrupts)
+{
+    ULONG_PTR EFlags;
+
+    /* Save EFlags and disable interrupts */
+    EFlags = __readeflags();
+    _disable();
+
+    /* Initialize the local APIC for this cpu */
+    ApicInitializeLocalApic(0);
+
+    /* Initialize and mask the PIC */
+    HalpInitializeLegacyPIC();
+
+    /* Initialize the I/O APIC */
+    ApicInitializeIOApic();
+    ApicWrite(APIC_EOI, 0);
+
+    /* Register interrupt handlers */
+    KeRegisterInterruptHandler(APIC_CLOCK_VECTOR, HalpClockInterrupt);
+    KeRegisterInterruptHandler(APC_VECTOR, HalpApcInterrupt);
+    KeRegisterInterruptHandler(DPC_VECTOR, HalpDispatchInterrupt);
+
+    // HACK, since we messed with the value, should init the local apic in
+    // HalInitializeProcessor instead
+    ApicSetCurrentIrql(APC_LEVEL);
+    ASSERT(ApicGetProcessorIrql() <= APC_LEVEL);
+
+__debugbreak();
+
+HalpInitializeClock();
+//HalpCalibrateStallExecution();
+_enable();
+for (;;);
+
+
+    /* Restore interrupt state */
+    if (EnableInterrupts) EFlags |= EFLAGS_INTERRUPT_MASK;
+    __writeeflags(EFlags);
+}
+
+VOID
+DECLSPEC_NORETURN
+FASTCALL
+HalpApcInterruptHandler(IN PKTRAP_FRAME TrapFrame)
+{
+    ASSERT(ApicGetCurrentIrql() < APC_LEVEL);
+    ASSERT(ApicGetProcessorIrql() == APC_LEVEL);
+
+    UNIMPLEMENTED;
+    ASSERT(FALSE);
+}
+
+VOID
+DECLSPEC_NORETURN
+FASTCALL
+HalpDispatchInterruptHandler(IN PKTRAP_FRAME TrapFrame)
+{
+    KIRQL OldIrql = ApicGetCurrentIrql();
+__debugbreak();
+    ASSERT(OldIrql < DISPATCH_LEVEL);
+    ASSERT(ApicGetProcessorIrql() == DISPATCH_LEVEL);
+
+    ApicSetCurrentIrql(DISPATCH_LEVEL);
+
+    /* Enable interrupts and call the kernel's DPC interrupt handler */
+    _enable();
+    KiDispatchInterrupt();
+    _disable();
+
+    ApicSetCurrentIrql(OldIrql);
+
+    ApicWrite(APIC_EOI, 0);
+
+    /* Exit the interrupt */
+    KiEoiHelper(TrapFrame);
+}
+
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+VOID
+FASTCALL
+HalRequestSoftwareInterrupt(IN KIRQL Irql)
+{
+    APIC_COMMAND_REGISTER CommandRegister;
+
+    /* Setup the command register */
+    CommandRegister.Long0 = 0;
+    CommandRegister.Vector = IrqlToTpr(Irql);
+    CommandRegister.MessageType = APIC_MT_Fixed;
+    CommandRegister.TriggerMode = APIC_TGM_Edge;
+    CommandRegister.DestinationShortHand = APIC_DSH_Self;
+
+    /* Write the low dword to send the interrupt */
+    ApicWrite(APIC_ICR0, CommandRegister.Long0);
+}
+
+VOID
+FASTCALL
+HalClearSoftwareInterrupt(
+    IN KIRQL Irql)
+{
+    /* Nothing to do */
+}
+
+BOOLEAN
+NTAPI
+HalEnableSystemInterrupt(
+    IN UCHAR Vector,
+    IN KIRQL Irql,
+    IN KINTERRUPT_MODE InterruptMode)
+{
+    IOAPIC_REDIRECTION_REGISTER ReDirReg;
+    UCHAR Index;
+    ASSERT(Irql <= HIGH_LEVEL);
+    ASSERT((IrqlToTpr(Irql) & 0xF0) == (Vector & 0xF0));
+
+    Index = HalpVectorToIndex[Vector];
+
+    /* Read lower dword of redirection entry */
+    ReDirReg.Long0 = IOApicRead(IOAPIC_REDTBL + 2 * Index);
+
+    ReDirReg.Vector = Vector;
+    ReDirReg.DeliveryMode = APIC_MT_LowestPriority;
+    ReDirReg.DestinationMode = APIC_DM_Logical;
+    ReDirReg.TriggerMode = 1 - InterruptMode;
+    ReDirReg.Mask = FALSE;
+
+    /* Write back lower dword */
+    IOApicWrite(IOAPIC_REDTBL + 2 * Irql, ReDirReg.Long0);
+
+    return TRUE;
+}
+
+VOID
+NTAPI
+HalDisableSystemInterrupt(
+    IN UCHAR Vector,
+    IN KIRQL Irql)
+{
+    IOAPIC_REDIRECTION_REGISTER ReDirReg;
+    UCHAR Index;
+    ASSERT(Irql <= HIGH_LEVEL);
+
+    Index = HalpVectorToIndex[Vector];
+
+    /* Read lower dword of redirection entry */
+    ReDirReg.Long0 = IOApicRead(IOAPIC_REDTBL + 2 * Index);
+
+    /* Mask it */
+    ReDirReg.Mask = 1;
+
+    /* Write back lower dword */
+    IOApicWrite(IOAPIC_REDTBL + 2 * Irql, ReDirReg.Long0);
+}
+
+BOOLEAN
+NTAPI
+HalBeginSystemInterrupt(
+    IN KIRQL Irql,
+    IN UCHAR Vector,
+    OUT PKIRQL OldIrql)
+{
+    /* Get the current IRQL */
+    *OldIrql = ApicGetCurrentIrql();
+
+    /* Set the new IRQL */
+    ApicSetCurrentIrql(Irql);
+
+    /* Turn on interrupts */
+    _enable();
+
+    /* Success */
+    return TRUE;
+}
+
+VOID
+NTAPI
+HalEndSystemInterrupt(
+    IN KIRQL OldIrql,
+    IN PKTRAP_FRAME TrapFrame)
+{
+    /* Restore the old IRQL */
+    ApicSetCurrentIrql(OldIrql);
+
+    /* Write 0 to the EndOfInterruptRegister for level triggered ints */
+    ApicWrite(APIC_EOI, 0);
+}
+
+#ifndef _M_AMD64
+
+KIRQL
+NTAPI
+KeGetCurrentIrql(VOID)
+{
+    /* Read the current TPR and convert it to an IRQL */
+    return ApicGetCurrentIrql();
+}
+
+VOID
+FASTCALL
+KfLowerIrql(
+    IN KIRQL OldIrql)
+{
+#if DBG
+    /* Validate correct lower */
+    if (OldIrql > ApicGetCurrentIrql())
+    {
+        /* Crash system */
+        KeBugCheck(IRQL_NOT_LESS_OR_EQUAL);
+    }
+#endif
+    /* Convert the new IRQL to a TPR value and write the register */
+    ApicSetCurrentIrql(OldIrql);
+}
+
+KIRQL
+FASTCALL
+KfRaiseIrql(
+    IN KIRQL NewIrql)
+{
+    KIRQL OldIrql;
+
+    /* Read the current TPR and convert it to an IRQL */
+    OldIrql = ApicGetCurrentIrql();
+#if DBG
+    /* Validate correct raise */
+    if (OldIrql > NewIrql)
+    {
+        /* Crash system */
+        KeBugCheck(IRQL_NOT_GREATER_OR_EQUAL);
+    }
+#endif
+    /* Convert the new IRQL to a TPR value and write the register */
+    ApicSetCurrentIrql(NewIrql);
+
+    return OldIrql;
+}
+
+KIRQL
+NTAPI
+KeRaiseIrqlToDpcLevel(VOID)
+{
+    return KfRaiseIrql(DISPATCH_LEVEL);
+}
+
+KIRQL
+NTAPI
+KeRaiseIrqlToSynchLevel(VOID)
+{
+    return KfRaiseIrql(SYNCH_LEVEL);
+}
+
+#endif /* !_M_AMD64 */
+

Propchange: trunk/reactos/hal/halx86/apic/apic.c
------------------------------------------------------------------------------
    svn:eol-style = native

Added: trunk/reactos/hal/halx86/apic/apic.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/apic/apic.h?rev=53611&view=auto
==============================================================================
--- trunk/reactos/hal/halx86/apic/apic.h (added)
+++ trunk/reactos/hal/halx86/apic/apic.h [iso-8859-1] Tue Sep  6 21:01:49 2011
@@ -1,0 +1,271 @@
+
+#ifdef _M_AMD64
+#define APIC_BASE 0xfffffffffee00000ULL;
+#define ZERO_VECTOR          0x00 // IRQL 00
+#define APC_VECTOR           0x3D // IRQL 01
+#define APIC_SPURIOUS_VECTOR 0x3f
+#define DPC_VECTOR           0x41 // IRQL 02
+#define APIC_GENERIC_VECTOR  0xC1 // IRQL 27
+#define APIC_CLOCK_VECTOR    0xD1 // IRQL 28
+#define APIC_SYNCH_VECTOR    0xD1 // IRQL 28
+#define APIC_IPI_VECTOR      0xE1 // IRQL 29
+#define APIC_ERROR_VECTOR    0xE3
+#define POWERFAIL_VECTOR     0xEF // IRQL 30
+#define APIC_PROFILE_VECTOR  0xFD // IRQL 31
+#define APIC_NMI_VECTOR      0xFF
+#define IrqlToTpr(Irql) (Irql << 4)
+#define TprToIrql(Tpr) (Tpr >> 4)
+#else
+#define APIC_BASE 0xFFFE0000
+#define IOAPIC_BASE 0xFFFE1000 // checkme
+#define IOAPIC_PHYS_BASE 0xFEC00000
+#define ZERO_VECTOR          0x00 // IRQL 00
+#define APIC_SPURIOUS_VECTOR 0x1f
+#define APC_VECTOR           0x3D // IRQL 01
+#define DPC_VECTOR           0x41 // IRQL 02
+#define APIC_GENERIC_VECTOR  0xC1 // IRQL 27
+#define APIC_CLOCK_VECTOR    0xD1 // IRQL 28
+#define APIC_SYNCH_VECTOR    0xD1 // IRQL 28
+#define APIC_IPI_VECTOR      0xE1 // IRQL 29
+#define APIC_ERROR_VECTOR    0xE3
+#define POWERFAIL_VECTOR     0xEF // IRQL 30
+#define APIC_PROFILE_VECTOR  0xFD // IRQL 31
+#define APIC_NMI_VECTOR      0xFF
+#define IrqlToTpr(Irql) (HalpIRQLtoTPR[Irql])
+#define TprToIrql(Tpr)  (HalVectorToIRQL[Tpr >> 4])
+#endif
+
+#define MSR_APIC_BASE 0x0000001B
+#define APIC_CLOCK_INDEX 8
+
+
+/* APIC Register Address Map */
+#define APIC_ID       0x0020 /* Local APIC ID Register (R/W) */
+#define APIC_VER      0x0030 /* Local APIC Version Register (R) */
+#define APIC_TPR      0x0080 /* Task Priority Register (R/W) */
+#define APIC_APR      0x0090 /* Arbitration Priority Register (R) */
+#define APIC_PPR      0x00A0 /* Processor Priority Register (R) */
+#define APIC_EOI      0x00B0 /* EOI Register (W) */
+#define APIC_RRR      0x00C0 /* Remote Read Register () */
+#define APIC_LDR      0x00D0 /* Logical Destination Register (R/W) */
+#define APIC_DFR      0x00E0 /* Destination Format Register (0-27 R, 28-31 R/W) */
+#define APIC_SIVR     0x00F0 /* Spurious Interrupt Vector Register (0-3 R, 4-9 R/W) */
+#define APIC_ISR      0x0100 /* Interrupt Service Register 0-255 (R) */
+#define APIC_TMR      0x0180 /* Trigger Mode Register 0-255 (R) */
+#define APIC_IRR      0x0200 /* Interrupt Request Register 0-255 (r) */
+#define APIC_ESR      0x0280 /* Error Status Register (R) */
+#define APIC_ICR0     0x0300 /* Interrupt Command Register 0-31 (R/W) */
+#define APIC_ICR1     0x0310 /* Interrupt Command Register 32-63 (R/W) */
+#define APIC_TMRLVTR  0x0320 /* Timer Local Vector Table (R/W) */
+#define	APIC_THRMLVTR 0x0330 /* Thermal Local Vector Table */
+#define APIC_PCLVTR   0x0340 /* Performance Counter Local Vector Table (R/W) */
+#define APIC_LINT0    0x0350 /* LINT0 Local Vector Table (R/W) */
+#define APIC_LINT1    0x0360 /* LINT1 Local Vector Table (R/W) */
+#define APIC_ERRLVTR  0x0370 /* Error Local Vector Table (R/W) */
+#define APIC_TICR     0x0380 /* Initial Count Register for Timer (R/W) */
+#define APIC_TCCR     0x0390 /* Current Count Register for Timer (R) */
+#define APIC_TDCR     0x03E0 /* Timer Divide Configuration Register (R/W) */
+#define APIC_EAFR     0x0400 /* extended APIC Feature register (R/W) */
+#define APIC_EACR     0x0410 /* Extended APIC Control Register (R/W) */
+#define APIC_SEOI     0x0420 /* Specific End Of Interrupt Register (W) */
+#define APIC_EXT0LVTR 0x0500 /* Extended Interrupt 0 Local Vector Table */
+#define APIC_EXT1LVTR 0x0510 /* Extended Interrupt 1 Local Vector Table */
+#define APIC_EXT2LVTR 0x0520 /* Extended Interrupt 2 Local Vector Table */
+#define APIC_EXT3LVTR 0x0530 /* Extended Interrupt 3 Local Vector Table */
+
+enum
+{
+    APIC_MT_Fixed = 0,
+    APIC_MT_LowestPriority = 1,
+    APIC_MT_SMI = 2,
+    APIC_MT_RemoteRead = 3,
+    APIC_MT_NMI = 4,
+    APIC_MT_INIT = 5,
+    APIC_MT_Startup = 6,
+    APIC_MT_ExtInt = 7,
+};
+
+enum
+{
+    APIC_TGM_Edge,
+    APIC_TGM_Level
+};
+
+enum
+{
+    APIC_DM_Physical,
+    APIC_DM_Logical
+};
+
+enum
+{
+    APIC_DSH_Destination,
+    APIC_DSH_Self,
+    APIC_DSH_AllIncludingSelf,
+    APIC_DSH_AllExclusingSelf
+};
+
+enum
+{
+    TIMER_DV_DivideBy2 = 0,
+    TIMER_DV_DivideBy4 = 1,
+    TIMER_DV_DivideBy8 = 2,
+    TIMER_DV_DivideBy16 = 3,
+    TIMER_DV_DivideBy32 = 8,
+    TIMER_DV_DivideBy64 = 9,
+    TIMER_DV_DivideBy128 = 10,
+    TIMER_DV_DivideBy1 = 11,
+};
+
+
+typedef union _APIC_BASE_ADRESS_REGISTER
+{
+    ULONG64 Long;
+    struct
+    {
+        ULONG64 Reserved1:8;
+        ULONG64 BootStrapCPUCore:1;
+        ULONG64 Reserved2:2;
+        ULONG64 Enable:1;
+        ULONG64 BaseAddress:40;
+        ULONG64 ReservedMBZ:12;
+    };
+} APIC_BASE_ADRESS_REGISTER;
+
+typedef union _APIC_SPURIOUS_INERRUPT_REGISTER
+{
+    ULONG Long;
+    struct
+    {
+        ULONG Vector:8;
+        ULONG SoftwareEnable:1;
+        ULONG FocusCPUCoreChecking:1;
+        ULONG ReservedMBZ:22;
+    };
+} APIC_SPURIOUS_INERRUPT_REGISTER;
+
+typedef union
+{
+    ULONG Long;
+    struct
+    {
+        ULONG Version:8;
+        ULONG ReservedMBZ:8;
+        ULONG MaxLVT:8;
+        ULONG ReservedMBZ1:7;
+        ULONG ExtRegSpacePresent:1;
+    };
+} APIC_VERSION_REGISTER;
+
+typedef union
+{
+    ULONG Long;
+    struct
+    {
+        ULONG Version:1;
+        ULONG SEOIEnable:1;
+        ULONG ExtApicIdEnable:1;
+        ULONG ReservedMBZ:29;
+    };
+} APIC_EXTENDED_CONTROL_REGISTER;
+
+typedef union _APIC_COMMAND_REGISTER
+{
+    ULONGLONG LongLong;
+    struct
+    {
+        ULONG Long0;
+        ULONG Long1;
+    };
+    struct
+    {
+        ULONGLONG Vector:8;
+        ULONGLONG MessageType:3;
+        ULONGLONG DestinationMode:1;
+        ULONGLONG DeliveryStatus:1;
+        ULONGLONG ReservedMBZ:1;
+        ULONGLONG Level:1;
+        ULONGLONG TriggerMode:1;
+        ULONGLONG RemoteReadStatus:2;
+        ULONGLONG DestinationShortHand:2;
+        ULONGLONG Reserved2MBZ:36;
+        ULONGLONG Destination:8;
+    };
+} APIC_COMMAND_REGISTER;
+
+typedef union
+{
+    ULONG Long;
+    struct
+    {
+        ULONG Vector:8;
+        ULONG MessageType:3;
+        ULONG ReservedMBZ:1;
+        ULONG DeliveryStatus:1;
+        ULONG Reserved1MBZ:1;
+        ULONG RemoteIRR:1;
+        ULONG TriggerMode:1;
+        ULONG Mask:1;
+        ULONG TimerMode:1;
+        ULONG Reserved2MBZ:13;
+    };
+} LVT_REGISTER;
+
+
+enum
+{
+    IOAPIC_IOREGSEL = 0x00,
+    IOAPIC_IOWIN    = 0x10
+};
+
+enum
+{
+    IOAPIC_ID  = 0x00,
+    IOAPIC_VER = 0x01,
+    IOAPIC_ARB = 0x02,
+    IOAPIC_REDTBL = 0x28
+};
+
+typedef union _IOAPIC_REDIRECTION_REGISTER
+{
+    ULONGLONG LongLong;
+    struct
+    {
+        ULONG Long0;
+        ULONG Long1;
+    };
+    struct
+    {
+        ULONGLONG Vector:8;
+        ULONGLONG DeliveryMode:3;
+        ULONGLONG DestinationMode:1;
+        ULONGLONG DeliveryStatus:1;
+        ULONGLONG Polarity:1;
+        ULONGLONG RemoteIRR:1;
+        ULONGLONG TriggerMode:1;
+        ULONGLONG Mask:1;
+        ULONGLONG Reserved:39;
+        ULONGLONG Destination:8;
+    };
+} IOAPIC_REDIRECTION_REGISTER;
+
+ULONG
+FORCEINLINE
+ApicRead(ULONG Offset)
+{
+    return *(volatile ULONG *)(APIC_BASE + Offset);
+}
+
+VOID
+FORCEINLINE
+ApicWrite(ULONG Offset, ULONG Value)
+{
+    *(volatile ULONG *)(APIC_BASE + Offset) = Value;
+}
+
+VOID
+NTAPI
+ApicInitializeTimer(ULONG Cpu);
+
+VOID ApicSpuriousService(VOID);
+

Propchange: trunk/reactos/hal/halx86/apic/apic.h
------------------------------------------------------------------------------
    svn:eol-style = native

Added: trunk/reactos/hal/halx86/apic/apictimer.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/apic/apictimer.c?rev=53611&view=auto
==============================================================================
--- trunk/reactos/hal/halx86/apic/apictimer.c (added)
+++ trunk/reactos/hal/halx86/apic/apictimer.c [iso-8859-1] Tue Sep  6 21:01:49 2011
@@ -1,0 +1,84 @@
+/*
+ * PROJECT:         ReactOS HAL
+ * LICENSE:         GPL - See COPYING in the top level directory
+ * FILE:            hal/halx86/apic/apictimer.c
+ * PURPOSE:         System Profiling
+ * PROGRAMMERS:     Timo Kreuzer (timo.kreuzer at reactos.org)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <hal.h>
+#define NDEBUG
+#include <debug.h>
+
+#include "apic.h"
+
+extern LARGE_INTEGER HalpCpuClockFrequency;
+
+/* TIMER FUNCTIONS ************************************************************/
+
+VOID
+NTAPI
+ApicSetTimerInterval(ULONG MicroSeconds)
+{
+    LVT_REGISTER LvtEntry;
+    ULONGLONG TimerInterval;
+
+    /* Calculate the Timer interval */
+    TimerInterval = HalpCpuClockFrequency.QuadPart * MicroSeconds / 1000000;
+
+    /* Set the count interval */
+    ApicWrite(APIC_TICR, (ULONG)TimerInterval);
+
+    /* Set to periodic */
+    LvtEntry.Long = 0;
+    LvtEntry.TimerMode = 1;
+    LvtEntry.Vector = APIC_PROFILE_VECTOR;
+    LvtEntry.Mask = 0;
+    ApicWrite(APIC_TMRLVTR, LvtEntry.Long);
+
+}
+
+VOID
+NTAPI
+ApicInitializeTimer(ULONG Cpu)
+{
+
+    /* Initialize the TSC */
+    //HalpInitializeTsc();
+
+    /* Set clock multiplier to 1 */
+    ApicWrite(APIC_TDCR, TIMER_DV_DivideBy1);
+
+    ApicSetTimerInterval(1000);
+
+// KeSetTimeIncrement
+}
+
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+VOID
+NTAPI
+HalStartProfileInterrupt(IN KPROFILE_SOURCE ProfileSource)
+{
+    UNIMPLEMENTED;
+    return;
+}
+
+VOID
+NTAPI
+HalStopProfileInterrupt(IN KPROFILE_SOURCE ProfileSource)
+{
+    UNIMPLEMENTED;
+    return;
+}
+
+ULONG_PTR
+NTAPI
+HalSetProfileInterval(IN ULONG_PTR Interval)
+{
+    UNIMPLEMENTED;
+    return Interval;
+}

Propchange: trunk/reactos/hal/halx86/apic/apictimer.c
------------------------------------------------------------------------------
    svn:eol-style = native

Added: trunk/reactos/hal/halx86/apic/apictrap.S
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/apic/apictrap.S?rev=53611&view=auto
==============================================================================
--- trunk/reactos/hal/halx86/apic/apictrap.S (added)
+++ trunk/reactos/hal/halx86/apic/apictrap.S [iso-8859-1] Tue Sep  6 21:01:49 2011
@@ -1,0 +1,36 @@
+/*
+ * FILE:            hal/halx86/apic/apictrap.S
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PURPOSE:         System Traps, Entrypoints and Exitpoints
+ * PROGRAMMER:      Timo Kreuzer (timo.kreuzer at reactos.org)
+ * NOTE:            See asmmacro.S for the shared entry/exit code.
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <asm.inc>
+#include <internal/i386/asmmacro.S>
+
+#ifdef _M_AMD64
+#include <ksamd64.inc>
+PUBLIC ApicSpuriousService
+#else
+#include <ks386.inc>
+PUBLIC _ApicSpuriousService
+#endif
+
+.code
+
+TRAP_ENTRY HalpTrap0D, 0
+TRAP_ENTRY HalpApcInterrupt, KI_SOFTWARE_TRAP
+TRAP_ENTRY HalpDispatchInterrupt, KI_PUSH_FAKE_ERROR_CODE
+TRAP_ENTRY HalpClockInterrupt, KI_PUSH_FAKE_ERROR_CODE
+TRAP_ENTRY HalpProfileInterrupt, KI_PUSH_FAKE_ERROR_CODE
+
+FUNC ApicSpuriousService
+    int 3
+    iret
+ENDFUNC ApicSpuriousService
+
+
+END

Propchange: trunk/reactos/hal/halx86/apic/apictrap.S
------------------------------------------------------------------------------
    svn:eol-style = native

Added: trunk/reactos/hal/halx86/apic/rtctimer.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/apic/rtctimer.c?rev=53611&view=auto
==============================================================================
--- trunk/reactos/hal/halx86/apic/rtctimer.c (added)
+++ trunk/reactos/hal/halx86/apic/rtctimer.c [iso-8859-1] Tue Sep  6 21:01:49 2011
@@ -1,0 +1,144 @@
+/*
+ * PROJECT:         ReactOS HAL
+ * LICENSE:         GNU GPL - See COPYING in the top level directory
+ * FILE:            hal/halx86/generic/apic.c
+ * PURPOSE:         HAL APIC Management and Control Code
+ * PROGRAMMERS:     Timo Kreuzer (timo.kreuzer at reactos.org)
+ * REFERENCES:
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <hal.h>
+#define NDEBUG
+#include <debug.h>
+
+
+/* GLOBALS ********************************************************************/
+
+const UCHAR HalpClockVector = 0xD1;
+BOOLEAN HalpClockSetMSRate;
+UCHAR HalpNextMSRate;
+UCHAR HalpCurrentRate = 9;
+ULONG HalpCurrentTimeIncrement;
+static UCHAR RtcLargestClockRate = 10;
+
+
+ULONG
+FORCEINLINE
+RtcClockRateToIncrement(UCHAR Rate)
+{
+    ULONG Freqency = ((32768 << 1) >> Rate);
+    return (1000000 + (Freqency/2)) / Freqency;
+}
+
+VOID
+RtcSetClockRate(UCHAR ClockRate)
+{
+    ULONG_PTR EFlags;
+    UCHAR RegisterA;
+
+    /* Disable interrupts */
+    EFlags = __readeflags();
+    _disable();
+
+    // TODO: disable NMI
+
+    /* Read value of register A */
+    RegisterA = HalpReadCmos(RTC_REGISTER_A);
+
+    /* Change lower 4 bits to new rate */
+    RegisterA &= 0xF0;
+    RegisterA |= ClockRate;
+
+    /* Write the new value */
+    HalpWriteCmos(RTC_REGISTER_A, RegisterA);
+
+    /* Restore interrupts if they were previously enabled */
+    __writeeflags(EFlags);
+}
+
+
+VOID
+NTAPI
+INIT_FUNCTION
+HalpInitializeClock(VOID)
+{
+    UCHAR RegisterB;
+    // TODO: disable NMI
+
+    /* Enable the periodic interrupt in the CMOS */
+    RegisterB = HalpReadCmos(RTC_REGISTER_B);
+    HalpWriteCmos(RTC_REGISTER_B, RegisterB | RTC_REG_B_PI);
+
+   // RtcSetClockRate(HalpCurrentRate);
+}
+
+VOID
+FASTCALL
+HalpClockInterruptHandler(IN PKTRAP_FRAME TrapFrame)
+{
+    ULONG LastIncrement;
+    KIRQL Irql;
+
+    /* Enter trap */
+    KiEnterInterruptTrap(TrapFrame);
+__debugbreak();
+    /* Start the interrupt */
+    if (HalBeginSystemInterrupt(CLOCK2_LEVEL, PRIMARY_VECTOR_BASE, &Irql))
+    {
+        /* Read register C, so that the next interrupt can happen */
+        HalpReadCmos(RTC_REGISTER_C);;
+
+        /* Save increment */
+        LastIncrement = HalpCurrentTimeIncrement;
+
+        /* Check if someone changed the time rate */
+        if (HalpClockSetMSRate)
+        {
+            /* Update the global values */
+            HalpCurrentRate = HalpNextMSRate;
+            HalpCurrentTimeIncrement = RtcClockRateToIncrement(HalpCurrentRate);
+
+            /* Set new clock rate */
+            RtcSetClockRate(HalpCurrentRate);
+
+            /* We're done */
+            HalpClockSetMSRate = FALSE;
+        }
+
+        /* Update the system time -- the kernel will exit this trap  */
+        KeUpdateSystemTime(TrapFrame, LastIncrement, Irql);
+    }
+
+    /* Spurious, just end the interrupt */
+    KiEoiHelper(TrapFrame);
+}
+
+VOID
+FASTCALL
+HalpProfileInterruptHandler(IN PKTRAP_FRAME TrapFrame)
+{
+    __debugbreak();
+}
+
+ULONG
+NTAPI
+HalSetTimeIncrement(IN ULONG Increment)
+{
+    UCHAR Rate;
+
+    /* Lookup largest value below given Increment */
+    for (Rate = 2; Rate < RtcLargestClockRate; Rate++)
+    {
+        /* Check if this is the largest rate possible */
+        if (RtcClockRateToIncrement(Rate + 1) > Increment) break;
+    }
+
+    /* Set the rate and tell HAL we want to change it */
+    HalpNextMSRate = Rate;
+    HalpClockSetMSRate = TRUE;
+
+    /* Return the real increment */
+    return RtcClockRateToIncrement(Rate);
+}

Propchange: trunk/reactos/hal/halx86/apic/rtctimer.c
------------------------------------------------------------------------------
    svn:eol-style = native

Added: trunk/reactos/hal/halx86/apic/tsc.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/apic/tsc.c?rev=53611&view=auto
==============================================================================
--- trunk/reactos/hal/halx86/apic/tsc.c (added)
+++ trunk/reactos/hal/halx86/apic/tsc.c [iso-8859-1] Tue Sep  6 21:01:49 2011
@@ -1,0 +1,140 @@
+/*
+ * PROJECT:         ReactOS HAL
+ * LICENSE:         GPL - See COPYING in the top level directory
+ * FILE:            hal/halamd64/generic/tsc.c
+ * PURPOSE:         HAL Routines for TSC handling
+ * PROGRAMMERS:     Timo Kreuzer (timo.kreuzer at reactos.org)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <hal.h>
+#define NDEBUG
+#include <debug.h>
+
+#include "tsc.h"
+
+LARGE_INTEGER HalpCpuClockFrequency = {INITIAL_STALL_COUNT * 1000000};
+
+UCHAR TscCalibrationPhase;
+LARGE_INTEGER TscCalibrationArray[NUM_SAMPLES];
+extern const UCHAR HalpClockVector;
+
+/* PRIVATE FUNCTIONS *********************************************************/
+
+VOID
+NTAPI
+HalpInitializeTsc()
+{
+    ULONG_PTR Flags;
+    KIDTENTRY OldIdtEntry, *IdtPointer;
+    PKPCR Pcr = KeGetPcr();
+
+    /* Check if the CPU supports RDTSC */
+    if (!(KeGetCurrentPrcb()->FeatureBits & KF_RDTSC))
+    {
+        KeBugCheck(HAL_INITIALIZATION_FAILED);
+    }
+
+     /* Save flags and disable interrupts */
+    Flags = __readeflags();
+    _disable();
+
+__debugbreak();
+
+    /* Initialze the PIT */
+    //HalpInitializePIT();
+
+    /* Save old IDT entry */
+    IdtPointer = KiGetIdtEntry(Pcr, HalpClockVector);
+    OldIdtEntry = *IdtPointer;
+
+    /* Set the calibration ISR */
+    KeRegisterInterruptHandler(HalpClockVector, TscCalibrationISR);
+
+    /* Reset TSC value to 0 */
+    __writemsr(MSR_RDTSC, 0);
+
+    /* Enable the timer interupt */
+    HalEnableSystemInterrupt(HalpClockVector, CLOCK_LEVEL, Latched);
+
+    /* Wait for completion */
+    _enable();
+    while (TscCalibrationPhase < NUM_SAMPLES) _ReadWriteBarrier();
+    _disable();
+
+    /* Disable the timer interupt */
+    HalDisableSystemInterrupt(HalpClockVector, CLOCK_LEVEL);
+
+    /* Restore old IDT entry */
+    *IdtPointer = OldIdtEntry;
+
+    // do linear regression
+
+
+    /* Restore flags */
+    __writeeflags(Flags);
+
+}
+
+VOID
+NTAPI
+HalpCalibrateStallExecution(VOID)
+{
+    // Timer interrupt is now active
+
+    HalpInitializeTsc();
+
+    KeGetPcr()->StallScaleFactor = (ULONG)(HalpCpuClockFrequency.QuadPart / 1000000);
+}
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+LARGE_INTEGER
+NTAPI
+KeQueryPerformanceCounter(
+    OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL)
+{
+    LARGE_INTEGER Result;
+
+    /* Make sure it's calibrated */
+    ASSERT(HalpCpuClockFrequency.QuadPart != 0);
+
+    /* Does the caller want the frequency? */
+    if (PerformanceFrequency)
+    {
+        /* Return tsc frequency */
+        *PerformanceFrequency = HalpCpuClockFrequency;
+    }
+
+    /* Return the current value */
+    Result.QuadPart = __rdtsc();
+    return Result;
+}
+
+VOID
+NTAPI
+KeStallExecutionProcessor(ULONG MicroSeconds)
+{
+    ULONG64 StartTime, EndTime;
+
+    /* Get the initial time */
+    StartTime = __rdtsc();
+
+    /* Calculate the ending time */
+    EndTime = StartTime + HalpCpuClockFrequency.QuadPart * MicroSeconds;
+
+    /* Loop until time is elapsed */
+    while (__rdtsc() < EndTime);
+}
+
+VOID
+NTAPI
+HalCalibratePerformanceCounter(
+    IN volatile PLONG Count,
+    IN ULONGLONG NewCount)
+{
+    UNIMPLEMENTED;
+    ASSERT(FALSE);
+}
+

Propchange: trunk/reactos/hal/halx86/apic/tsc.c
------------------------------------------------------------------------------
    svn:eol-style = native

Added: trunk/reactos/hal/halx86/apic/tsc.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/apic/tsc.h?rev=53611&view=auto
==============================================================================
--- trunk/reactos/hal/halx86/apic/tsc.h (added)
+++ trunk/reactos/hal/halx86/apic/tsc.h [iso-8859-1] Tue Sep  6 21:01:49 2011
@@ -1,0 +1,15 @@
+
+
+#define NUM_SAMPLES 4
+#define MSR_RDTSC 0x10
+
+#ifndef __ASM__
+
+void TscCalibrationISR(void);
+extern LARGE_INTEGER HalpCpuClockFrequency;
+VOID NTAPI HalpInitializeTsc();
+
+
+#define KiGetIdtEntry(Pcr, Vector) &((Pcr)->IDT[Vector])
+
+#endif

Propchange: trunk/reactos/hal/halx86/apic/tsc.h
------------------------------------------------------------------------------
    svn:eol-style = native

Added: trunk/reactos/hal/halx86/apic/tsccal.S
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/apic/tsccal.S?rev=53611&view=auto
==============================================================================
--- trunk/reactos/hal/halx86/apic/tsccal.S (added)
+++ trunk/reactos/hal/halx86/apic/tsccal.S [iso-8859-1] Tue Sep  6 21:01:49 2011
@@ -1,0 +1,39 @@
+
+#include <asm.inc>
+#include "tsc.h"
+
+.code
+
+EXTERN _TscCalibrationPhase:BYTE
+EXTERN _TscCalibrationArray:QWORD
+
+PUBLIC _TscCalibrationISR
+_TscCalibrationISR:
+    push eax
+    push ecx
+    push edx
+
+    /* The first thing we do is read the current TSC value */
+    rdtsc
+
+    /* Read the current phase */
+    movzx ecx, byte ptr ds:[_TscCalibrationPhase]
+
+    /* Check if we're already done */
+    cmp cl, NUM_SAMPLES
+    jnb _CalibrationISR_Exit
+
+    /* Store the current value */
+    mov dword ptr _TscCalibrationArray[ecx * 2], eax
+    mov dword ptr _TscCalibrationArray[ecx * 2 + 4], edx
+
+    /* Advance phase */
+    inc byte ptr ds:[_TscCalibrationPhase]
+
+_CalibrationISR_Exit:
+    pop edx
+    pop ecx
+    pop eax
+    iretd
+
+END

Propchange: trunk/reactos/hal/halx86/apic/tsccal.S
------------------------------------------------------------------------------
    svn:eol-style = native




More information about the Ros-diffs mailing list