2 added + 8 modified, total 10 files
reactos/hal/halx86
diff -N apic.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ apic.c 28 Nov 2004 01:30:01 -0000 1.1
@@ -0,0 +1,853 @@
+/*
+ * ReactOS kernel
+ * Copyright (C) 2004 ReactOS Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* $Id: apic.c,v 1.1 2004/11/28 01:30:01 hbirr Exp $
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: hal/halx86/apic.c
+ * PURPOSE:
+ * PROGRAMMER:
+ */
+
+#include <roscfg.h>
+#include <ddk/ntddk.h>
+
+#include <hal.h>
+#include <halirq.h>
+#include <mps.h>
+#include <apic.h>
+
+#define NDEBUG
+#include <internal/debug.h>
+
+BOOLEAN VerifyLocalAPIC(VOID);
+VOID APICCalibrateTimer(ULONG CPU);
+
+extern VOID MpsTimerInterrupt(VOID);
+extern VOID MpsErrorInterrupt(VOID);
+extern VOID MpsSpuriousInterrupt(VOID);
+extern VOID MpsIpiInterrupt(VOID);
+
+extern ULONG APICMode; /* APIC mode at startup */
+extern PULONG BIOSBase; /* Virtual address of BIOS data segment */
+extern PULONG CommonBase; /* Virtual address of common area */
+extern ULONG BootCPU; /* Bootstrap processor */
+extern ULONG OnlineCPUs; /* Bitmask of online CPUs */
+
+extern CHAR *APstart, *APend;
+extern VOID (*APflush)(VOID);
+
+#define CMOS_READ(address) ({ \
+ WRITE_PORT_UCHAR((PUCHAR)0x70, address)); \
+ READ_PORT_UCHAR((PUCHAR)0x71)); \
+})
+
+#define CMOS_WRITE(address, value) ({ \
+ WRITE_PORT_UCHAR((PUCHAR)0x70, address); \
+ WRITE_PORT_UCHAR((PUCHAR)0x71, value); \
+})
+
+#define BIOS_AREA 0x0
+#define COMMON_AREA 0x2000
+
+
+extern CPU_INFO CPUMap[MAX_CPU]; /* Map of all CPUs in the system */
+
+PULONG APICBase = (PULONG)APIC_DEFAULT_BASE; /* Virtual address of local APIC */
+
+/* For debugging */
+ULONG lastregr[MAX_CPU];
+ULONG lastvalr[MAX_CPU];
+ULONG lastregw[MAX_CPU];
+ULONG lastvalw[MAX_CPU];
+
+ULONG APICGetMaxLVT(VOID)
+{
+ ULONG tmp, ver, maxlvt;
+
+ tmp = APICRead(APIC_VER);
+ ver = GET_APIC_VERSION(tmp);
+ /* 82489DXs do not report # of LVT entries. */
+ maxlvt = APIC_INTEGRATED(ver) ? GET_APIC_MAXLVT(tmp) : 2;
+
+ return maxlvt;
+}
+
+VOID APICClear(VOID)
+{
+ ULONG tmp, maxlvt;
+
+ maxlvt = APICGetMaxLVT();
+
+ /*
+ * Careful: we have to set masks only first to deassert
+ * any level-triggered sources.
+ */
+
+ if (maxlvt >= 3)
+ {
+ tmp = ERROR_VECTOR;
+ APICWrite(APIC_LVT3, tmp | APIC_LVT3_MASKED);
+ }
+
+ tmp = APICRead(APIC_LVTT);
+ APICWrite(APIC_LVTT, tmp | APIC_LVT_MASKED);
+
+ tmp = APICRead(APIC_LINT0);
+ APICWrite(APIC_LINT0, tmp | APIC_LVT_MASKED);
+
+ tmp = APICRead(APIC_LINT1);
+ APICWrite(APIC_LINT1, tmp | APIC_LVT_MASKED);
+
+ if (maxlvt >= 4)
+ {
+ tmp = APICRead(APIC_LVTPC);
+ APICWrite(APIC_LVTPC, tmp | APIC_LVT_MASKED);
+ }
+#if 0
+ if (maxlvt >= 5)
+ {
+ tmp = APICRead(APIC_LVTTHMR);
+ APICWrite(APIC_LVTTHMR, tmp | APIC_LVT_MASKED);
+ }
+#endif
+ /*
+ * Clean APIC state for other OSs:
+ */
+ APICWrite(APIC_LVTT, APIC_LVT_MASKED);
+ APICWrite(APIC_LINT0, APIC_LVT_MASKED);
+ APICWrite(APIC_LINT1, APIC_LVT_MASKED);
+
+ if (maxlvt >= 3)
+ {
+ APICWrite(APIC_LVT3, APIC_LVT3_MASKED);
+ }
+
+ if (maxlvt >= 4)
+ {
+ APICWrite(APIC_LVTPC, APIC_LVT_MASKED);
+ }
+#if 0
+ if (maxlvt >= 5)
+ {
+ APICWrite(APIC_LVTTHMR, APIC_LVT_MASKED);
+ }
+#endif
+}
+
+/* Enable symetric I/O mode ie. connect the BSP's local APIC to INT and NMI lines */
+VOID EnableSMPMode(VOID)
+{
+ /*
+ * Do not trust the local APIC being empty at bootup.
+ */
+ APICClear();
+
+ WRITE_PORT_UCHAR((PUCHAR)0x22, 0x70);
+ WRITE_PORT_UCHAR((PUCHAR)0x23, 0x01);
+}
+
+/* Disable symetric I/O mode ie. go to PIC mode */
+inline VOID DisableSMPMode(VOID)
+{
+ /*
+ * Put the board back into PIC mode (has an effect
+ * only on certain older boards). Note that APIC
+ * interrupts, including IPIs, won't work beyond
+ * this point! The only exception are INIT IPIs.
+ */
+ WRITE_PORT_UCHAR((PUCHAR)0x22, 0x70);
+ WRITE_PORT_UCHAR((PUCHAR)0x23, 0x00);
+}
+
+VOID DumpESR(VOID)
+{
+ ULONG tmp;
+
+ if (APICGetMaxLVT() > 3)
+ {
+ APICWrite(APIC_ESR, 0);
+ }
+ tmp = APICRead(APIC_ESR);
+ DbgPrint("ESR %08x\n", tmp);
+}
+
+
+VOID APICDisable(VOID)
+{
+ ULONG tmp;
+
+ APICClear();
+
+ /*
+ * Disable APIC (implies clearing of registers for 82489DX!).
+ */
+ tmp = APICRead(APIC_SIVR);
+ tmp &= ~APIC_SIVR_ENABLE;
+ APICWrite(APIC_SIVR, tmp);
+}
+
+VOID HaliInitBSP(VOID)
+{
+ PUSHORT ps;
+ static BOOLEAN BSPInitialized = FALSE;
+
+ /* Only initialize the BSP once */
+ if (BSPInitialized)
+ {
+ KEBUGCHECK(0);
+ return;
+ }
+
+ BSPInitialized = TRUE;
+
+ DPRINT("APIC is mapped at 0x%X\n", APICBase);
+
+ if (VerifyLocalAPIC())
+ {
+ DPRINT("APIC found\n");
+ }
+ else
+ {
+ DPRINT("No APIC found\n");
+ KEBUGCHECK(0);
+ }
+
+ if (APICMode == amPIC)
+ {
+ EnableSMPMode();
+ }
+
+ APICSetup();
+
+ /* BIOS data segment */
+ BIOSBase = (PULONG)BIOS_AREA;
+
+ /* Area for communicating with the APs */
+ CommonBase = (PULONG)COMMON_AREA;
+
+ /* Copy bootstrap code to common area */
+ memcpy((PVOID)((ULONG)CommonBase + PAGE_SIZE),
+ &APstart,
+ (ULONG)&APend - (ULONG)&APstart + 1);
+
+ /* Set shutdown code */
+ CMOS_WRITE(0xF, 0xA);
+
+ /* Set warm reset vector */
+ ps = (PUSHORT)((ULONG)BIOSBase + 0x467);
+ *ps = (COMMON_AREA + PAGE_SIZE) & 0xF;
+
+ ps = (PUSHORT)((ULONG)BIOSBase + 0x469);
+ *ps = (COMMON_AREA + PAGE_SIZE) >> 4;
+
+ /* Calibrate APIC timer */
+ APICCalibrateTimer(BootCPU);
+}
+
+volatile inline ULONG _APICRead(ULONG Offset)
+{
+ PULONG p;
+
+ p = (PULONG)((ULONG)APICBase + Offset);
+ return *p;
+}
+
+#if 0
+inline VOID APICWrite(ULONG Offset,
+ ULONG Value)
+{
+ PULONG p;
+
+ p = (PULONG)((ULONG)APICBase + Offset);
+
+ *p = Value;
+}
+#else
+inline VOID APICWrite(ULONG Offset,
+ ULONG Value)
+{
+ PULONG p;
+ ULONG CPU = (_APICRead(APIC_ID) & APIC_ID_MASK) >> 24;
+
+ lastregw[CPU] = Offset;
+ lastvalw[CPU] = Value;
+
+ p = (PULONG)((ULONG)APICBase + Offset);
+
+ *p = Value;
+}
+#endif
+
+
+#if 0
+volatile inline ULONG APICRead(ULONG Offset)
+{
+ PULONG p;
+
+ p = (PULONG)((ULONG)APICBase + Offset);
+ return *p;
+}
+#else
+volatile inline ULONG APICRead(ULONG Offset)
+{
+ PULONG p;
+ ULONG CPU = (_APICRead(APIC_ID) & APIC_ID_MASK) >> 24;
+
+ lastregr[CPU] = Offset;
+ lastvalr[CPU] = 0;
+
+ p = (PULONG)((ULONG)APICBase + Offset);
+
+ lastvalr[CPU] = *p;
+ return lastvalr[CPU];
+}
+#endif
+
+inline VOID APICSendEOI(VOID)
+{
+ // Send the EOI
+ APICWrite(APIC_EOI, 0);
+}
+
+static VOID APICDumpBit(ULONG base)
+{
+ ULONG v, i, j;
+
+ DbgPrint("0123456789abcdef0123456789abcdef\n");
+ for (i = 0; i < 8; i++)
+ {
+ v = APICRead(base + i*0x10);
+ for (j = 0; j < 32; j++)
+ {
+ if (v & (1<<j))
+ DbgPrint("1");
+ else
+ DbgPrint("0");
+ }
+ DbgPrint("\n");
+ }
+}
+
+
+VOID APICDump(VOID)
+/*
+ * Dump the contents of the local APIC registers
+ */
+{
+ ULONG v, ver, maxlvt;
+ ULONG r1, r2, w1, w2;
+ ULONG CPU = ThisCPU();;
+
+
+
+ r1 = lastregr[CPU];
+ r2 = lastvalr[CPU];
+ w1 = lastregw[CPU];
+ w2 = lastvalw[CPU];
+
+ DbgPrint("\nPrinting local APIC contents on CPU(%d):\n", ThisCPU());
+ v = APICRead(APIC_ID);
+ DbgPrint("... ID : %08x (%01x) ", v, GET_APIC_ID(v));
+ v = APICRead(APIC_VER);
+ DbgPrint("... VERSION: %08x\n", v);
+ ver = GET_APIC_VERSION(v);
+ maxlvt = APICGetMaxLVT();
+
+ v = APICRead(APIC_TPR);
+ DbgPrint("... TPR : %08x (%02x)", v, v & ~0);
+
+ if (APIC_INTEGRATED(ver))
+ {
+ /* !82489DX */
+ v = APICRead(APIC_APR);
+ DbgPrint("... APR : %08x (%02x)\n", v, v & ~0);
+ v = APICRead(APIC_PPR);
+ DbgPrint("... PPR : %08x\n", v);
+ }
+
+ v = APICRead(APIC_EOI);
+ DbgPrint("... EOI : %08x ! ", v);
+ v = APICRead(APIC_LDR);
+ DbgPrint("... LDR : %08x\n", v);
+ v = APICRead(APIC_DFR);
+ DbgPrint("... DFR : %08x ! ", v);
+ v = APICRead(APIC_SIVR);
+ DbgPrint("... SIVR : %08x\n", v);
+
+ if (0)
+ {
+ DbgPrint("... ISR field:\n");
+ APICDumpBit(APIC_ISR);
+ DbgPrint("... TMR field:\n");
+ APICDumpBit(APIC_TMR);
+ DbgPrint("... IRR field:\n");
+ APICDumpBit(APIC_IRR);
+ }
+
+ if (APIC_INTEGRATED(ver))
+ {
+ /* !82489DX */
+ if (maxlvt > 3)
+ {
+ /* Due to the Pentium erratum 3AP. */
+ APICWrite(APIC_ESR, 0);
+ }
+ v = APICRead(APIC_ESR);
+ DbgPrint("... ESR : %08x\n", v);
+ }
+
+ v = APICRead(APIC_ICR0);
+ DbgPrint("... ICR0 : %08x ! ", v);
+ v = APICRead(APIC_ICR1);
+ DbgPrint("... ICR1 : %08x ! ", v);
+
+ v = APICRead(APIC_LVTT);
+ DbgPrint("... LVTT : %08x\n", v);
+
+ if (maxlvt > 3)
+ {
+ /* PC is LVT#4. */
+ v = APICRead(APIC_LVTPC);
+ DbgPrint("... LVTPC : %08x ! ", v);
+ }
+ v = APICRead(APIC_LINT0);
+ DbgPrint("... LINT0 : %08x ! ", v);
+ v = APICRead(APIC_LINT1);
+ DbgPrint("... LINT1 : %08x\n", v);
+
+ if (maxlvt > 2)
+ {
+ v = APICRead(APIC_LVT3);
+ DbgPrint("... LVT3 : %08x\n", v);
+ }
+
+ v = APICRead(APIC_ICRT);
+ DbgPrint("... ICRT : %08x ! ", v);
+ v = APICRead(APIC_CCRT);
+ DbgPrint("... CCCT : %08x ! ", v);
+ v = APICRead(APIC_TDCR);
+ DbgPrint("... TDCR : %08x\n", v);
+ DbgPrint("\n");
+ DbgPrint("Last register read (offset): 0x%08X\n", r1);
+ DbgPrint("Last register read (value): 0x%08X\n", r2);
+ DbgPrint("Last register written (offset): 0x%08X\n", w1);
+ DbgPrint("Last register written (value): 0x%08X\n", w2);
+ DbgPrint("\n");
+}
+
+BOOLEAN VerifyLocalAPIC(VOID)
+{
+ UINT reg0, reg1;
+ CHECKPOINT1;
+ /* The version register is read-only in a real APIC */
+ reg0 = APICRead(APIC_VER);
+ DPRINT1("Getting VERSION: %x\n", reg0);
+ APICWrite(APIC_VER, reg0 ^ APIC_VER_MASK);
+ reg1 = APICRead(APIC_VER);
+ DPRINT1("Getting VERSION: %x\n", reg1);
+
+ /*
+ * The two version reads above should print the same
+ * numbers. If the second one is different, then we
+ * poke at a non-APIC.
+ */
+
+ if (reg1 != reg0)
+ {
+ return FALSE;
+ }
+
+ /*
+ * Check if the version looks reasonably.
+ */
+ reg1 = GET_APIC_VERSION(reg0);
+ if (reg1 == 0x00 || reg1 == 0xff)
+ {
+ return FALSE;
+ }
+ reg1 = APICGetMaxLVT();
+ if (reg1 < 0x02 || reg1 == 0xff)
+ {
+ return FALSE;
+ }
+
+ /*
+ * The ID register is read/write in a real APIC.
+ */
+ reg0 = APICRead(APIC_ID);
+ DPRINT1("Getting ID: %x\n", reg0);
+ APICWrite(APIC_ID, reg0 ^ APIC_ID_MASK);
+ reg1 = APICRead(APIC_ID);
+ DPRINT1("Getting ID: %x\n", reg1);
+ APICWrite(APIC_ID, reg0);
+ if (reg1 != (reg0 ^ APIC_ID_MASK))
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+VOID APICSendIPI(ULONG Target, ULONG Mode)
+{
+ ULONG tmp, i, flags;
+
+ /* save flags and disable interrupts */
+ Ki386SaveFlags(flags);
+ Ki386DisableInterrupts();
+
+ /* Wait up to 100ms for the APIC to become ready */
+ for (i = 0; i < 10000; i++)
+ {
+ tmp = APICRead(APIC_ICR0);
+ /* Check Delivery Status */
+ if ((tmp & APIC_ICR0_DS) == 0)
+ break;
+ KeStallExecutionProcessor(10);
+ }
+
+ if (i == 10000)
+ {
+ DPRINT1("CPU(%d) Previous IPI was not delivered after 100ms.\n", ThisCPU());
+ }
+
+ /* Setup the APIC to deliver the IPI */
+ DPRINT("%08x %x\n", SET_APIC_DEST_FIELD(Target), Target);
+ APICWrite(APIC_ICR1, SET_APIC_DEST_FIELD(Target));
+
+ if (Target == APIC_TARGET_SELF)
+ {
+ Mode |= APIC_ICR0_DESTS_SELF;
+ }
+ else if (Target == APIC_TARGET_ALL)
+ {
+ Mode |= APIC_ICR0_DESTS_ALL;
+ }
+ else if (Target == APIC_TARGET_ALL_BUT_SELF)
+ {
+ Mode |= APIC_ICR0_DESTS_ALL_BUT_SELF;
+ }
+ else
+ {
+ Mode |= APIC_ICR0_DESTS_FIELD;
+ }
+
+ /* Now, fire off the IPI */
+ APICWrite(APIC_ICR0, Mode);
+
+ /* Wait up to 100ms for the APIC to become ready */
+ for (i = 0; i < 10000; i++)
+ {
+ tmp = APICRead(APIC_ICR0);
+ /* Check Delivery Status */
+ if ((tmp & APIC_ICR0_DS) == 0)
+ break;
+ KeStallExecutionProcessor(10);
+ }
+
+ if (i == 10000)
+ {
+ DPRINT1("CPU(%d) Current IPI was not delivered after 100ms.\n", ThisCPU());
+ }
+ Ki386RestoreFlags(flags);
+}
+
+VOID APICSetup(VOID)
+{
+ ULONG CPU, tmp;
+
+ CPU = ThisCPU();
+
+// APICDump();
+
+ DPRINT1("CPU%d:\n", CPU);
+ DPRINT1(" Physical APIC id: %d\n", GET_APIC_ID(APICRead(APIC_ID)));
+ DPRINT1(" Logical APIC id: %d\n", GET_APIC_LOGICAL_ID(APICRead(APIC_LDR)));
+ DPRINT1("%08x %08x %08x\n", APICRead(APIC_ID), APICRead(APIC_LDR), APICRead(APIC_DFR));
+
+ /*
+ * Intel recommends to set DFR, LDR and TPR before enabling
+ * an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel
+ * document number 292116). So here it goes...
+ */
+
+ /*
+ * Put the APIC into flat delivery mode.
+ * Must be "all ones" explicitly for 82489DX.
+ */
+ APICWrite(APIC_DFR, 0xFFFFFFFF);
+
+ /*
+ * Set up the logical destination ID.
+ */
+ tmp = APICRead(APIC_LDR);
+ tmp &= ~APIC_LDR_MASK;
+ /*
+ * FIXME:
+ * This works only up to 8 CPU's
+ */
+ tmp |= (1 << (KeGetCurrentProcessorNumber() + 24));
+ APICWrite(APIC_LDR, tmp);
+
+
+ DPRINT1("CPU%d:\n", CPU);
+ DPRINT1(" Physical APIC id: %d\n", GET_APIC_ID(APICRead(APIC_ID)));
+ DPRINT1(" Logical APIC id: %d\n", GET_APIC_LOGICAL_ID(APICRead(APIC_LDR)));
+ DPRINT1("%08x %08x %08x\n", APICRead(APIC_ID), APICRead(APIC_LDR), APICRead(APIC_DFR));
+ DPRINT1("%d\n", CPUMap[CPU].APICId);
+
+ /* Accept only higher interrupts */
+ APICWrite(APIC_TPR, 0xef);
+
+ /* Enable local APIC */
+ tmp = APICRead(APIC_SIVR);
+ tmp &= ~0xff;
+ tmp |= APIC_SIVR_ENABLE;
+
+#if 0
+ tmp &= ~APIC_SIVR_FOCUS;
+#else
+ tmp |= APIC_SIVR_FOCUS;
+#endif
+
+ /* Set spurious interrupt vector */
+ tmp |= SPURIOUS_VECTOR;
+ APICWrite(APIC_SIVR, tmp);
+
+ /*
+ * Set up LVT0, LVT1:
+ *
+ * set up through-local-APIC on the BP's LINT0. This is not
+ * strictly necessery in pure symmetric-IO mode, but sometimes
+ * we delegate interrupts to the 8259A.
+ */
+ tmp = APICRead(APIC_LINT0) & APIC_LVT_MASKED;
+ if (CPU == BootCPU && (APICMode == amPIC || !tmp))
+ {
+ tmp = APIC_DM_EXTINT;
+ DPRINT1("enabled ExtINT on CPU#%d\n", CPU);
+ }
+ else
+ {
+ tmp = APIC_DM_EXTINT | APIC_LVT_MASKED;
+ DPRINT1("masked ExtINT on CPU#%d\n", CPU);
+ }
+ APICWrite(APIC_LINT0, tmp);
+
+
+ /*
+ * Only the BSP should see the LINT1 NMI signal, obviously.
+ */
+ if (CPU == BootCPU)
+ {
+ tmp = APIC_DM_NMI;
+ }
+ else
+ {
+ tmp = APIC_DM_NMI | APIC_LVT_MASKED;
+ }
+ if (!APIC_INTEGRATED(CPUMap[CPU].APICVersion))
+ {
+ /* 82489DX */
+ tmp |= APIC_LVT_LEVEL_TRIGGER;
+ }
+ APICWrite(APIC_LINT1, tmp);
+
+ if (APIC_INTEGRATED(CPUMap[CPU].APICVersion))
+ {
+ /* !82489DX */
+ if (APICGetMaxLVT() > 3)
+ {
+ /* Due to the Pentium erratum 3AP */
+ APICWrite(APIC_ESR, 0);
+ }
+
+ tmp = APICRead(APIC_ESR);
+ DPRINT("ESR value before enabling vector: 0x%X\n", tmp);
+
+ /* Enable sending errors */
+ tmp = ERROR_VECTOR;
+ APICWrite(APIC_LVT3, tmp);
+
+ /*
+ * Spec says clear errors after enabling vector
+ */
+ if (APICGetMaxLVT() > 3)
+ {
+ APICWrite(APIC_ESR, 0);
+ }
+ tmp = APICRead(APIC_ESR);
+ DPRINT("ESR value after enabling vector: 0x%X\n", tmp);
+ }
+}
+
+VOID APICSyncArbIDs(VOID)
+{
+ ULONG i, tmp;
+
+ /* Wait up to 100ms for the APIC to become ready */
+ for (i = 0; i < 10000; i++)
+ {
+ tmp = APICRead(APIC_ICR0);
+ /* Check Delivery Status */
+ if ((tmp & APIC_ICR0_DS) == 0)
+ break;
+ KeStallExecutionProcessor(10);
+ }
+
+ if (i == 10000)
+ {
+ DPRINT("CPU(%d) APIC busy for 100ms.\n", ThisCPU());
+ }
+
+ DPRINT("Synchronizing Arb IDs.\n");
+ APICWrite(APIC_ICR0, APIC_ICR0_DESTS_ALL | APIC_ICR0_LEVEL | APIC_DM_INIT);
+}
+
+VOID MpsErrorHandler(VOID)
+{
+ ULONG tmp1, tmp2;
+
+ APICDump();
+
+ tmp1 = APICRead(APIC_ESR);
+ APICWrite(APIC_ESR, 0);
+ tmp2 = APICRead(APIC_ESR);
+ DPRINT1("APIC error on CPU(%d) ESR(%x)(%x)\n", ThisCPU(), tmp1, tmp2);
+
+ /*
+ * Acknowledge the interrupt
+ */
+ APICSendEOI();
+
+ /* Here is what the APIC error bits mean:
+ * 0: Send CS error
+ * 1: Receive CS error
+ * 2: Send accept error
+ * 3: Receive accept error
+ * 4: Reserved
+ * 5: Send illegal vector
+ * 6: Received illegal vector
+ * 7: Illegal register address
+ */
+ DPRINT1("APIC error on CPU(%d) ESR(%x)(%x)\n", ThisCPU(), tmp1, tmp2);
+ for (;;);
+}
+
+VOID MpsSpuriousHandler(VOID)
+{
+ ULONG tmp;
+
+ DPRINT1("Spurious interrupt on CPU(%d)\n", ThisCPU());
+
+ tmp = APICRead(APIC_ISR + ((SPURIOUS_VECTOR & ~0x1f) >> 1));
+ if (tmp & (1 << (SPURIOUS_VECTOR & 0x1f)))
+ {
+ APICSendEOI();
+ return;
+ }
+#if 0
+ /* No need to send EOI here */
+ APICDump();
+#endif
+}
+
+VOID MpsIpiHandler(VOID)
+{
+ KIRQL oldIrql;
+
+ HalBeginSystemInterrupt(IPI_VECTOR,
+ VECTOR2IRQL(IPI_VECTOR),
+ &oldIrql);
+ Ki386EnableInterrupts();
+#if 0
+ DbgPrint("(%s:%d) MpsIpiHandler on CPU%d, current irql is %d\n",
+ __FILE__,__LINE__, KeGetCurrentProcessorNumber(), KeGetCurrentIrql());
+#endif
+
+ KiIpiServiceRoutine(NULL, NULL);
+
+#if 0
+ DbgPrint("(%s:%d) MpsIpiHandler on CPU%d done\n", __FILE__,__LINE__, KeGetCurrentProcessorNumber());
+#endif
+
+ Ki386DisableInterrupts();
+ HalEndSystemInterrupt(oldIrql, 0);
+}
+
+VOID
+MpsIRQTrapFrameToTrapFrame(PKIRQ_TRAPFRAME IrqTrapFrame,
+ PKTRAP_FRAME TrapFrame)
+{
+ TrapFrame->Gs = (USHORT)IrqTrapFrame->Gs;
+ TrapFrame->Fs = (USHORT)IrqTrapFrame->Fs;
+ TrapFrame->Es = (USHORT)IrqTrapFrame->Es;
+ TrapFrame->Ds = (USHORT)IrqTrapFrame->Ds;
+ TrapFrame->Eax = IrqTrapFrame->Eax;
+ TrapFrame->Ecx = IrqTrapFrame->Ecx;
+ TrapFrame->Edx = IrqTrapFrame->Edx;
+ TrapFrame->Ebx = IrqTrapFrame->Ebx;
+ TrapFrame->Esp = IrqTrapFrame->Esp;
+ TrapFrame->Ebp = IrqTrapFrame->Ebp;
+ TrapFrame->Esi = IrqTrapFrame->Esi;
+ TrapFrame->Edi = IrqTrapFrame->Edi;
+ TrapFrame->Eip = IrqTrapFrame->Eip;
+ TrapFrame->Cs = IrqTrapFrame->Cs;
+ TrapFrame->Eflags = IrqTrapFrame->Eflags;
+}
+
+VOID
+MpsTimerHandler(ULONG Vector, PKIRQ_TRAPFRAME Trapframe)
+{
+ KIRQL oldIrql;
+ KTRAP_FRAME KernelTrapFrame;
+#if 0
+ ULONG CPU;
+ static ULONG Count[MAX_CPU] = {0,};
+#endif
+ HalBeginSystemInterrupt(LOCAL_TIMER_VECTOR,
+ VECTOR2IRQL(LOCAL_TIMER_VECTOR),
+ &oldIrql);
+ Ki386EnableInterrupts();
+
+#if 0
+ CPU = ThisCPU();
+ if ((Count[CPU] % 100) == 0)
+ {
+ DbgPrint("(%s:%d) MpsTimerHandler on CPU%d, irql = %d, epi = %x, KPCR = %x\n", __FILE__, __LINE__, CPU, oldIrql,Trapframe->Eip, KeGetCurrentKPCR());
+ }
+ Count[CPU]++;
+#endif
+
+ MpsIRQTrapFrameToTrapFrame(Trapframe, &KernelTrapFrame);
+ if (KeGetCurrentProcessorNumber() == 0)
+ {
+ KeUpdateSystemTime(&KernelTrapFrame, oldIrql);
+ }
+ else
+ {
+ KeUpdateRunTime(&KernelTrapFrame, oldIrql);
+ }
+
+ Ki386DisableInterrupts();
+ HalEndSystemInterrupt (oldIrql, 0);
+}
+
+/* EOF */
reactos/hal/halx86
diff -u -r1.14 -r1.15
--- Makefile 18 Oct 2004 19:11:07 -0000 1.14
+++ Makefile 28 Nov 2004 01:30:01 -0000 1.15
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.14 2004/10/18 19:11:07 chorns Exp $
+# $Id: Makefile,v 1.15 2004/11/28 01:30:01 hbirr Exp $
PATH_TO_TOP = ../..
@@ -72,6 +72,7 @@
HAL_MP = \
$(HAL_OBJECTS) \
+ apic.o \
mpsirql.o \
mpsboot.o \
mps.o
reactos/hal/halx86
diff -u -r1.9 -r1.10
--- halinit.c 22 Jul 2004 18:49:18 -0000 1.9
+++ halinit.c 28 Nov 2004 01:30:01 -0000 1.10
@@ -1,4 +1,4 @@
-/* $Id: halinit.c,v 1.9 2004/07/22 18:49:18 navaraf Exp $
+/* $Id: halinit.c,v 1.10 2004/11/28 01:30:01 hbirr Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@@ -64,7 +64,6 @@
{
HalpInitBusHandlers();
HalpInitDma();
- HalpCalibrateStallExecution();
/* Enumerate the devices on the motherboard */
HalpStartEnumerator();
reactos/hal/halx86
diff -u -r1.7 -r1.8
--- misc.c 1 Nov 2004 19:01:25 -0000 1.7
+++ misc.c 28 Nov 2004 01:30:01 -0000 1.8
@@ -1,4 +1,4 @@
-/* $Id: misc.c,v 1.7 2004/11/01 19:01:25 hbirr Exp $
+/* $Id: misc.c,v 1.8 2004/11/28 01:30:01 hbirr Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@@ -13,6 +13,13 @@
#include <ddk/ntddk.h>
#include <hal.h>
+#ifdef MP
+#include <apic.h>
+#endif
+
+#define NDEBUG
+#include <internal/debug.h>
+
/* FUNCTIONS ****************************************************************/
#ifdef MP
@@ -54,14 +61,16 @@
#endif
}
-
VOID STDCALL
-HalRequestIpi(ULONG Unknown)
+HalRequestIpi(ULONG ProcessorNo)
{
- return;
+ DPRINT("HalRequestIpi(ProcessorNo %d)\n", ProcessorNo);
+#ifdef MP
+ APICSendIPI(1 << ProcessorNo,
+ IPI_VECTOR|APIC_ICR0_LEVEL_DEASSERT|APIC_ICR0_DESTM);
+#endif
}
-
ULONG FASTCALL
HalSystemVectorDispatchEntry (
ULONG Unknown1,
reactos/hal/halx86
diff -u -r1.11 -r1.12
--- mp.c 1 Nov 2004 19:01:25 -0000 1.11
+++ mp.c 28 Nov 2004 01:30:01 -0000 1.12
@@ -1,4 +1,4 @@
-/* $Id: mp.c,v 1.11 2004/11/01 19:01:25 hbirr Exp $
+/* $Id: mp.c,v 1.12 2004/11/28 01:30:01 hbirr Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@@ -23,6 +23,7 @@
#include <hal.h>
#include <halirq.h>
#include <mps.h>
+#include <apic.h>
#include <internal/ntoskrnl.h>
#include <internal/i386/segment.h>
@@ -69,9 +70,7 @@
ULONG APICMode; /* APIC mode at startup */
ULONG BootCPU; /* Bootstrap processor */
-ULONG NextCPU; /* Next CPU to start */
PULONG BIOSBase; /* Virtual address of BIOS data segment */
-PULONG APICBase; /* Virtual address of local APIC */
PULONG CommonBase; /* Virtual address of common area */
extern CHAR *APstart, *APend;
@@ -80,6 +79,7 @@
extern VOID MpsTimerInterrupt(VOID);
extern VOID MpsErrorInterrupt(VOID);
extern VOID MpsSpuriousInterrupt(VOID);
+extern VOID MpsIpiInterrupt(VOID);
#define CMOS_READ(address) ({ \
WRITE_PORT_UCHAR((PUCHAR)0x70, address)); \
@@ -91,21 +91,9 @@
WRITE_PORT_UCHAR((PUCHAR)0x71, value); \
})
-static BOOLEAN MPSInitialized = FALSE; /* Is the MP system initialized? */
-
-VOID APICDisable(VOID);
-static VOID APICSyncArbIDs(VOID);
-
-/* For debugging */
-ULONG lastregr = 0;
-ULONG lastvalr = 0;
-ULONG lastregw = 0;
-ULONG lastvalw = 0;
-
#endif /* MP */
-static BOOLEAN BSPInitialized = FALSE; /* Is the BSP initialized? */
/* FUNCTIONS *****************************************************************/
@@ -117,10 +105,10 @@
{
ULONG tmp;
- if (irq & 8)
+ if (irq >= 8)
{
tmp = READ_PORT_UCHAR((PUCHAR)0xA1);
- tmp |= (1 << irq);
+ tmp |= (1 << (irq - 8));
WRITE_PORT_UCHAR((PUCHAR)0xA1, tmp);
}
else
@@ -136,10 +124,10 @@
{
ULONG tmp;
- if (irq & 8)
+ if (irq >= 8)
{
tmp = READ_PORT_UCHAR((PUCHAR)0xA1);
- tmp &= ~(1 << irq);
+ tmp &= ~(1 << (irq - 8));
WRITE_PORT_UCHAR((PUCHAR)0xA1, tmp);
}
else
@@ -176,6 +164,7 @@
{
IOAPIC_ROUTE_ENTRY Entry;
+ DPRINT("IOAPICClearPin(Apic %d, Pin %d\n", Apic, Pin);
/*
* Disable it in the IO-APIC irq-routing table
*/
@@ -652,7 +641,7 @@
*/
entry.dest.logical.logical_dest = OnlineCPUs;
#else
- entry.dest.logical.logical_dest = 1 << BootCPU;
+ entry.dest.logical.logical_dest = 1 << 0;
#endif
idx = IOAPICGetIrqEntry(apic,pin,INT_VECTORED);
if (idx == -1)
@@ -679,7 +668,7 @@
#if 0
entry.dest.logical.logical_dest = OnlineCPUs;
#else
- entry.dest.logical.logical_dest = 1 << BootCPU;
+ entry.dest.logical.logical_dest = 1 << 0;
#endif
}
@@ -899,317 +888,6 @@
/* Functions for handling local APICs */
-#if 0
-volatile inline ULONG APICRead(ULONG Offset)
-{
- PULONG p;
-
- p = (PULONG)((ULONG)APICBase + Offset);
- return *p;
-}
-#else
-volatile inline ULONG APICRead(ULONG Offset)
-{
- PULONG p;
-
- lastregr = Offset;
- lastvalr = 0;
-
- p = (PULONG)((ULONG)APICBase + Offset);
-
- lastvalr = *p;
- return lastvalr;
-}
-#endif
-
-#if 0
-inline VOID APICWrite(ULONG Offset,
- ULONG Value)
-{
- PULONG p;
-
- p = (PULONG)((ULONG)APICBase + Offset);
-
- *p = Value;
-}
-#else
-inline VOID APICWrite(ULONG Offset,
- ULONG Value)
-{
- PULONG p;
-
- lastregw = Offset;
- lastvalw = Value;
-
- p = (PULONG)((ULONG)APICBase + Offset);
-
- *p = Value;
-}
-#endif
-
-
-inline VOID APICSendEOI(VOID)
-{
- // Send the EOI
- APICWrite(APIC_EOI, 0);
-}
-
-
-VOID DumpESR(VOID)
-{
- ULONG tmp;
-
- if (CPUMap[ThisCPU()].MaxLVT > 3)
- {
- APICWrite(APIC_ESR, 0);
- }
- tmp = APICRead(APIC_ESR);
- DbgPrint("ESR %08x\n", tmp);
-}
-
-
-ULONG APICGetMaxLVT(VOID)
-{
- ULONG tmp, ver, maxlvt;
-
- tmp = APICRead(APIC_VER);
- ver = GET_APIC_VERSION(tmp);
- /* 82489DXs do not report # of LVT entries. */
- maxlvt = APIC_INTEGRATED(ver) ? GET_APIC_MAXLVT(tmp) : 2;
-
- return maxlvt;
-}
-
-
-static VOID APICClear(VOID)
-{
- ULONG tmp, maxlvt;
-
- maxlvt = CPUMap[ThisCPU()].MaxLVT;
-
- /*
- * Careful: we have to set masks only first to deassert
- * any level-triggered sources.
- */
- tmp = APICRead(APIC_LVTT);
- APICWrite(APIC_LVTT, tmp | APIC_LVT_MASKED);
-
- tmp = APICRead(APIC_LINT0);
- APICWrite(APIC_LINT0, tmp | APIC_LVT_MASKED);
-
- tmp = APICRead(APIC_LINT1);
- APICWrite(APIC_LINT1, tmp | APIC_LVT_MASKED);
-
- if (maxlvt >= 3)
- {
- tmp = APICRead(APIC_LVT3);
- APICWrite(APIC_LVT3, tmp | APIC_LVT3_MASKED);
- }
-
- if (maxlvt >= 4)
- {
- tmp = APICRead(APIC_LVTPC);
- APICWrite(APIC_LVTPC, tmp | APIC_LVT_MASKED);
- }
-
- /*
- * Clean APIC state for other OSs:
- */
- APICRead(APIC_SIVR); // Dummy read
- APICWrite(APIC_LVTT, APIC_LVT_MASKED);
-
- APICRead(APIC_SIVR); // Dummy read
- APICWrite(APIC_LINT0, APIC_LVT_MASKED);
-
- APICRead(APIC_SIVR); // Dummy read
- APICWrite(APIC_LINT1, APIC_LVT_MASKED);
-
- if (maxlvt >= 3)
- {
- APICRead(APIC_SIVR); // Dummy read
- APICWrite(APIC_LVT3, APIC_LVT3_MASKED);
- }
-
- if (maxlvt >= 4)
- {
- APICRead(APIC_SIVR); // Dummy read
- APICWrite(APIC_LVTPC, APIC_LVT_MASKED);
- }
-}
-
-/* Enable symetric I/O mode ie. connect the BSP's
- local APIC to INT and NMI lines */
-inline VOID EnableSMPMode(VOID)
-{
- /*
- * Do not trust the local APIC being empty at bootup.
- */
- APICClear();
-
- WRITE_PORT_UCHAR((PUCHAR)0x22, 0x70);
- WRITE_PORT_UCHAR((PUCHAR)0x23, 0x01);
-}
-
-
-/* Disable symetric I/O mode ie. go to PIC mode */
-inline VOID DisableSMPMode(VOID)
-{
- /*
- * Put the board back into PIC mode (has an effect
- * only on certain older boards). Note that APIC
- * interrupts, including IPIs, won't work beyond
- * this point! The only exception are INIT IPIs.
- */
- WRITE_PORT_UCHAR((PUCHAR)0x22, 0x70);
- WRITE_PORT_UCHAR((PUCHAR)0x23, 0x00);
-}
-
-
-VOID APICDisable(VOID)
-{
- ULONG tmp;
-
- APICClear();
-
- /*
- * Disable APIC (implies clearing of registers for 82489DX!).
- */
- tmp = APICRead(APIC_SIVR);
- tmp &= ~APIC_SIVR_ENABLE;
- APICWrite(APIC_SIVR, tmp);
-}
-
-
-inline ULONG ThisCPU(VOID)
-{
- return (APICRead(APIC_ID) & APIC_ID_MASK) >> 24;
-}
-
-
-static VOID APICDumpBit(ULONG base)
-{
- ULONG v, i, j;
-
- DbgPrint("0123456789abcdef0123456789abcdef\n");
- for (i = 0; i < 8; i++)
- {
- v = APICRead(base + i*0x10);
- for (j = 0; j < 32; j++)
- {
- if (v & (1<<j))
- DbgPrint("1");
- else
- DbgPrint("0");
- }
- DbgPrint("\n");
- }
-}
-
-
-VOID APICDump(VOID)
-/*
- * Dump the contents of the local APIC registers
- */
-{
- ULONG v, ver, maxlvt;
- ULONG r1, r2, w1, w2;
-
- r1 = lastregr;
- r2 = lastvalr;
- w1 = lastregw;
- w2 = lastvalw;
-
- DbgPrint("\nPrinting local APIC contents on CPU(%d):\n", ThisCPU());
- v = APICRead(APIC_ID);
- DbgPrint("... ID : %08x (%01x) ", v, GET_APIC_ID(v));
- v = APICRead(APIC_VER);
- DbgPrint("... VERSION: %08x\n", v);
- ver = GET_APIC_VERSION(v);
- maxlvt = CPUMap[ThisCPU()].MaxLVT;
-
- v = APICRead(APIC_TPR);
- DbgPrint("... TPR : %08x (%02x)", v, v & ~0);
-
- if (APIC_INTEGRATED(ver))
- {
- /* !82489DX */
- v = APICRead(APIC_APR);
- DbgPrint("... APR : %08x (%02x)\n", v, v & ~0);
- v = APICRead(APIC_PPR);
- DbgPrint("... PPR : %08x\n", v);
- }
-
- v = APICRead(APIC_EOI);
- DbgPrint("... EOI : %08x ! ", v);
- v = APICRead(APIC_LDR);
- DbgPrint("... LDR : %08x\n", v);
- v = APICRead(APIC_DFR);
- DbgPrint("... DFR : %08x ! ", v);
- v = APICRead(APIC_SIVR);
- DbgPrint("... SIVR : %08x\n", v);
-
- if (0)
- {
- DbgPrint("... ISR field:\n");
- APICDumpBit(APIC_ISR);
- DbgPrint("... TMR field:\n");
- APICDumpBit(APIC_TMR);
- DbgPrint("... IRR field:\n");
- APICDumpBit(APIC_IRR);
- }
-
- if (APIC_INTEGRATED(ver))
- {
- /* !82489DX */
- if (maxlvt > 3)
- {
- /* Due to the Pentium erratum 3AP. */
- APICWrite(APIC_ESR, 0);
- }
- v = APICRead(APIC_ESR);
- DbgPrint("... ESR : %08x\n", v);
- }
-
- v = APICRead(APIC_ICR0);
- DbgPrint("... ICR0 : %08x ! ", v);
- v = APICRead(APIC_ICR1);
- DbgPrint("... ICR1 : %08x ! ", v);
-
- v = APICRead(APIC_LVTT);
- DbgPrint("... LVTT : %08x\n", v);
-
- if (maxlvt > 3)
- {
- /* PC is LVT#4. */
- v = APICRead(APIC_LVTPC);
- DbgPrint("... LVTPC : %08x ! ", v);
- }
- v = APICRead(APIC_LINT0);
- DbgPrint("... LINT0 : %08x ! ", v);
- v = APICRead(APIC_LINT1);
- DbgPrint("... LINT1 : %08x\n", v);
-
- if (maxlvt > 2)
- {
- v = APICRead(APIC_LVT3);
- DbgPrint("... LVT3 : %08x\n", v);
- }
-
- v = APICRead(APIC_ICRT);
- DbgPrint("... ICRT : %08x ! ", v);
- v = APICRead(APIC_CCRT);
- DbgPrint("... CCCT : %08x ! ", v);
- v = APICRead(APIC_TDCR);
- DbgPrint("... TDCR : %08x\n", v);
- DbgPrint("\n");
- DbgPrint("Last register read (offset): 0x%08X\n", r1);
- DbgPrint("Last register read (value): 0x%08X\n", r2);
- DbgPrint("Last register written (offset): 0x%08X\n", w1);
- DbgPrint("Last register written (value): 0x%08X\n", w2);
- DbgPrint("\n");
-}
-
-
ULONG Read8254Timer(VOID)
{
ULONG Count;
@@ -1221,7 +899,6 @@
return Count;
}
-
VOID WaitFor8254Wraparound(VOID)
{
ULONG CurCount, PrevCount = ~0;
@@ -1316,155 +993,7 @@
CPUMap[CPU].BusSpeed%1000000);
}
-
-static VOID APICSleep(ULONG Count)
-/*
- PARAMETERS:
- Count = Number of microseconds to busy wait
- */
-{
- KeStallExecutionProcessor(Count);
-}
-
-
-static VOID APICSyncArbIDs(VOID)
-{
- ULONG i, tmp;
-
- /* Wait up to 100ms for the APIC to become ready */
- for (i = 0; i < 10000; i++)
- {
- tmp = APICRead(APIC_ICR0);
- /* Check Delivery Status */
- if ((tmp & APIC_ICR0_DS) == 0)
- break;
- APICSleep(10);
- }
-
- if (i == 10000)
- {
- DPRINT("CPU(%d) APIC busy for 100ms.\n", ThisCPU());
- }
-
- DPRINT("Synchronizing Arb IDs.\n");
- APICWrite(APIC_ICR0, APIC_ICR0_DESTS_ALL | APIC_ICR0_LEVEL | APIC_DM_INIT);
-}
-
-
-VOID APICSendIPI(ULONG Target,
- ULONG DeliveryMode,
- ULONG IntNum,
- ULONG Level)
-{
- ULONG tmp, i, flags;
-
- /* save flags and disable interrupts */
- Ki386SaveFlags(flags);
- Ki386DisableInterrupts();
-
- /* Wait up to 100ms for the APIC to become ready */
- for (i = 0; i < 10000; i++)
- {
- tmp = APICRead(APIC_ICR0);
- /* Check Delivery Status */
- if ((tmp & APIC_ICR0_DS) == 0)
- break;
- APICSleep(10);
- }
-
- if (i == 10000)
- {
- DPRINT("CPU(%d) Previous IPI was not delivered after 100ms.\n", ThisCPU());
- }
-
- /* Setup the APIC to deliver the IPI */
- tmp = APICRead(APIC_ICR1);
- tmp &= 0x00FFFFFF;
- APICWrite(APIC_ICR1, tmp | SET_APIC_DEST_FIELD(Target));
-
- tmp = APICRead(APIC_ICR0);
- tmp &= ~(APIC_ICR0_LEVEL | APIC_ICR0_DESTM | APIC_ICR0_DM | APIC_ICR0_VECTOR);
- tmp |= (DeliveryMode | IntNum | Level);
-
- if (Target == APIC_TARGET_SELF)
- {
- tmp |= APIC_ICR0_DESTS_SELF;
- }
- else if (Target == APIC_TARGET_ALL)
- {
- tmp |= APIC_ICR0_DESTS_ALL;
- }
- else if (Target == APIC_TARGET_ALL_BUT_SELF)
- {
- tmp |= APIC_ICR0_DESTS_ALL_BUT_SELF;
- }
- else
- {
- tmp |= APIC_ICR0_DESTS_FIELD;
- }
-
- /* Now, fire off the IPI */
- APICWrite(APIC_ICR0, tmp);
-
- Ki386RestoreFlags(flags);
-}
-
-
-BOOLEAN VerifyLocalAPIC(VOID)
-{
- UINT reg0, reg1;
-
- /* The version register is read-only in a real APIC */
- reg0 = APICRead(APIC_VER);
- DPRINT("Getting VERSION: %x\n", reg0);
- APICWrite(APIC_VER, reg0 ^ APIC_VER_MASK);
- reg1 = APICRead(APIC_VER);
- DPRINT("Getting VERSION: %x\n", reg1);
-
- /*
- * The two version reads above should print the same
- * numbers. If the second one is different, then we
- * poke at a non-APIC.
- */
-
- if (reg1 != reg0)
- {
- return FALSE;
- }
-
- /*
- * Check if the version looks reasonably.
- */
- reg1 = GET_APIC_VERSION(reg0);
- if (reg1 == 0x00 || reg1 == 0xff)
- {
- return FALSE;
- }
- reg1 = APICGetMaxLVT();
- if (reg1 < 0x02 || reg1 == 0xff)
- {
- return FALSE;
- }
-
- /*
- * The ID register is read/write in a real APIC.
- */
- reg0 = APICRead(APIC_ID);
- DPRINT("Getting ID: %x\n", reg0);
- APICWrite(APIC_ID, reg0 ^ APIC_ID_MASK);
- reg1 = APICRead(APIC_ID);
- DPRINT("Getting ID: %x\n", reg1);
- APICWrite(APIC_ID, reg0);
- if (reg1 != (reg0 ^ APIC_ID_MASK))
- {
- return FALSE;
- }
-
- return TRUE;
-}
-
-
-static VOID
+VOID
SetInterruptGate(ULONG index, ULONG address)
{
IDT_DESCRIPTOR *idt;
@@ -1474,302 +1003,85 @@
idt->b = 0x8e00 + (((ULONG)address)&0xffff0000);
}
-VOID KeSetCurrentIrql (KIRQL NewIrql);
-VOID HalpLowerIrql(KIRQL NewIrql);
-
-
-
-VOID
-MpsIRQTrapFrameToTrapFrame(PKIRQ_TRAPFRAME IrqTrapFrame,
- PKTRAP_FRAME TrapFrame)
-{
- TrapFrame->Gs = (USHORT)IrqTrapFrame->Gs;
- TrapFrame->Fs = (USHORT)IrqTrapFrame->Fs;
- TrapFrame->Es = (USHORT)IrqTrapFrame->Es;
- TrapFrame->Ds = (USHORT)IrqTrapFrame->Ds;
- TrapFrame->Eax = IrqTrapFrame->Eax;
- TrapFrame->Ecx = IrqTrapFrame->Ecx;
- TrapFrame->Edx = IrqTrapFrame->Edx;
- TrapFrame->Ebx = IrqTrapFrame->Ebx;
- TrapFrame->Esp = IrqTrapFrame->Esp;
- TrapFrame->Ebp = IrqTrapFrame->Ebp;
- TrapFrame->Esi = IrqTrapFrame->Esi;
- TrapFrame->Edi = IrqTrapFrame->Edi;
- TrapFrame->Eip = IrqTrapFrame->Eip;
- TrapFrame->Cs = IrqTrapFrame->Cs;
- TrapFrame->Eflags = IrqTrapFrame->Eflags;
-}
-
+#endif /* MP */
-VOID
-MpsTimerHandler(ULONG Vector, PKIRQ_TRAPFRAME Trapframe)
+VOID STDCALL
+HalInitializeProcessor(ULONG ProcessorNumber,
+ PVOID /*PLOADER_PARAMETER_BLOCK*/ LoaderBlock)
{
- KIRQL oldIrql;
+#ifdef MP
ULONG CPU;
- KTRAP_FRAME KernelTrapFrame;
-#if 0
- static ULONG Count[MAX_CPU] = {0,};
#endif
- APICWrite (APIC_TPR, 0xff & APIC_TPR_PRI);
- APICSendEOI();
-
- oldIrql = KeGetCurrentIrql ();
- KeSetCurrentIrql (PROFILE_LEVEL);
- Ki386EnableInterrupts();
+ DPRINT("HalInitializeProcessor(%x %x)\n", ProcessorNumber, LoaderBlock);
+#ifdef MP
CPU = ThisCPU();
-
-#if 0
- if ((Count[CPU] % 100) == 0)
+ if (OnlineCPUs & (1 << CPU))
{
- DPRINT1("MpsTimerHandler(), CPU = %d, irql = %d, Eip = %x\n", CPU, oldIrql,Trapframe->Eip);
+ KEBUGCHECK(0);
}
- Count[CPU]++;
-#endif
- MpsIRQTrapFrameToTrapFrame(Trapframe, &KernelTrapFrame);
- if (CPU == BootCPU)
+ if (ProcessorNumber == 0)
{
- KeUpdateSystemTime(&KernelTrapFrame, oldIrql);
+ HaliInitBSP();
}
else
{
- KeUpdateRunTime(&KernelTrapFrame, oldIrql);
- }
-
- Ki386DisableInterrupts();
- HalpLowerIrql (oldIrql);
- APICWrite (APIC_TPR, IRQL2TPR (oldIrql) & APIC_TPR_PRI);
-}
-
-VOID MpsErrorHandler(VOID)
-{
- ULONG tmp1, tmp2;
-
- APICDump();
-
- tmp1 = APICRead(APIC_ESR);
- APICWrite(APIC_ESR, 0);
- tmp2 = APICRead(APIC_ESR);
- DPRINT1("APIC error on CPU(%d) ESR(%x)(%x)\n", ThisCPU(), tmp1, tmp2);
-
- /*
- * Acknowledge the interrupt
- */
- APICSendEOI();
-
- /* Here is what the APIC error bits mean:
- * 0: Send CS error
- * 1: Receive CS error
- * 2: Send accept error
- * 3: Receive accept error
- * 4: Reserved
- * 5: Send illegal vector
- * 6: Received illegal vector
- * 7: Illegal register address
- */
- DPRINT1("APIC error on CPU(%d) ESR(%x)(%x)\n", ThisCPU(), tmp1, tmp2);
- for (;;);
-}
-
-
-VOID MpsSpuriousHandler(VOID)
-{
- DPRINT1("Spurious interrupt on CPU(%d)\n", ThisCPU());
-
- /* No need to send EOI here */
-
- APICDump();
-}
-
-
-VOID APICSetup(VOID)
-{
- ULONG CPU, tmp;
-
- CPU = ThisCPU();
-
- /*
- * Intel recommends to set DFR, LDR and TPR before enabling
- * an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel
- * document number 292116). So here it goes...
- */
+ APICSetup();
- /*
- * Put the APIC into flat delivery mode.
- * Must be "all ones" explicitly for 82489DX.
- */
- APICWrite(APIC_DFR, 0xFFFFFFFF);
+ DPRINT("CPU %d says it is now booted.\n", CPU);
+
+ APICCalibrateTimer(CPU);
+ }
- /*
- * Set up the logical destination ID.
- */
- tmp = APICRead(APIC_LDR);
- tmp &= ~APIC_LDR_MASK;
- tmp |= (1 << (CPU + 24));
- APICWrite(APIC_LDR, tmp);
-
- /* Accept all interrupts */
- tmp = APICRead(APIC_TPR) & ~APIC_TPR_PRI;
- APICWrite(APIC_TPR, tmp);
-
- /* Enable local APIC */
- tmp = APICRead(APIC_SIVR);
- tmp &= ~0xff;
- tmp |= APIC_SIVR_ENABLE;
+ /* This processor is now booted */
+ CPUMap[CPU].Flags |= CPU_ENABLED;
+ OnlineCPUs |= (1 << CPU);
-#if 1
- tmp &= ~APIC_SIVR_FOCUS;
-#else
- tmp |= APIC_SIVR_FOCUS;
+ /* Setup busy waiting */
+ HalpCalibrateStallExecution();
#endif
-
- /* Set spurious interrupt vector */
- tmp |= SPURIOUS_VECTOR;
- APICWrite(APIC_SIVR, tmp);
-
- /*
- * Set up LVT0, LVT1:
- *
- * set up through-local-APIC on the BP's LINT0. This is not
- * strictly necessery in pure symmetric-IO mode, but sometimes
- * we delegate interrupts to the 8259A.
- */
- tmp = APICRead(APIC_LINT0) & APIC_LVT_MASKED;
- if (CPU == BootCPU && (APICMode == amPIC || !tmp))
- {
- tmp = APIC_DM_EXTINT;
- DPRINT("enabled ExtINT on CPU#%d\n", CPU);
- }
- else
- {
- tmp = APIC_DM_EXTINT | APIC_LVT_MASKED;
- DPRINT("masked ExtINT on CPU#%d\n", CPU);
- }
- APICWrite(APIC_LINT0, tmp);
-
-
- /*
- * Only the BSP should see the LINT1 NMI signal, obviously.
- */
- if (CPU == BootCPU)
- {
- tmp = APIC_DM_NMI;
- }
- else
- {
- tmp = APIC_DM_NMI | APIC_LVT_MASKED;
- }
- if (!APIC_INTEGRATED(CPUMap[CPU].APICVersion))
- {
- /* 82489DX */
- tmp |= APIC_LVT_LEVEL_TRIGGER;
- }
- APICWrite(APIC_LINT1, tmp);
-
- if (APIC_INTEGRATED(CPUMap[CPU].APICVersion))
- {
- /* !82489DX */
- if (CPUMap[CPU].MaxLVT > 3)
- {
- /* Due to the Pentium erratum 3AP */
- APICWrite(APIC_ESR, 0);
- }
-
- tmp = APICRead(APIC_ESR);
- DPRINT("ESR value before enabling vector: 0x%X\n", tmp);
-
- /* Enable sending errors */
- tmp = ERROR_VECTOR;
- APICWrite(APIC_LVT3, tmp);
-
- /*
- * Spec says clear errors after enabling vector
- */
- if (CPUMap[CPU].MaxLVT > 3)
- {
- APICWrite(APIC_ESR, 0);
- }
- tmp = APICRead(APIC_ESR);
- DPRINT("ESR value after enabling vector: 0x%X\n", tmp);
- }
}
-VOID
-HaliInitBSP(VOID)
+BOOLEAN STDCALL
+HalAllProcessorsStarted (VOID)
{
- PUSHORT ps;
+ DPRINT("HalAllProcessorsStarted()\n");
- /* Only initialize the BSP once */
- if (BSPInitialized)
- {
- return;
- }
-
- BSPInitialized = TRUE;
-
- DPRINT("APIC is mapped at 0x%X\n", APICBase);
-
- if (VerifyLocalAPIC())
- {
- DPRINT("APIC found\n");
- }
- else
- {
- DPRINT1("No APIC found\n");
- KEBUGCHECK(0);
- }
-
- CPUMap[BootCPU].MaxLVT = APICGetMaxLVT();
-
- SetInterruptGate(LOCAL_TIMER_VECTOR, (ULONG)MpsTimerInterrupt);
- SetInterruptGate(ERROR_VECTOR, (ULONG)MpsErrorInterrupt);
- SetInterruptGate(SPURIOUS_VECTOR, (ULONG)MpsSpuriousInterrupt);
-
- if (APICMode == amPIC)
- {
- EnableSMPMode();
- }
-
- APICSetup();
+#ifdef MP
- /* BIOS data segment */
- BIOSBase = (PULONG)BIOS_AREA;
-
- /* Area for communicating with the APs */
- CommonBase = (PULONG)COMMON_AREA;
-
- /* Copy bootstrap code to common area */
- memcpy((PVOID)((ULONG)CommonBase + PAGE_SIZE),
- &APstart,
- (ULONG)&APend - (ULONG)&APstart + 1);
-
- /* Set shutdown code */
- CMOS_WRITE(0xF, 0xA);
-
- /* Set warm reset vector */
- ps = (PUSHORT)((ULONG)BIOSBase + 0x467);
- *ps = (COMMON_AREA + PAGE_SIZE) & 0xF;
-
- ps = (PUSHORT)((ULONG)BIOSBase + 0x469);
- *ps = (COMMON_AREA + PAGE_SIZE) >> 4;
+ ULONG CPUs = 0, i;
+ for (i = 0; i < 32; i++)
+ {
+ if (OnlineCPUs & (1 << i))
+ {
+ CPUs++;
+ }
+ }
+ if (CPUs > CPUCount)
+ {
+ KEBUGCHECK(0);
+ }
+ else if (CPUs == CPUCount)
+ {
+ IOAPICSetup();
+ return TRUE;
+ }
+ return FALSE;
- /* Calibrate APIC timer */
- APICCalibrateTimer(BootCPU);
+#else /* MP */
- /* The boot processor is online */
- OnlineCPUs = (1 << BootCPU);
-}
+ return TRUE;
#endif /* MP */
+}
-VOID STDCALL HalInitializeProcessor(ULONG ProcessorNumber,
- PVOID ProcessorStack)
+BOOLEAN STDCALL
+HalStartNextProcessor(ULONG Unknown1,
+ ULONG ProcessorStack)
{
-
#ifdef MP
-
PCOMMON_AREA_INFO Common;
ULONG StartupCount;
ULONG DeliveryStatus = 0;
@@ -1777,215 +1089,150 @@
ULONG CPU, i, j;
ULONG tmp, maxlvt;
- DPRINT("HalInitializeProcessor(%x %x)\n", ProcessorNumber, ProcessorStack);
+ DPRINT("HalStartNextProcessor(%x %x)\n", Unknown1, ProcessorStack);
- if (ProcessorNumber == 0)
+ for (CPU = 0; CPU < CPUCount; CPU++)
{
- /* Boot processor is already initialized */
- NextCPU = 1;
- return;
+ if (!(OnlineCPUs & (1<<CPU)))
+ {
+ break;
+ }
}
- if (NextCPU < CPUCount)
+ if (CPU >= CPUCount)
{
- for (CPU = 0; CPU < CPUCount; CPU++)
- {
- if (!(OnlineCPUs & (1<<CPU)))
- {
- break;
- }
- }
+ KEBUGCHECK(0);
+ }
- if (CPU >= CPUCount)
- {
- KEBUGCHECK(0);
- }
+ DPRINT1("Attempting to boot CPU %d\n", CPU);
-
- DPRINT("Attempting to boot CPU %d\n", CPU);
+ /* Send INIT IPI */
- /* Send INIT IPI */
- APICSendIPI(CPUMap[CPU].APICId, APIC_DM_INIT, 0, APIC_ICR0_LEVEL_ASSERT);
+ APICSendIPI(CPU, APIC_DM_INIT|APIC_ICR0_LEVEL_ASSERT);
- APICSleep(200);
+ KeStallExecutionProcessor(200);
- /* Deassert INIT */
- APICSendIPI(CPUMap[CPU].APICId, APIC_DM_INIT, 0, APIC_ICR0_LEVEL_DEASSERT);
+ /* Deassert INIT */
- if (APIC_INTEGRATED(CPUMap[CPU].APICVersion))
- {
- /* Clear APIC errors */
[truncated at 1000 lines; 462 more skipped]
reactos/hal/halx86
diff -u -r1.3 -r1.4
--- mps.S 1 Nov 2004 19:01:25 -0000 1.3
+++ mps.S 28 Nov 2004 01:30:01 -0000 1.4
@@ -1,4 +1,4 @@
-/* $Id: mps.S,v 1.3 2004/11/01 19:01:25 hbirr Exp $
+/* $Id: mps.S,v 1.4 2004/11/28 01:30:01 hbirr Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@@ -36,6 +36,19 @@
popl %ds; \
popa;
+.global _MpsIpiInterrupt
+_MpsIpiInterrupt:
+ /* Save registers */
+ BEFORE
+
+ /* Call the C handler */
+ call _MpsIpiHandler
+
+ /* Return to the caller */
+ AFTER
+ iret
+
+
.globl _MpsErrorInterrupt
_MpsErrorInterrupt:
/* Save registers */
reactos/hal/halx86
diff -u -r1.11 -r1.12
--- mpsirql.c 1 Nov 2004 19:01:25 -0000 1.11
+++ mpsirql.c 28 Nov 2004 01:30:01 -0000 1.12
@@ -19,6 +19,7 @@
#include <halirq.h>
#include <hal.h>
#include <mps.h>
+#include <apic.h>
#define NDEBUG
#include <internal/debug.h>
@@ -26,9 +27,6 @@
/* GLOBALS ******************************************************************/;
-VOID STDCALL
-KiInterruptDispatch2 (ULONG Irq, KIRQL old_level);
-
/* FUNCTIONS ****************************************************************/
KIRQL STDCALL KeGetCurrentIrql (VOID)
@@ -42,14 +40,16 @@
Ki386SaveFlags(Flags);
Ki386DisableInterrupts();
- irql = KeGetCurrentKPCR()->Irql;
- Ki386RestoreFlags(Flags);
+ irql = Ki386ReadFsByte(offsetof(KPCR, Irql));
if (irql > HIGH_LEVEL)
{
DPRINT1 ("CurrentIrql %x\n", irql);
KEBUGCHECK (0);
- for(;;);
+ }
+ if (Flags & X86_EFLAGS_IF)
+ {
+ Ki386EnableInterrupts();
}
return irql;
}
@@ -62,41 +62,46 @@
{
ULONG Flags;
if (NewIrql > HIGH_LEVEL)
- {
- DPRINT1 ("NewIrql %x\n", NewIrql);
- KEBUGCHECK (0);
- for(;;);
- }
+ {
+ DPRINT1 ("NewIrql %x\n", NewIrql);
+ KEBUGCHECK (0);
+ }
Ki386SaveFlags(Flags);
Ki386DisableInterrupts();
- KeGetCurrentKPCR()->Irql = NewIrql;
- Ki386RestoreFlags(Flags);
+ Ki386WriteFsByte(offsetof(KPCR, Irql), NewIrql);
+ if (Flags & X86_EFLAGS_IF)
+ {
+ Ki386EnableInterrupts();
+ }
}
-
-
-
VOID
-HalpLowerIrql(KIRQL NewIrql)
+HalpLowerIrql(KIRQL NewIrql, BOOL FromHalEndSystemInterrupt)
{
- PKPCR Pcr = KeGetCurrentKPCR();
+ ULONG Flags;
if (NewIrql >= DISPATCH_LEVEL)
{
KeSetCurrentIrql (NewIrql);
APICWrite(APIC_TPR, IRQL2TPR (NewIrql) & APIC_TPR_PRI);
return;
}
+ Ki386SaveFlags(Flags);
if (KeGetCurrentIrql() > APC_LEVEL)
- {
- KeSetCurrentIrql (DISPATCH_LEVEL);
- APICWrite(APIC_TPR, IRQL2TPR (DISPATCH_LEVEL) & APIC_TPR_PRI);
- if (Pcr->HalReserved[1])
{
- Pcr->HalReserved[1] = 0;
- KiDispatchInterrupt();
+ KeSetCurrentIrql (DISPATCH_LEVEL);
+ APICWrite(APIC_TPR, IRQL2TPR (DISPATCH_LEVEL) & APIC_TPR_PRI);
+ if (FromHalEndSystemInterrupt || Ki386ReadFsByte(offsetof(KPCR, HalReserved[HAL_DPC_REQUEST])))
+ {
+ Ki386WriteFsByte(offsetof(KPCR, HalReserved[HAL_DPC_REQUEST]), 0);
+ Ki386EnableInterrupts();
+ KiDispatchInterrupt();
+ if (!(Flags & X86_EFLAGS_IF))
+ {
+ Ki386DisableInterrupts();
+ }
+ }
+ KeSetCurrentIrql (APC_LEVEL);
}
- KeSetCurrentIrql (APC_LEVEL);
- }
if (NewIrql == APC_LEVEL)
{
return;
@@ -104,7 +109,12 @@
if (KeGetCurrentThread () != NULL &&
KeGetCurrentThread ()->ApcState.KernelApcPending)
{
- KiDeliverApc (0, 0, 0);
+ Ki386EnableInterrupts();
+ KiDeliverApc(KernelMode, NULL, NULL);
+ if (!(Flags & X86_EFLAGS_IF))
+ {
+ Ki386DisableInterrupts();
+ }
}
KeSetCurrentIrql (PASSIVE_LEVEL);
}
@@ -134,10 +144,8 @@
{
DPRINT1 ("NewIrql %x CurrentIrql %x\n", NewIrql, oldIrql);
KEBUGCHECK (0);
- for(;;);
}
-
- HalpLowerIrql (NewIrql);
+ HalpLowerIrql (NewIrql, FALSE);
}
@@ -186,22 +194,29 @@
{
KIRQL OldIrql;
ULONG Flags;
-
- if (NewIrql < KeGetCurrentIrql ())
+
+ Ki386SaveFlags(Flags);
+ Ki386DisableInterrupts();
+
+ OldIrql = KeGetCurrentIrql ();
+
+ if (NewIrql < OldIrql)
{
DPRINT1 ("CurrentIrql %x NewIrql %x\n", KeGetCurrentIrql (), NewIrql);
KEBUGCHECK (0);
- for(;;);
}
- Ki386SaveFlags(Flags);
- Ki386DisableInterrupts();
+
+
if (NewIrql > DISPATCH_LEVEL)
{
- APICWrite (APIC_TPR, IRQL2TPR (NewIrql) & APIC_TPR_PRI);
+ APICWrite (APIC_TPR, IRQL2TPR(NewIrql) & APIC_TPR_PRI);
}
- OldIrql = KeGetCurrentIrql ();
KeSetCurrentIrql (NewIrql);
- Ki386RestoreFlags(Flags);
+ if (Flags & X86_EFLAGS_IF)
+ {
+ Ki386EnableInterrupts();
+ }
+
return OldIrql;
}
@@ -286,42 +301,43 @@
{
ULONG Flags;
DPRINT("Vector (0x%X) Irql (0x%X)\n", Vector, Irql);
-
+
if (KeGetCurrentIrql () >= Irql)
- {
- DPRINT1("current irql %d, new irql %d\n", KeGetCurrentIrql(), Irql);
- KEBUGCHECK(0);
- }
-
- if (Vector < FIRST_DEVICE_VECTOR ||
- Vector >= FIRST_DEVICE_VECTOR + NUMBER_DEVICE_VECTORS)
{
- DPRINT1("Not a device interrupt, vector %x\n", Vector);
- return FALSE;
+ DPRINT1("current irql %d, new irql %d\n", KeGetCurrentIrql(), Irql);
+ KEBUGCHECK(0);
}
Ki386SaveFlags(Flags);
- Ki386DisableInterrupts();
+ if (Flags & X86_EFLAGS_IF)
+ {
+ DPRINT1("HalBeginSystemInterrupt was called with interrupt's enabled\n");
+ KEBUGCHECK(0);
+ }
APICWrite (APIC_TPR, IRQL2TPR (Irql) & APIC_TPR_PRI);
-
- APICSendEOI();
-
*OldIrql = KeGetCurrentIrql ();
KeSetCurrentIrql (Irql);
- Ki386RestoreFlags(Flags);
-
return(TRUE);
}
VOID STDCALL
HalEndSystemInterrupt (KIRQL Irql,
- ULONG Unknown2)
+ ULONG Unknown2)
/*
* FUNCTION: Finish a system interrupt and restore the specified irq level.
*/
{
- HalpLowerIrql (Irql);
+ ULONG Flags;
+ Ki386SaveFlags(Flags);
+
+ if (Flags & X86_EFLAGS_IF)
+ {
+ DPRINT1("HalEndSystemInterrupt was called with interrupt's enabled\n");
+ KEBUGCHECK(0);
+ }
+ APICSendEOI();
+ HalpLowerIrql (Irql, TRUE);
}
BOOLEAN STDCALL
@@ -369,21 +385,14 @@
VOID FASTCALL
HalRequestSoftwareInterrupt(IN KIRQL Request)
{
- ULONG Flags;
switch (Request)
{
case APC_LEVEL:
- Ki386SaveFlags(Flags);
- Ki386DisableInterrupts();
- KeGetCurrentKPCR()->HalReserved[0] = 1;
- Ki386RestoreFlags(Flags);
+ Ki386WriteFsByte(offsetof(KPCR, HalReserved[HAL_APC_REQUEST]), 1);
break;
case DISPATCH_LEVEL:
- Ki386SaveFlags(Flags);
- Ki386DisableInterrupts();
- KeGetCurrentKPCR()->HalReserved[1] = 1;
- Ki386RestoreFlags(Flags);
+ Ki386WriteFsByte(offsetof(KPCR, HalReserved[HAL_DPC_REQUEST]), 1);
break;
default:
reactos/hal/halx86
diff -u -r1.7 -r1.8
--- timer.c 14 Nov 2004 19:01:31 -0000 1.7
+++ timer.c 28 Nov 2004 01:30:01 -0000 1.8
@@ -20,7 +20,7 @@
* MA 02139, USA.
*
*/
-/* $Id: timer.c,v 1.7 2004/11/14 19:01:31 hbirr Exp $
+/* $Id: timer.c,v 1.8 2004/11/28 01:30:01 hbirr Exp $
*
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/hal/x86/udelay.c
@@ -321,11 +321,18 @@
* RETURNS: The number of performance counter ticks since boot
*/
{
- PKPCR Pcr = KeGetCurrentKPCR();
+ PKPCR Pcr;
LARGE_INTEGER Value;
+ ULONG Flags;
+
+ Ki386SaveFlags(Flags);
+ Ki386DisableInterrupts();
+
+ Pcr = KeGetCurrentKPCR();
if (Pcr->PrcbData.FeatureBits & X86_FEATURE_TSC)
{
+ Ki386RestoreFlags(Flags);
if (NULL != PerformanceFreq)
{
PerformanceFreq->QuadPart = Pcr->PrcbData.MHz * (ULONGLONG)1000000;
@@ -338,6 +345,8 @@
LARGE_INTEGER TicksNew;
ULONG CountsLeft;
+ Ki386RestoreFlags(Flags);
+
if (NULL != PerformanceFreq)
{
PerformanceFreq->QuadPart = CLOCK_TICK_RATE;
reactos/hal/halx86/include
diff -N apic.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ apic.h 28 Nov 2004 01:30:02 -0000 1.1
@@ -0,0 +1,197 @@
+/*
+ *
+ */
+
+#ifndef __INTERNAL_HAL_APIC_H
+#define __INTERNAL_HAL_APIC_H
+
+#define APIC_DEFAULT_BASE 0xFEE00000 /* Default Local APIC Base Register Address */
+
+/* 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_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_LVTT 0x0320 /* Local Vector Table (Timer) (R/W) */
+#define APIC_LVTTHMR 0x0330
+#define APIC_LVTPC 0x0340 /* Performance Counter LVT (R/W) */
+#define APIC_LINT0 0x0350 /* Local Vector Table (LINT0) (R/W) */
+#define APIC_LINT1 0x0360 /* Local Vector Table (LINT1) (R/W) */
+#define APIC_LVT3 0x0370 /* Local Vector Table (Error) (R/W) */
+#define APIC_ICRT 0x0380 /* Initial Count Register for Timer (R/W) */
+#define APIC_CCRT 0x0390 /* Current Count Register for Timer (R) */
+#define APIC_TDCR 0x03E0 /* Timer Divide Configuration Register (R/W) */
+
+#define APIC_ID_MASK (0xF << 24)
+#define GET_APIC_ID(x) (((x) & APIC_ID_MASK) >> 24)
+#define GET_APIC_LOGICAL_ID(x) (((x)>>24)&0xFF)
+#define APIC_VER_MASK 0xFF00FF
+#define GET_APIC_VERSION(x) ((x) & 0xFF)
+#define GET_APIC_MAXLVT(x) (((x) >> 16) & 0xFF)
+
+#define APIC_TPR_PRI 0xFF
+#define APIC_TPR_INT 0xF0
+#define APIC_TPR_SUB 0xF
+#define APIC_TPR_MAX 0xFF /* Maximum priority */
+#define APIC_TPR_MIN 0x20 /* Minimum priority */
+
+#define APIC_LDR_MASK (0xFF << 24)
+
+#define APIC_SIVR_ENABLE (0x1 << 8)
+#define APIC_SIVR_FOCUS (0x1 << 9)
+
+#define APIC_ESR_MASK (0xFE << 0) /* Error Mask */
+
+#define APIC_ICR0_VECTOR (0xFF << 0) /* Vector */
+#define APIC_ICR0_DM (0x7 << 8) /* Delivery Mode */
+#define APIC_ICR0_DESTM (0x1 << 11) /* Destination Mode */
+#define APIC_ICR0_DS (0x1 << 12) /* Delivery Status */
+#define APIC_ICR0_LEVEL (0x1 << 14) /* Level */
+#define APIC_ICR0_TM (0x1 << 15) /* Trigger Mode */
+#define APIC_ICR0_DESTS (0x3 << 18) /* Destination Shorthand */
+
+/* Delivery Modes */
+#define APIC_DM_FIXED (0x0 << 8)
+#define APIC_DM_LOWEST (0x1 << 8)
+#define APIC_DM_SMI (0x2 << 8)
+#define APIC_DM_REMRD (0x3 << 8)
+#define APIC_DM_NMI (0x4 << 8)
+#define APIC_DM_INIT (0x5 << 8)
+#define APIC_DM_STARTUP (0x6 << 8)
+#define APIC_DM_EXTINT (0x7 << 8)
+#define GET_APIC_DELIVERY_MODE(x) (((x) >> 8) & 0x7)
+#define SET_APIC_DELIVERY_MODE(x,y) (((x) & ~0x700) | ((y) << 8))
+
+/* Destination Shorthand values */
+#define APIC_ICR0_DESTS_FIELD (0x0 << 0)
+#define APIC_ICR0_DESTS_SELF (0x1 << 18)
+#define APIC_ICR0_DESTS_ALL (0x2 << 18)
+#define APIC_ICR0_DESTS_ALL_BUT_SELF (0x3 << 18)
+
+#define APIC_ICR0_LEVEL_DEASSERT (0x0 << 14) /* Deassert level */
+#define APIC_ICR0_LEVEL_ASSERT (0x1 << 14) /* Assert level */
+
+#define GET_APIC_DEST_FIELD(x) (((x) >> 24) & 0xFF)
+#define SET_APIC_DEST_FIELD(x) (((x) & 0xFF) << 24)
+
+#define GET_APIC_TIMER_BASE(x) (((x) >> 18) & 0x3)
+#define SET_APIC_TIMER_BASE(x) ((x) << 18)
+#define APIC_TIMER_BASE_CLKIN 0x0
+#define APIC_TIMER_BASE_TMBASE 0x1
+#define APIC_TIMER_BASE_DIV 0x2
+
+#define APIC_LVT_VECTOR (0xFF << 0) /* Vector */
+#define APIC_LVT_DS (0x1 << 12) /* Delivery Status */
+#define APIC_LVT_REMOTE_IRR (0x1 << 14) /* Remote IRR */
+#define APIC_LVT_LEVEL_TRIGGER (0x1 << 15) /* Lvel Triggered */
+#define APIC_LVT_MASKED (0x1 << 16) /* Mask */
+#define APIC_LVT_PERIODIC (0x1 << 17) /* Timer Mode */
+
+#define APIC_LVT3_DM (0x7 << 8)
+#define APIC_LVT3_IIPP (0x1 << 13)
+#define APIC_LVT3_TM (0x1 << 15)
+#define APIC_LVT3_MASKED (0x1 << 16)
+#define APIC_LVT3_OS (0x1 << 17)
+
+#define APIC_TDCR_TMBASE (0x1 << 2)
+#define APIC_TDCR_MASK 0x0F
+#define APIC_TDCR_2 0x00
+#define APIC_TDCR_4 0x01
+#define APIC_TDCR_8 0x02
+#define APIC_TDCR_16 0x03
+#define APIC_TDCR_32 0x08
+#define APIC_TDCR_64 0x09
+#define APIC_TDCR_128 0x0A
+#define APIC_TDCR_1 0x0B
+
+#define APIC_LVT_VECTOR (0xFF << 0) /* Vector */
+#define APIC_LVT_DS (0x1 << 12) /* Delivery Status */
+#define APIC_LVT_REMOTE_IRR (0x1 << 14) /* Remote IRR */
+#define APIC_LVT_LEVEL_TRIGGER (0x1 << 15) /* Lvel Triggered */
+#define APIC_LVT_MASKED (0x1 << 16) /* Mask */
+#define APIC_LVT_PERIODIC (0x1 << 17) /* Timer Mode */
+
+#define APIC_LVT3_DM (0x7 << 8)
+#define APIC_LVT3_IIPP (0x1 << 13)
+#define APIC_LVT3_TM (0x1 << 15)
+#define APIC_LVT3_MASKED (0x1 << 16)
+#define APIC_LVT3_OS (0x1 << 17)
+
+#define APIC_TDCR_TMBASE (0x1 << 2)
+#define APIC_TDCR_MASK 0x0F
+#define APIC_TDCR_2 0x00
+#define APIC_TDCR_4 0x01
+#define APIC_TDCR_8 0x02
+#define APIC_TDCR_16 0x03
+#define APIC_TDCR_32 0x08
+#define APIC_TDCR_64 0x09
+#define APIC_TDCR_128 0x0A
+#define APIC_TDCR_1 0x0B
+
+#define APIC_TARGET_SELF 0x100
+#define APIC_TARGET_ALL 0x200
+#define APIC_TARGET_ALL_BUT_SELF 0x300
+
+#define APIC_INTEGRATED(version) (version & 0xF0)
+
+#define MAX_CPU 32
+
+/*
+ * Local APIC timer IRQ vector is on a different priority level,
+ * to work around the 'lost local interrupt if more than 2 IRQ
+ * sources per level' errata.
+ */
+#define LOCAL_TIMER_VECTOR 0xEF
+
+#define IPI_VECTOR 0xFB
+#define ERROR_VECTOR 0xFE
+#define SPURIOUS_VECTOR 0xFF /* Must be 0xXF */
+
+
+typedef struct _CPU_INFO
+{
+ UCHAR Flags; /* CPU flags */
+ UCHAR APICId; /* Local APIC ID */
+ UCHAR APICVersion; /* Local APIC version */
+// UCHAR MaxLVT; /* Number of LVT registers */
+ ULONG BusSpeed; /* BUS speed */
+ ULONG CoreSpeed; /* Core speed */
+ UCHAR Padding[16-12]; /* Padding to 16-byte */
+} CPU_INFO, *PCPU_INFO;
+
+
+/* Prototypes */
+
+
+volatile inline ULONG APICRead(ULONG Offset);
+inline VOID APICWrite(ULONG Offset, ULONG Value);
+VOID APICSendIPI(ULONG Target, ULONG Mode);
+
+ULONG APICGetMaxLVT(VOID);
+VOID APICSetup(VOID);
+VOID HaliInitBSP(VOID);
+VOID APICSyncArbIDs(VOID);
+inline VOID APICSendEOI(VOID);
+
+static inline ULONG ThisCPU(VOID)
+{
+ return (APICRead(APIC_ID) & APIC_ID_MASK) >> 24;
+}
+
+
+#endif
+
+
+/* EOF */
+
reactos/hal/halx86/include
diff -u -r1.7 -r1.8
--- mps.h 21 Nov 2004 22:01:11 -0000 1.7
+++ mps.h 28 Nov 2004 01:30:02 -0000 1.8
@@ -5,134 +5,12 @@
* FIXME: This does not work if we have more than 24 IRQs (ie. more than one
* I/O APIC)
*/
-#define IRQL2VECTOR(irql) IRQ2VECTOR(PROFILE_LEVEL - (irql))
-#define IRQL2TPR(irql) (((irql) == PASSIVE_LEVEL) ? 0 : ((irql) >= CLOCK1_LEVEL ? 0xff : IRQL2VECTOR(irql)))
+#define IRQL2VECTOR(irql) (IRQ2VECTOR(PROFILE_LEVEL - (irql)))
+#define IRQL2TPR(irql) ((irql) >= IPI_LEVEL ? IPI_VECTOR : ((irql) >= PROFILE_LEVEL ? LOCAL_TIMER_VECTOR : ((irql) > DISPATCH_LEVEL ? IRQL2VECTOR(irql) : 0)))
-#define APIC_DEFAULT_BASE 0xFEE00000 /* Default Local APIC Base Register Address */
#define IOAPIC_DEFAULT_BASE 0xFEC00000 /* Default I/O APIC Base Register Address */
-/* 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_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_LVTT 0x0320 /* Local Vector Table (Timer) (R/W) */
-#define APIC_LVTPC 0x0340 /* Performance Counter LVT (R/W) */
-#define APIC_LINT0 0x0350 /* Local Vector Table (LINT0) (R/W) */
-#define APIC_LINT1 0x0360 /* Local Vector Table (LINT1) (R/W) */
-#define APIC_LVT3 0x0370 /* Local Vector Table (Error) (R/W) */
-#define APIC_ICRT 0x0380 /* Initial Count Register for Timer (R/W) */
-#define APIC_CCRT 0x0390 /* Current Count Register for Timer (R) */
-#define APIC_TDCR 0x03E0 /* Timer Divide Configuration Register (R/W) */
-
-#define APIC_ID_MASK (0xF << 24)
-#define GET_APIC_ID(x) (((x) & APIC_ID_MASK) >> 24)
-#define GET_APIC_LOGICAL_ID(x) (((x)>>24)&0xFF)
-#define APIC_VER_MASK 0xFF00FF
-#define GET_APIC_VERSION(x) ((x) & 0xFF)
-#define GET_APIC_MAXLVT(x) (((x) >> 16) & 0xFF)
-
-#define APIC_TPR_PRI 0xFF
-#define APIC_TPR_INT 0xF0
-#define APIC_TPR_SUB 0xF
-#define APIC_TPR_MAX 0xFF /* Maximum priority */
-#define APIC_TPR_MIN 0x20 /* Minimum priority */
-
-#define APIC_LDR_MASK (0xFF << 24)
-
-#define APIC_SIVR_ENABLE (0x1 << 8)
-#define APIC_SIVR_FOCUS (0x1 << 9)
-
-#define APIC_ESR_MASK (0xFE << 0) /* Error Mask */
-
-#define APIC_ICR0_VECTOR (0xFF << 0) /* Vector */
-#define APIC_ICR0_DM (0x7 << 8) /* Delivery Mode */
-#define APIC_ICR0_DESTM (0x1 << 11) /* Destination Mode */
-#define APIC_ICR0_DS (0x1 << 12) /* Delivery Status */
-#define APIC_ICR0_LEVEL (0x1 << 14) /* Level */
-#define APIC_ICR0_TM (0x1 << 15) /* Trigger Mode */
-#define APIC_ICR0_DESTS (0x3 << 18) /* Destination Shorthand */
-
-/* Delivery Modes */
-#define APIC_DM_FIXED (0x0 << 8)
-#define APIC_DM_LOWEST (0x1 << 8)
-#define APIC_DM_SMI (0x2 << 8)
-#define APIC_DM_REMRD (0x3 << 8)
-#define APIC_DM_NMI (0x4 << 8)
-#define APIC_DM_INIT (0x5 << 8)
-#define APIC_DM_STARTUP (0x6 << 8)
-#define APIC_DM_EXTINT (0x7 << 8)
-#define GET_APIC_DELIVERY_MODE(x) (((x) >> 8) & 0x7)
-#define SET_APIC_DELIVERY_MODE(x,y) (((x) & ~0x700) | ((y) << 8))
-
-/* Destination Shorthand values */
-#define APIC_ICR0_DESTS_FIELD (0x0 << 0)
-#define APIC_ICR0_DESTS_SELF (0x1 << 18)
-#define APIC_ICR0_DESTS_ALL (0x2 << 18)
-#define APIC_ICR0_DESTS_ALL_BUT_SELF (0x3 << 18)
-
-#define APIC_ICR0_LEVEL_DEASSERT (0x0 << 14) /* Deassert level */
-#define APIC_ICR0_LEVEL_ASSERT (0x1 << 14) /* Assert level */
-
-#define GET_APIC_DEST_FIELD(x) (((x) >> 24) & 0xFF)
-#define SET_APIC_DEST_FIELD(x) (((x) & 0xFF) << 24)
-
-#define GET_APIC_TIMER_BASE(x) (((x) >> 18) & 0x3)
-#define SET_APIC_TIMER_BASE(x) ((x) << 18)
-#define APIC_TIMER_BASE_CLKIN 0x0
-#define APIC_TIMER_BASE_TMBASE 0x1
-#define APIC_TIMER_BASE_DIV 0x2
-
-#define APIC_LVT_VECTOR (0xFF << 0) /* Vector */
-#define APIC_LVT_DS (0x1 << 12) /* Delivery Status */
-#define APIC_LVT_REMOTE_IRR (0x1 << 14) /* Remote IRR */
-#define APIC_LVT_LEVEL_TRIGGER (0x1 << 15) /* Lvel Triggered */
-#define APIC_LVT_MASKED (0x1 << 16) /* Mask */
-#define APIC_LVT_PERIODIC (0x1 << 17) /* Timer Mode */
-
-#define APIC_LVT3_DM (0x7 << 8)
-#define APIC_LVT3_IIPP (0x1 << 13)
-#define APIC_LVT3_TM (0x1 << 15)
-#define APIC_LVT3_MASKED (0x1 << 16)
-#define APIC_LVT3_OS (0x1 << 17)
-
-#define APIC_TDCR_TMBASE (0x1 << 2)
-#define APIC_TDCR_MASK 0x0F
-#define APIC_TDCR_2 0x00
-#define APIC_TDCR_4 0x01
-#define APIC_TDCR_8 0x02
-#define APIC_TDCR_16 0x03
-#define APIC_TDCR_32 0x08
-#define APIC_TDCR_64 0x09
-#define APIC_TDCR_128 0x0A
-#define APIC_TDCR_1 0x0B
-
-#define APIC_TARGET_SELF 0x100
-#define APIC_TARGET_ALL 0x200
-#define APIC_TARGET_ALL_BUT_SELF 0x300
-
-#define IPI_CACHE_FLUSH 0x40
-#define IPI_INV_TLB 0x41
-#define IPI_INV_PTE 0x42
-#define IPI_INV_RESCHED 0x43
-#define IPI_STOP 0x44
-
-
-#define APIC_INTEGRATED(version) (version & 0xF0)
-
-
/* I/O APIC Register Address Map */
#define IOAPIC_IOREGSEL 0x0000 /* I/O Register Select (index) (R/W) */
#define IOAPIC_IOWIN 0x0010 /* I/O window (data) (R/W) */
@@ -201,18 +79,6 @@
} IOAPIC_INFO, *PIOAPIC_INFO;
-/*
- * Local APIC timer IRQ vector is on a different priority level,
- * to work around the 'lost local interrupt if more than 2 IRQ
- * sources per level' errata.
- */
-#define LOCAL_TIMER_VECTOR 0xEF
-
-#define CALL_FUNCTION_VECTOR 0xFB
-#define RESCHEDULE_VECTOR 0xFC
-#define INVALIDATE_TLB_VECTOR 0xFD
-#define ERROR_VECTOR 0xFE
-#define SPURIOUS_VECTOR 0xFF /* Must be 0xXF */
#if 0
/* This values are defined in halirql.h */
@@ -395,20 +261,8 @@
}
-#define MAX_CPU 32
-typedef struct _CPU_INFO
-{
- UCHAR Flags; /* CPU flags */
- UCHAR APICId; /* Local APIC ID */
- UCHAR APICVersion; /* Local APIC version */
- UCHAR MaxLVT; /* Number of LVT registers */
- ULONG BusSpeed; /* BUS speed */
- ULONG CoreSpeed; /* Core speed */
- UCHAR Padding[16-12]; /* Padding to 16-byte */
-} CPU_INFO, *PCPU_INFO;
-
/* CPU flags */
#define CPU_USABLE 0x01 /* 1 if the CPU is usable (ie. can be used) */
#define CPU_ENABLED 0x02 /* 1 if the CPU is enabled */
@@ -430,17 +284,9 @@
VOID IOAPICWrite(ULONG Apic, ULONG Offset, ULONG Value);
VOID IOAPICMaskIrq(ULONG Irq);
VOID IOAPICUnmaskIrq(ULONG Irq);
-volatile inline ULONG APICRead(ULONG Offset);
-inline VOID APICWrite(ULONG Offset, ULONG Value);
-inline VOID APICSendEOI(VOID);
-inline ULONG ThisCPU(VOID);
-VOID APICSendIPI(ULONG Target,
- ULONG DeliveryMode,
- ULONG IntNum,
- ULONG Level);
+
/* For debugging */
VOID IOAPICDump(VOID);
-VOID APICDump(VOID);
#endif /* __INCLUDE_HAL_MPS */
CVSspam 0.2.8