Split some of the halmp files according its functions.

svn path=/trunk/; revision=13868
This commit is contained in:
Hartmut Birr 2005-03-07 16:40:32 +00:00
parent 63981fc041
commit 8399d9c123
12 changed files with 1917 additions and 1908 deletions

View file

@ -165,7 +165,7 @@ static ULONG Read8254Timer(VOID)
}
static VOID WaitFor8254Wraparound(VOID)
VOID WaitFor8254Wraparound(VOID)
{
ULONG CurCount, PrevCount = ~0;
LONG Delta;

View file

@ -145,7 +145,16 @@
#define APIC_INTEGRATED(version) (version & 0xF0)
typedef enum {
amPIC = 0, /* IMCR and PIC compatibility mode */
amVWIRE /* Virtual Wire compatibility mode */
} APIC_MODE;
#ifdef CONFIG_SMP
#define MAX_CPU 32
#else
#define MAX_CPU 1
#endif
/*
* Local APIC timer IRQ vector is on a different priority level,
@ -158,6 +167,11 @@
#define ERROR_VECTOR 0xFE
#define SPURIOUS_VECTOR 0xFF /* Must be 0xXF */
/* 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 */
#define CPU_BSP 0x04 /* 1 if the CPU is the bootstrap processor */
#define CPU_TSC 0x08 /* 1 if the CPU has a time stamp counter */
typedef struct _CPU_INFO
{
@ -170,23 +184,26 @@ typedef struct _CPU_INFO
UCHAR Padding[16-12]; /* Padding to 16-byte */
} CPU_INFO, *PCPU_INFO;
extern ULONG CPUCount; /* Total number of CPUs */
extern ULONG BootCPU; /* Bootstrap processor */
extern ULONG OnlineCPUs; /* Bitmask of online CPUs */
extern CPU_INFO CPUMap[MAX_CPU]; /* Map of all CPUs in the system */
/* Prototypes */
inline ULONG APICRead(ULONG Offset);
inline VOID APICWrite(ULONG Offset, ULONG Value);
inline ULONG APICRead(ULONG Offset);
VOID APICSendIPI(ULONG Target, ULONG Mode);
ULONG APICGetMaxLVT(VOID);
VOID APICSetup(VOID);
VOID HaliInitBSP(VOID);
VOID APICSyncArbIDs(VOID);
inline VOID APICSendEOI(VOID);
VOID APICCalibrateTimer(ULONG CPU);
VOID HaliStartApplicationProcessor(ULONG Cpu, ULONG Stack);
static inline ULONG ThisCPU(VOID)
{
return (APICRead(APIC_ID) & APIC_ID_MASK) >> 24;
return (APICRead(APIC_ID) & APIC_ID_MASK) >> 24;
}

View file

@ -413,6 +413,8 @@ HalQueryDisplayOwnership();
#define Ki386EnableInterrupts() __asm__ __volatile__("sti\n\t")
#define Ki386HaltProcessor() __asm__ __volatile__("hlt\n\t")
#define Ki386RdTSC(x) __asm__ __volatile__("rdtsc\n\t" : "=A" (x.u.LowPart), "=d" (x.u.HighPart));
#define Ki386Rdmsr(msr,val1,val2) __asm__ __volatile__("rdmsr" : "=a" (val1), "=d" (val2) : "c" (msr))
#define Ki386Wrmsr(msr,val1,val2) __asm__ __volatile__("wrmsr" : /* no outputs */ : "c" (msr), "a" (val1), "d" (val2))
static inline BYTE Ki386ReadFsByte(ULONG offset)
{

View file

@ -0,0 +1,101 @@
/*
*
*/
#ifndef __INTERNAL_HAL_IOAPIC_H
#define __INTERNAL_HAL_IOAPIC_H
/* 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) */
#define IOAPIC_ID 0x0000 /* IO APIC ID (R/W) */
#define IOAPIC_VER 0x0001 /* IO APIC Version (R) */
#define IOAPIC_ARB 0x0002 /* IO APIC Arbitration ID (R) */
#define IOAPIC_REDTBL 0x0010 /* Redirection Table (0-23 64-bit registers) (R/W) */
#define IOAPIC_ID_MASK (0xF << 24)
#define GET_IOAPIC_ID(x) (((x) & IOAPIC_ID_MASK) >> 24)
#define SET_IOAPIC_ID(x) ((x) << 24)
#define IOAPIC_VER_MASK (0xFF)
#define GET_IOAPIC_VERSION(x) (((x) & IOAPIC_VER_MASK))
#define IOAPIC_MRE_MASK (0xFF << 16) /* Maximum Redirection Entry */
#define GET_IOAPIC_MRE(x) (((x) & IOAPIC_MRE_MASK) >> 16)
#define IOAPIC_ARB_MASK (0xF << 24)
#define GET_IOAPIC_ARB(x) (((x) & IOAPIC_ARB_MASK) >> 24)
#define IOAPIC_TBL_DELMOD (0x7 << 10) /* Delivery Mode (see APIC_DM_*) */
#define IOAPIC_TBL_DM (0x1 << 11) /* Destination Mode */
#define IOAPIC_TBL_DS (0x1 << 12) /* Delivery Status */
#define IOAPIC_TBL_INTPOL (0x1 << 13) /* Interrupt Input Pin Polarity */
#define IOAPIC_TBL_RIRR (0x1 << 14) /* Remote IRR */
#define IOAPIC_TBL_TM (0x1 << 15) /* Trigger Mode */
#define IOAPIC_TBL_IM (0x1 << 16) /* Interrupt Mask */
#define IOAPIC_TBL_DF0 (0xF << 56) /* Destination Field (physical mode) */
#define IOAPIC_TBL_DF1 (0xFF<< 56) /* Destination Field (logical mode) */
#define IOAPIC_TBL_VECTOR (0xFF << 0) /* Vector (10h - FEh) */
typedef struct _IOAPIC_ROUTE_ENTRY {
ULONG vector : 8,
delivery_mode : 3, /* 000: FIXED
* 001: lowest priority
* 111: ExtINT
*/
dest_mode : 1, /* 0: physical, 1: logical */
delivery_status : 1,
polarity : 1,
irr : 1,
trigger : 1, /* 0: edge, 1: level */
mask : 1, /* 0: enabled, 1: disabled */
__reserved_2 : 15;
union {
struct {
ULONG __reserved_1 : 24,
physical_dest : 4,
__reserved_2 : 4;
} physical;
struct {
ULONG __reserved_1 : 24,
logical_dest : 8;
} logical;
} dest;
} __attribute__ ((packed)) IOAPIC_ROUTE_ENTRY, *PIOAPIC_ROUTE_ENTRY;
typedef struct _IOAPIC_INFO
{
ULONG ApicId; /* APIC ID */
ULONG ApicVersion; /* APIC version */
ULONG ApicAddress; /* APIC address */
ULONG EntryCount; /* Number of redirection entries */
} IOAPIC_INFO, *PIOAPIC_INFO;
#define IOAPIC_DEFAULT_BASE 0xFEC00000 /* Default I/O APIC Base Register Address */
extern ULONG IRQCount; /* Number of IRQs */
extern UCHAR BUSMap[MAX_BUS]; /* Map of all buses in the system */
extern UCHAR PCIBUSMap[MAX_BUS]; /* Map of all PCI buses in the system */
extern IOAPIC_INFO IOAPICMap[MAX_IOAPIC]; /* Map of all I/O APICs in the system */
extern ULONG IOAPICCount; /* Number of I/O APICs in the system */
extern ULONG APICMode; /* APIC mode at startup */
extern MP_CONFIGURATION_INTSRC IRQMap[MAX_IRQ_SOURCE]; /* Map of all IRQs */
VOID IOAPICSetupIrqs(VOID);
VOID IOAPICEnable(VOID);
VOID IOAPICSetupIds(VOID);
VOID IOAPICMaskIrq(ULONG Irq);
VOID IOAPICUnmaskIrq(ULONG Irq);
VOID HaliReconfigurePciInterrupts(VOID);
/* For debugging */
VOID IOAPICDump(VOID);
#endif
/* EOF */

View file

@ -9,76 +9,6 @@
#define IRQL2TPR(irql) ((irql) >= IPI_LEVEL ? IPI_VECTOR : ((irql) >= PROFILE_LEVEL ? LOCAL_TIMER_VECTOR : ((irql) > DISPATCH_LEVEL ? IRQL2VECTOR(irql) : 0)))
#define IOAPIC_DEFAULT_BASE 0xFEC00000 /* Default I/O APIC Base Register Address */
/* 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) */
#define IOAPIC_ID 0x0000 /* IO APIC ID (R/W) */
#define IOAPIC_VER 0x0001 /* IO APIC Version (R) */
#define IOAPIC_ARB 0x0002 /* IO APIC Arbitration ID (R) */
#define IOAPIC_REDTBL 0x0010 /* Redirection Table (0-23 64-bit registers) (R/W) */
#define IOAPIC_ID_MASK (0xF << 24)
#define GET_IOAPIC_ID(x) (((x) & IOAPIC_ID_MASK) >> 24)
#define SET_IOAPIC_ID(x) ((x) << 24)
#define IOAPIC_VER_MASK (0xFF)
#define GET_IOAPIC_VERSION(x) (((x) & IOAPIC_VER_MASK))
#define IOAPIC_MRE_MASK (0xFF << 16) /* Maximum Redirection Entry */
#define GET_IOAPIC_MRE(x) (((x) & IOAPIC_MRE_MASK) >> 16)
#define IOAPIC_ARB_MASK (0xF << 24)
#define GET_IOAPIC_ARB(x) (((x) & IOAPIC_ARB_MASK) >> 24)
#define IOAPIC_TBL_DELMOD (0x7 << 10) /* Delivery Mode (see APIC_DM_*) */
#define IOAPIC_TBL_DM (0x1 << 11) /* Destination Mode */
#define IOAPIC_TBL_DS (0x1 << 12) /* Delivery Status */
#define IOAPIC_TBL_INTPOL (0x1 << 13) /* Interrupt Input Pin Polarity */
#define IOAPIC_TBL_RIRR (0x1 << 14) /* Remote IRR */
#define IOAPIC_TBL_TM (0x1 << 15) /* Trigger Mode */
#define IOAPIC_TBL_IM (0x1 << 16) /* Interrupt Mask */
#define IOAPIC_TBL_DF0 (0xF << 56) /* Destination Field (physical mode) */
#define IOAPIC_TBL_DF1 (0xFF<< 56) /* Destination Field (logical mode) */
#define IOAPIC_TBL_VECTOR (0xFF << 0) /* Vector (10h - FEh) */
typedef struct _IOAPIC_ROUTE_ENTRY {
ULONG vector : 8,
delivery_mode : 3, /* 000: FIXED
* 001: lowest priority
* 111: ExtINT
*/
dest_mode : 1, /* 0: physical, 1: logical */
delivery_status : 1,
polarity : 1,
irr : 1,
trigger : 1, /* 0: edge, 1: level */
mask : 1, /* 0: enabled, 1: disabled */
__reserved_2 : 15;
union { struct { ULONG
__reserved_1 : 24,
physical_dest : 4,
__reserved_2 : 4;
} physical;
struct { ULONG
__reserved_1 : 24,
logical_dest : 8;
} logical;
} dest;
} __attribute__ ((packed)) IOAPIC_ROUTE_ENTRY, *PIOAPIC_ROUTE_ENTRY;
typedef struct _IOAPIC_INFO
{
ULONG ApicId; /* APIC ID */
ULONG ApicVersion; /* APIC version */
ULONG ApicAddress; /* APIC address */
ULONG EntryCount; /* Number of redirection entries */
} IOAPIC_INFO, *PIOAPIC_INFO;
#if 0
/* This values are defined in halirql.h */
@ -148,12 +78,6 @@ typedef struct __attribute__((packed)) _MP_CONFIGURATION_PROCESSOR
} __attribute__((packed)) MP_CONFIGURATION_PROCESSOR,
*PMP_CONFIGURATION_PROCESSOR;
#define CPU_FLAG_ENABLED 1 /* Processor is available */
#define CPU_FLAG_BSP 2 /* Processor is the bootstrap processor */
#define CPU_STEPPING_MASK 0x0F
#define CPU_MODEL_MASK 0xF0
#define CPU_FAMILY_MASK 0xF00
typedef struct __attribute__((packed)) _MP_CONFIGURATION_BUS
@ -239,54 +163,20 @@ typedef struct __attribute__((packed)) _MP_CONFIGURATION_INTLOCAL
} MP_CONFIGURATION_INTLOCAL, *PMP_CONFIGURATION_INTLOCAL;
#define MP_APIC_ALL 0xFF
static inline VOID ReadPentiumClock(PULARGE_INTEGER Count)
{
register ULONG nLow;
register ULONG nHigh;
#if defined(__GNUC__)
__asm__ __volatile__ ("rdtsc" : "=a" (nLow), "=d" (nHigh));
#elif defined(_MSC_VER)
__asm rdtsc
__asm mov nLow, eax
__asm mov nHigh, edx
#else
#error Unknown compiler for inline assembler
#endif
Count->u.LowPart = nLow;
Count->u.HighPart = nHigh;
}
/* 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 */
#define CPU_BSP 0x04 /* 1 if the CPU is the bootstrap processor */
typedef enum {
amPIC = 0, /* IMCR and PIC compatibility mode */
amVWIRE /* Virtual Wire compatibility mode */
} APIC_MODE;
#define CPU_FLAG_ENABLED 1 /* Processor is available */
#define CPU_FLAG_BSP 2 /* Processor is the bootstrap processor */
#define CPU_STEPPING_MASK 0x0F
#define CPU_MODEL_MASK 0xF0
#define CPU_FAMILY_MASK 0xF00
#define PIC_IRQS 16
/* Prototypes */
VOID HalpInitMPS(VOID);
ULONG IOAPICRead(ULONG Apic, ULONG Offset);
VOID IOAPICWrite(ULONG Apic, ULONG Offset, ULONG Value);
VOID IOAPICMaskIrq(ULONG Irq);
VOID IOAPICUnmaskIrq(ULONG Irq);
/* For debugging */
VOID IOAPICDump(VOID);
#endif /* __INCLUDE_HAL_MPS */

View file

@ -61,7 +61,9 @@ GENERIC_OBJECTS = \
MP_OBJECTS = \
apic.o \
halinit_mp.o \
ioapic.o \
ipi_mp.o \
mpconfig.o \
mpsirql.o \
mpsboot.o \
mps.o \

View file

@ -1,6 +1,6 @@
/*
* ReactOS kernel
* Copyright (C) 2004 ReactOS Team
* Copyright (C) 2004, 2005 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
@ -25,6 +25,8 @@
* PROGRAMMER:
*/
/* INCLUDE ***********************************************************************/
#include <ddk/ntddk.h>
#include <internal/i386/ps.h>
@ -36,22 +38,46 @@
#define NDEBUG
#include <internal/debug.h>
BOOLEAN VerifyLocalAPIC(VOID);
VOID APICCalibrateTimer(ULONG CPU);
/* GLOBALS ***********************************************************************/
extern VOID MpsTimerInterrupt(VOID);
extern VOID MpsErrorInterrupt(VOID);
extern VOID MpsSpuriousInterrupt(VOID);
extern VOID MpsIpiInterrupt(VOID);
ULONG CPUCount; /* Total number of CPUs */
ULONG BootCPU; /* Bootstrap processor */
ULONG OnlineCPUs; /* Bitmask of online CPUs */
CPU_INFO CPUMap[MAX_CPU]; /* Map of all CPUs in the system */
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 */
#ifdef CONFIG_SMP
PULONG BIOSBase; /* Virtual address of BIOS data segment */
PULONG CommonBase; /* Virtual address of common area */
#endif
extern CHAR *APstart, *APend;
extern VOID (*APflush)(VOID);
PULONG APICBase = (PULONG)APIC_DEFAULT_BASE; /* Virtual address of local APIC */
ULONG APICMode; /* APIC mode at startup */
/* For debugging */
ULONG lastregr[MAX_CPU];
ULONG lastvalr[MAX_CPU];
ULONG lastregw[MAX_CPU];
ULONG lastvalw[MAX_CPU];
#ifdef CONFIG_SMP
typedef struct __attribute__((packed)) _COMMON_AREA_INFO
{
ULONG Stack; /* Location of AP stack */
ULONG PageDirectory; /* Page directory for an AP */
ULONG NtProcessStartup; /* Kernel entry point for an AP */
ULONG PaeModeEnabled; /* PAE mode is enabled */
ULONG Debug[16]; /* For debugging */
} COMMON_AREA_INFO, *PCOMMON_AREA_INFO;
#endif
CHAR *APstart, *APend;
#define BIOS_AREA 0x0
#define COMMON_AREA 0x2000
#define HZ (100)
#define APIC_DIVISOR (16)
#define CMOS_READ(address) ({ \
WRITE_PORT_UCHAR((PUCHAR)0x70, address)); \
@ -63,19 +89,16 @@ extern VOID (*APflush)(VOID);
WRITE_PORT_UCHAR((PUCHAR)0x71, value); \
})
#define BIOS_AREA 0x0
#define COMMON_AREA 0x2000
extern PVOID IMPORTED MmSystemRangeStart;
/* FUNCTIONS *********************************************************************/
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];
extern ULONG Read8254Timer(VOID);
extern VOID WaitFor8254Wraparound(VOID);
extern VOID MpsTimerInterrupt(VOID);
extern VOID MpsErrorInterrupt(VOID);
extern VOID MpsSpuriousInterrupt(VOID);
extern VOID MpsIpiInterrupt(VOID);
ULONG APICGetMaxLVT(VOID)
{
@ -152,7 +175,7 @@ VOID APICClear(VOID)
}
/* Enable symetric I/O mode ie. connect the BSP's local APIC to INT and NMI lines */
VOID EnableSMPMode(VOID)
VOID EnableApicMode(VOID)
{
/*
* Do not trust the local APIC being empty at bootup.
@ -203,63 +226,6 @@ VOID APICDisable(VOID)
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);
}
inline ULONG _APICRead(ULONG Offset)
{
@ -455,7 +421,6 @@ VOID APICDump(VOID)
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);
@ -502,9 +467,23 @@ BOOLEAN VerifyLocalAPIC(VOID)
return FALSE;
}
ULONG l, h;
Ki386Rdmsr(0x1b /*MSR_IA32_APICBASE*/, l, h);
if (!(l & /*MSR_IA32_APICBASE_ENABLE*/(1<<11)))
{
DPRINT1("Local APIC disabled by BIOS -- reenabling.\n");
l &= ~/*MSR_IA32_APICBASE_BASE*/(1<<11);
l |= /*MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE*/(1<<11)|0xfee00000;
Ki386Wrmsr(0x1b/*MSR_IA32_APICBASE*/, l, h);
}
return TRUE;
}
#ifdef CONFIG_SMP
VOID APICSendIPI(ULONG Target, ULONG Mode)
{
ULONG tmp, i, flags;
@ -568,6 +547,7 @@ VOID APICSendIPI(ULONG Target, ULONG Mode)
}
Ki386RestoreFlags(flags);
}
#endif
VOID APICSetup(VOID)
{
@ -651,7 +631,6 @@ VOID APICSetup(VOID)
}
APICWrite(APIC_LINT0, tmp);
/*
* Only the BSP should see the LINT1 NMI signal, obviously.
*/
@ -697,7 +676,7 @@ VOID APICSetup(VOID)
DPRINT("ESR value after enabling vector: 0x%X\n", tmp);
}
}
#ifdef CONFIG_SMP
VOID APICSyncArbIDs(VOID)
{
ULONG i, tmp;
@ -720,6 +699,7 @@ VOID APICSyncArbIDs(VOID)
DPRINT("Synchronizing Arb IDs.\n");
APICWrite(APIC_ICR0, APIC_ICR0_DESTS_ALL | APIC_ICR0_LEVEL | APIC_DM_INIT);
}
#endif
VOID MpsErrorHandler(VOID)
{
@ -769,12 +749,13 @@ VOID MpsSpuriousHandler(VOID)
#endif
}
#ifdef CONFIG_SMP
VOID MpsIpiHandler(VOID)
{
KIRQL oldIrql;
HalBeginSystemInterrupt(IPI_VECTOR,
VECTOR2IRQL(IPI_VECTOR),
IPI_LEVEL,
&oldIrql);
Ki386EnableInterrupts();
#if 0
@ -791,6 +772,7 @@ VOID MpsIpiHandler(VOID)
Ki386DisableInterrupts();
HalEndSystemInterrupt(oldIrql, 0);
}
#endif
VOID
MpsIRQTrapFrameToTrapFrame(PKIRQ_TRAPFRAME IrqTrapFrame,
@ -823,7 +805,7 @@ MpsTimerHandler(ULONG Vector, PKIRQ_TRAPFRAME Trapframe)
static ULONG Count[MAX_CPU] = {0,};
#endif
HalBeginSystemInterrupt(LOCAL_TIMER_VECTOR,
VECTOR2IRQL(LOCAL_TIMER_VECTOR),
PROFILE_LEVEL,
&oldIrql);
Ki386EnableInterrupts();
@ -850,4 +832,318 @@ MpsTimerHandler(ULONG Vector, PKIRQ_TRAPFRAME Trapframe)
HalEndSystemInterrupt (oldIrql, 0);
}
VOID APICSetupLVTT(ULONG ClockTicks)
{
ULONG tmp;
tmp = GET_APIC_VERSION(APICRead(APIC_VER));
if (!APIC_INTEGRATED(tmp))
{
tmp = SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV) | APIC_LVT_PERIODIC | LOCAL_TIMER_VECTOR;;
}
else
{
/* Periodic timer */
tmp = APIC_LVT_PERIODIC | LOCAL_TIMER_VECTOR;;
}
APICWrite(APIC_LVTT, tmp);
tmp = APICRead(APIC_TDCR);
tmp &= ~(APIC_TDCR_1 | APIC_TIMER_BASE_DIV);
tmp |= APIC_TDCR_16;
APICWrite(APIC_TDCR, tmp);
APICWrite(APIC_ICRT, ClockTicks / APIC_DIVISOR);
}
VOID
APICCalibrateTimer(ULONG CPU)
{
ULARGE_INTEGER t1, t2;
LONG tt1, tt2;
BOOLEAN TSCPresent;
DPRINT("Calibrating APIC timer for CPU %d\n", CPU);
APICSetupLVTT(1000000000);
TSCPresent = KeGetCurrentKPCR()->PrcbData.FeatureBits & X86_FEATURE_TSC ? TRUE : FALSE;
/*
* The timer chip counts down to zero. Let's wait
* for a wraparound to start exact measurement:
* (the current tick might have been already half done)
*/
WaitFor8254Wraparound();
/*
* We wrapped around just now. Let's start
*/
if (TSCPresent)
{
Ki386RdTSC(t1);
}
tt1 = APICRead(APIC_CCRT);
WaitFor8254Wraparound();
tt2 = APICRead(APIC_CCRT);
if (TSCPresent)
{
Ki386RdTSC(t2);
CPUMap[CPU].CoreSpeed = (HZ * (t2.QuadPart - t1.QuadPart));
DPRINT("CPU clock speed is %ld.%04ld MHz.\n",
CPUMap[CPU].CoreSpeed/1000000,
CPUMap[CPU].CoreSpeed%1000000);
KeGetCurrentKPCR()->PrcbData.MHz = CPUMap[CPU].CoreSpeed/1000000;
}
CPUMap[CPU].BusSpeed = (HZ * (long)(tt1 - tt2) * APIC_DIVISOR);
/* Setup timer for normal operation */
// APICSetupLVTT((CPUMap[CPU].BusSpeed / 1000000) * 100); // 100ns
APICSetupLVTT((CPUMap[CPU].BusSpeed / 1000000) * 10000); // 10ms
// APICSetupLVTT((CPUMap[CPU].BusSpeed / 1000000) * 100000); // 100ms
DPRINT("Host bus clock speed is %ld.%04ld MHz.\n",
CPUMap[CPU].BusSpeed/1000000,
CPUMap[CPU].BusSpeed%1000000);
}
VOID
SetInterruptGate(ULONG index, ULONG address)
{
IDT_DESCRIPTOR *idt;
idt = (IDT_DESCRIPTOR*)((ULONG)KeGetCurrentKPCR()->IDT + index * sizeof(IDT_DESCRIPTOR));
idt->a = (((ULONG)address)&0xffff) + (KERNEL_CS << 16);
idt->b = 0x8e00 + (((ULONG)address)&0xffff0000);
}
VOID HaliInitBSP(VOID)
{
#ifdef CONFIG_SMP
PUSHORT ps;
#endif
static BOOLEAN BSPInitialized = FALSE;
/* Only initialize the BSP once */
if (BSPInitialized)
{
KEBUGCHECK(0);
return;
}
BSPInitialized = TRUE;
/* Setup interrupt handlers */
SetInterruptGate(LOCAL_TIMER_VECTOR, (ULONG)MpsTimerInterrupt);
SetInterruptGate(ERROR_VECTOR, (ULONG)MpsErrorInterrupt);
SetInterruptGate(SPURIOUS_VECTOR, (ULONG)MpsSpuriousInterrupt);
#ifdef CONFIG_SMP
SetInterruptGate(IPI_VECTOR, (ULONG)MpsIpiInterrupt);
#endif
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)
{
EnableApicMode();
}
APICSetup();
#ifdef CONFIG_SMP
/* 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;
#endif
/* Calibrate APIC timer */
APICCalibrateTimer(BootCPU);
}
#ifdef CONFIG_SMP
VOID
HaliStartApplicationProcessor(ULONG Cpu, ULONG Stack)
{
ULONG tmp, maxlvt;
PCOMMON_AREA_INFO Common;
ULONG StartupCount;
ULONG i, j;
ULONG DeliveryStatus = 0;
ULONG AcceptStatus = 0;
if (Cpu >= MAX_CPU ||
Cpu >= CPUCount ||
OnlineCPUs & (1 << Cpu))
{
KEBUGCHECK(0);
}
DPRINT1("Attempting to boot CPU %d\n", Cpu);
/* Send INIT IPI */
APICSendIPI(Cpu, APIC_DM_INIT|APIC_ICR0_LEVEL_ASSERT);
KeStallExecutionProcessor(200);
/* Deassert INIT */
APICSendIPI(Cpu, APIC_DM_INIT|APIC_ICR0_LEVEL_DEASSERT);
if (APIC_INTEGRATED(CPUMap[Cpu].APICVersion))
{
/* Clear APIC errors */
APICWrite(APIC_ESR, 0);
tmp = (APICRead(APIC_ESR) & APIC_ESR_MASK);
}
Common = (PCOMMON_AREA_INFO)CommonBase;
/* Write the location of the AP stack */
Common->Stack = (ULONG)Stack;
/* Write the page directory page */
Ke386GetPageTableDirectory(Common->PageDirectory);
/* Write the kernel entry point */
Common->NtProcessStartup = (ULONG_PTR)RtlImageNtHeader(MmSystemRangeStart)->OptionalHeader.AddressOfEntryPoint + (ULONG_PTR)MmSystemRangeStart;
/* Write the state of the mae mode */
Common->PaeModeEnabled = Ke386GetCr4() & X86_CR4_PAE ? 1 : 0;
DPRINT1("%x %x %x %x\n", Common->Stack, Common->PageDirectory, Common->NtProcessStartup, Common->PaeModeEnabled);
DPRINT("Cpu %d got stack at 0x%X\n", Cpu, Common->Stack);
#if 0
for (j = 0; j < 16; j++)
{
Common->Debug[j] = 0;
}
#endif
maxlvt = APICGetMaxLVT();
/* Is this a local APIC or an 82489DX? */
StartupCount = (APIC_INTEGRATED(CPUMap[Cpu].APICVersion)) ? 2 : 0;
for (i = 1; i <= StartupCount; i++)
{
/* It's a local APIC, so send STARTUP IPI */
DPRINT("Sending startup signal %d\n", i);
/* Clear errors */
APICWrite(APIC_ESR, 0);
APICRead(APIC_ESR);
APICSendIPI(Cpu, APIC_DM_STARTUP | ((COMMON_AREA + PAGE_SIZE) >> 12)|APIC_ICR0_LEVEL_DEASSERT);
/* Wait up to 10ms for IPI to be delivered */
j = 0;
do
{
KeStallExecutionProcessor(10);
/* Check Delivery Status */
DeliveryStatus = APICRead(APIC_ICR0) & APIC_ICR0_DS;
j++;
} while ((DeliveryStatus) && (j < 1000));
KeStallExecutionProcessor(200);
/*
* Due to the Pentium erratum 3AP.
*/
if (maxlvt > 3)
{
APICRead(APIC_SIVR);
APICWrite(APIC_ESR, 0);
}
AcceptStatus = APICRead(APIC_ESR) & APIC_ESR_MASK;
if (DeliveryStatus || AcceptStatus)
{
break;
}
}
if (DeliveryStatus)
{
DPRINT("STARTUP IPI for CPU %d was never delivered.\n", Cpu);
}
if (AcceptStatus)
{
DPRINT("STARTUP IPI for CPU %d was never accepted.\n", Cpu);
}
if (!(DeliveryStatus || AcceptStatus))
{
/* Wait no more than 5 seconds for processor to boot */
DPRINT("Waiting for 5 seconds for CPU %d to boot\n", Cpu);
/* Wait no more than 5 seconds */
for (j = 0; j < 50000; j++)
{
if (CPUMap[Cpu].Flags & CPU_ENABLED)
{
break;
}
KeStallExecutionProcessor(100);
}
}
if (CPUMap[Cpu].Flags & CPU_ENABLED)
{
DbgPrint("CPU %d is now running\n", Cpu);
}
else
{
DbgPrint("Initialization of CPU %d failed\n", Cpu);
}
#if 0
DPRINT("Debug bytes are:\n");
for (j = 0; j < 4; j++)
{
DPRINT("0x%08X 0x%08X 0x%08X 0x%08X.\n",
Common->Debug[j*4+0],
Common->Debug[j*4+1],
Common->Debug[j*4+2],
Common->Debug[j*4+3]);
}
#endif
}
#endif
/* EOF */

View file

@ -20,10 +20,34 @@
/* FUNCTIONS ***************************************************************/
extern BOOLEAN HaliFindSmpConfig(VOID);
/***************************************************************************/
VOID
HalpInitPhase0(VOID)
{
HalpInitMPS();
static BOOLEAN MPSInitialized = FALSE;
/* Only initialize MP system once. Once called the first time,
each subsequent call is part of the initialization sequence
for an application processor. */
DPRINT("HalpInitPhase0()\n");
if (MPSInitialized)
{
KEBUGCHECK(0);
}
MPSInitialized = TRUE;
if (!HaliFindSmpConfig())
{
KEBUGCHECK(0);
}
}
/* EOF */

View file

@ -0,0 +1,712 @@
/* $Id$
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: hal/halx86/generic/ioapic.c
* PURPOSE:
* PROGRAMMER:
*/
/* INCLUDES *****************************************************************/
#include <ddk/ntddk.h>
#include <hal.h>
#include <mps.h>
#include <halirq.h>
#include <apic.h>
#include <ioapic.h>
#include <internal/ntoskrnl.h>
#include <internal/i386/segment.h>
#include <internal/ke.h>
#include <internal/ps.h>
#define NDEBUG
#include <internal/debug.h>
/* GLOBALS *****************************************************************/
MP_CONFIGURATION_INTSRC IRQMap[MAX_IRQ_SOURCE]; /* Map of all IRQs */
ULONG IRQCount = 0; /* Number of IRQs */
ULONG IrqApicMap[MAX_IRQ_SOURCE];
UCHAR BUSMap[MAX_BUS]; /* Map of all buses in the system */
UCHAR PCIBUSMap[MAX_BUS]; /* Map of all PCI buses in the system */
IOAPIC_INFO IOAPICMap[MAX_IOAPIC]; /* Map of all I/O APICs in the system */
ULONG IOAPICCount; /* Number of I/O APICs in the system */
ULONG IRQVectorMap[MAX_IRQ_SOURCE]; /* IRQ to vector map */
/* EISA interrupts are always polarity zero and can be edge or level
* trigger depending on the ELCR value. If an interrupt is listed as
* EISA conforming in the MP table, that means its trigger type must
* be read in from the ELCR */
#define default_EISA_trigger(idx) (EISA_ELCR(IRQMap[idx].SrcBusIrq))
#define default_EISA_polarity(idx) (0)
/* ISA interrupts are always polarity zero edge triggered,
* when listed as conforming in the MP table. */
#define default_ISA_trigger(idx) (0)
#define default_ISA_polarity(idx) (0)
/* PCI interrupts are always polarity one level triggered,
* when listed as conforming in the MP table. */
#define default_PCI_trigger(idx) (1)
#define default_PCI_polarity(idx) (1)
/* MCA interrupts are always polarity zero level triggered,
* when listed as conforming in the MP table. */
#define default_MCA_trigger(idx) (1)
#define default_MCA_polarity(idx) (0)
/***************************************************************************/
extern VOID Disable8259AIrq(ULONG irq);
ULONG IOAPICRead(ULONG Apic, ULONG Offset);
VOID IOAPICWrite(ULONG Apic, ULONG Offset, ULONG Value);
/* FUNCTIONS ***************************************************************/
/*
* EISA Edge/Level control register, ELCR
*/
static ULONG EISA_ELCR(ULONG irq)
{
if (irq < 16)
{
PUCHAR port = (PUCHAR)(0x4d0 + (irq >> 3));
return (READ_PORT_UCHAR(port) >> (irq & 7)) & 1;
}
DPRINT("Broken MPtable reports ISA irq %d\n", irq);
return 0;
}
static ULONG
IRQPolarity(ULONG idx)
{
ULONG bus = IRQMap[idx].SrcBusId;
ULONG polarity;
/*
* Determine IRQ line polarity (high active or low active):
*/
switch (IRQMap[idx].IrqFlag & 3)
{
case 0: /* conforms, ie. bus-type dependent polarity */
{
switch (BUSMap[bus])
{
case MP_BUS_ISA: /* ISA pin */
polarity = default_ISA_polarity(idx);
break;
case MP_BUS_EISA: /* EISA pin */
polarity = default_EISA_polarity(idx);
break;
case MP_BUS_PCI: /* PCI pin */
polarity = default_PCI_polarity(idx);
break;
case MP_BUS_MCA: /* MCA pin */
polarity = default_MCA_polarity(idx);
break;
default:
DPRINT("Broken BIOS!!\n");
polarity = 1;
}
}
break;
case 1: /* high active */
polarity = 0;
break;
case 2: /* reserved */
DPRINT("Broken BIOS!!\n");
polarity = 1;
break;
case 3: /* low active */
polarity = 1;
break;
default: /* invalid */
DPRINT("Broken BIOS!!\n");
polarity = 1;
}
return polarity;
}
static ULONG
IRQTrigger(ULONG idx)
{
ULONG bus = IRQMap[idx].SrcBusId;
ULONG trigger;
/*
* Determine IRQ trigger mode (edge or level sensitive):
*/
switch ((IRQMap[idx].IrqFlag >> 2) & 3)
{
case 0: /* conforms, ie. bus-type dependent */
{
switch (BUSMap[bus])
{
case MP_BUS_ISA: /* ISA pin */
trigger = default_ISA_trigger(idx);
break;
case MP_BUS_EISA: /* EISA pin */
trigger = default_EISA_trigger(idx);
break;
case MP_BUS_PCI: /* PCI pin */
trigger = default_PCI_trigger(idx);
break;
case MP_BUS_MCA: /* MCA pin */
trigger = default_MCA_trigger(idx);
break;
default:
DPRINT("Broken BIOS!!\n");
trigger = 1;
}
}
break;
case 1: /* edge */
trigger = 0;
break;
case 2: /* reserved */
DPRINT("Broken BIOS!!\n");
trigger = 1;
break;
case 3: /* level */
trigger = 1;
break;
default: /* invalid */
DPRINT("Broken BIOS!!\n");
trigger = 0;
}
return trigger;
}
static ULONG
Pin2Irq(ULONG idx,
ULONG apic,
ULONG pin)
{
ULONG irq, i;
ULONG bus = IRQMap[idx].SrcBusId;
/*
* Debugging check, we are in big trouble if this message pops up!
*/
if (IRQMap[idx].DstApicInt != pin)
{
DPRINT("broken BIOS or MPTABLE parser, ayiee!!\n");
}
switch (BUSMap[bus])
{
case MP_BUS_ISA: /* ISA pin */
case MP_BUS_EISA:
case MP_BUS_MCA:
irq = IRQMap[idx].SrcBusIrq;
break;
case MP_BUS_PCI: /* PCI pin */
/*
* PCI IRQs are mapped in order
*/
i = irq = 0;
while (i < apic)
{
irq += IOAPICMap[i++].EntryCount;
}
irq += pin;
break;
default:
DPRINT("Unknown bus type %d.\n",bus);
irq = 0;
}
return irq;
}
static ULONG
AssignIrqVector(ULONG irq)
{
#if 0
static ULONG current_vector = FIRST_DEVICE_VECTOR, vector_offset = 0;
#endif
ULONG vector;
/* There may already have been assigned a vector for this IRQ */
vector = IRQVectorMap[irq];
if (vector > 0)
{
return vector;
}
#if 0
if (current_vector > FIRST_SYSTEM_VECTOR)
{
vector_offset++;
current_vector = FIRST_DEVICE_VECTOR + vector_offset;
}
else if (current_vector == FIRST_SYSTEM_VECTOR)
{
DPRINT1("Ran out of interrupt sources!");
KEBUGCHECK(0);
}
vector = current_vector;
IRQVectorMap[irq] = vector;
current_vector += 8;
return vector;
#else
vector = IRQ2VECTOR(irq);
IRQVectorMap[irq] = vector;
return vector;
#endif
}
/*
* Find the IRQ entry number of a certain pin.
*/
static ULONG
IOAPICGetIrqEntry(ULONG apic,
ULONG pin,
ULONG type)
{
ULONG i;
for (i = 0; i < IRQCount; i++)
{
if (IRQMap[i].IrqType == type &&
(IRQMap[i].DstApicId == IOAPICMap[apic].ApicId || IRQMap[i].DstApicId == MP_APIC_ALL) &&
IRQMap[i].DstApicInt == pin)
{
return i;
}
}
return -1;
}
VOID
IOAPICSetupIrqs(VOID)
{
IOAPIC_ROUTE_ENTRY entry;
ULONG apic, pin, idx, irq, first_notcon = 1, vector, trigger;
DPRINT("Init IO_APIC IRQs\n");
/* Setup IRQ to vector translation map */
memset(&IRQVectorMap, 0, sizeof(IRQVectorMap));
for (apic = 0; apic < IOAPICCount; apic++)
{
for (pin = 0; pin < IOAPICMap[apic].EntryCount; pin++)
{
/*
* add it to the IO-APIC irq-routing table
*/
memset(&entry,0,sizeof(entry));
entry.delivery_mode = (APIC_DM_LOWEST >> 8);
entry.dest_mode = 1; /* logical delivery */
entry.mask = 1; /* disable IRQ */
entry.dest.logical.logical_dest = 0;
idx = IOAPICGetIrqEntry(apic,pin,INT_VECTORED);
if (idx == -1)
{
if (first_notcon)
{
DPRINT(" IO-APIC (apicid-pin) %d-%d\n", IOAPICMap[apic].ApicId, pin);
first_notcon = 0;
}
else
{
DPRINT(", %d-%d\n", IOAPICMap[apic].ApicId, pin);
}
continue;
}
trigger = IRQTrigger(idx);
entry.polarity = IRQPolarity(idx);
if (trigger)
{
entry.trigger = 1;
}
irq = Pin2Irq(idx, apic, pin);
vector = AssignIrqVector(irq);
entry.vector = vector;
DPRINT("vector 0x%.08x assigned to irq 0x%.02x\n", vector, irq);
if (irq == 0)
{
/* Mask timer IRQ */
entry.mask = 1;
}
if ((apic == 0) && (irq < 16))
{
Disable8259AIrq(irq);
}
IOAPICWrite(apic, IOAPIC_REDTBL+2*pin+1, *(((PULONG)&entry)+1));
IOAPICWrite(apic, IOAPIC_REDTBL+2*pin, *(((PULONG)&entry)+0));
IrqApicMap[irq] = apic;
DPRINT("Vector %x, Pin %x, Irq %x\n", vector, pin, irq);
}
}
}
static VOID
IOAPICClearPin(ULONG Apic, ULONG Pin)
{
IOAPIC_ROUTE_ENTRY Entry;
DPRINT("IOAPICClearPin(Apic %d, Pin %d\n", Apic, Pin);
/*
* Disable it in the IO-APIC irq-routing table
*/
memset(&Entry, 0, sizeof(Entry));
Entry.mask = 1;
IOAPICWrite(Apic, IOAPIC_REDTBL + 2 * Pin, *(((PULONG)&Entry) + 0));
IOAPICWrite(Apic, IOAPIC_REDTBL + 1 + 2 * Pin, *(((PULONG)&Entry) + 1));
}
static VOID
IOAPICClear(ULONG Apic)
{
ULONG Pin;
for (Pin = 0; Pin < /*IOAPICMap[Apic].EntryCount*/24; Pin++)
{
IOAPICClearPin(Apic, Pin);
}
}
static VOID
IOAPICClearAll(VOID)
{
ULONG Apic;
for (Apic = 0; Apic < IOAPICCount; Apic++)
{
IOAPICClear(Apic);
}
}
VOID
IOAPICEnable(VOID)
{
ULONG i, tmp;
/* Setup IRQ to vector translation map */
memset(&IRQVectorMap, 0, sizeof(IRQVectorMap));
/*
* The number of IO-APIC IRQ registers (== #pins):
*/
for (i = 0; i < IOAPICCount; i++)
{
tmp = IOAPICRead(i, IOAPIC_VER);
IOAPICMap[i].EntryCount = GET_IOAPIC_MRE(tmp) + 1;
}
/*
* Do not trust the IO-APIC being empty at bootup
*/
IOAPICClearAll();
}
VOID
IOAPICSetupIds(VOID)
{
ULONG tmp, apic, i;
UCHAR old_id;
/*
* Set the IOAPIC ID to the value stored in the MPC table.
*/
for (apic = 0; apic < IOAPICCount; apic++)
{
/* Read the register 0 value */
tmp = IOAPICRead(apic, IOAPIC_ID);
old_id = IOAPICMap[apic].ApicId;
if (IOAPICMap[apic].ApicId >= 0xf)
{
DPRINT1("BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n",
apic, IOAPICMap[apic].ApicId);
DPRINT1("... fixing up to %d. (tell your hw vendor)\n",
GET_IOAPIC_ID(tmp));
IOAPICMap[apic].ApicId = GET_IOAPIC_ID(tmp);
}
/*
* We need to adjust the IRQ routing table
* if the ID changed.
*/
if (old_id != IOAPICMap[apic].ApicId)
{
for (i = 0; i < IRQCount; i++)
{
if (IRQMap[i].DstApicId == old_id)
{
IRQMap[i].DstApicId = IOAPICMap[apic].ApicId;
}
}
}
/*
* Read the right value from the MPC table and
* write it into the ID register.
*/
DPRINT("Changing IO-APIC physical APIC ID to %d\n",
IOAPICMap[apic].ApicId);
tmp &= ~IOAPIC_ID_MASK;
tmp |= SET_IOAPIC_ID(IOAPICMap[apic].ApicId);
IOAPICWrite(apic, IOAPIC_ID, tmp);
/*
* Sanity check
*/
tmp = IOAPICRead(apic, 0);
if (GET_IOAPIC_ID(tmp) != IOAPICMap[apic].ApicId)
{
DPRINT1("Could not set I/O APIC ID!\n");
KEBUGCHECK(0);
}
}
}
/* This is performance critical and should probably be done in assembler */
VOID IOAPICMaskIrq(ULONG Irq)
{
IOAPIC_ROUTE_ENTRY Entry;
ULONG Apic = IrqApicMap[Irq];
*(((PULONG)&Entry)+0) = IOAPICRead(Apic, IOAPIC_REDTBL+2*Irq);
*(((PULONG)&Entry)+1) = IOAPICRead(Apic, IOAPIC_REDTBL+2*Irq+1);
Entry.dest.logical.logical_dest &= ~(1 << KeGetCurrentProcessorNumber());
if (Entry.dest.logical.logical_dest == 0)
{
Entry.mask = 1;
}
IOAPICWrite(Apic, IOAPIC_REDTBL+2*Irq+1, *(((PULONG)&Entry)+1));
IOAPICWrite(Apic, IOAPIC_REDTBL+2*Irq, *(((PULONG)&Entry)+0));
}
/* This is performance critical and should probably be done in assembler */
VOID IOAPICUnmaskIrq(ULONG Irq)
{
IOAPIC_ROUTE_ENTRY Entry;
ULONG Apic = IrqApicMap[Irq];
*(((PULONG)&Entry)+0) = IOAPICRead(Apic, IOAPIC_REDTBL+2*Irq);
*(((PULONG)&Entry)+1) = IOAPICRead(Apic, IOAPIC_REDTBL+2*Irq+1);
Entry.dest.logical.logical_dest |= 1 << KeGetCurrentProcessorNumber();
Entry.mask = 0;
IOAPICWrite(Apic, IOAPIC_REDTBL+2*Irq+1, *(((PULONG)&Entry)+1));
IOAPICWrite(Apic, IOAPIC_REDTBL+2*Irq, *(((PULONG)&Entry)+0));
}
VOID IOAPICDump(VOID)
{
ULONG apic, i;
ULONG reg0, reg1, reg2=0;
DbgPrint("Number of MP IRQ sources: %d.\n", IRQCount);
for (i = 0; i < IOAPICCount; i++)
{
DbgPrint("Number of IO-APIC #%d registers: %d.\n",
IOAPICMap[i].ApicId,
IOAPICMap[i].EntryCount);
}
/*
* We are a bit conservative about what we expect. We have to
* know about every hardware change ASAP.
*/
DbgPrint("Testing the IO APIC.......................\n");
for (apic = 0; apic < IOAPICCount; apic++)
{
reg0 = IOAPICRead(apic, IOAPIC_ID);
reg1 = IOAPICRead(apic, IOAPIC_VER);
if (GET_IOAPIC_VERSION(reg1) >= 0x10)
{
reg2 = IOAPICRead(apic, IOAPIC_ARB);
}
DbgPrint("\n");
DbgPrint("IO APIC #%d......\n", IOAPICMap[apic].ApicId);
DbgPrint(".... register #00: %08X\n", reg0);
DbgPrint("....... : physical APIC id: %02X\n", GET_IOAPIC_ID(reg0));
if (reg0 & 0xF0FFFFFF)
{
DbgPrint(" WARNING: Unexpected IO-APIC\n");
}
DbgPrint(".... register #01: %08X\n", reg1);
i = GET_IOAPIC_MRE(reg1);
DbgPrint("....... : max redirection entries: %04X\n", i);
if ((i != 0x0f) && /* older (Neptune) boards */
(i != 0x17) && /* typical ISA+PCI boards */
(i != 0x1b) && /* Compaq Proliant boards */
(i != 0x1f) && /* dual Xeon boards */
(i != 0x22) && /* bigger Xeon boards */
(i != 0x2E) &&
(i != 0x3F))
{
DbgPrint(" WARNING: Unexpected IO-APIC\n");
}
i = GET_IOAPIC_VERSION(reg1);
DbgPrint("....... : IO APIC version: %04X\n", i);
if ((i != 0x01) && /* 82489DX IO-APICs */
(i != 0x10) && /* oldest IO-APICs */
(i != 0x11) && /* Pentium/Pro IO-APICs */
(i != 0x13)) /* Xeon IO-APICs */
{
DbgPrint(" WARNING: Unexpected IO-APIC\n");
}
if (reg1 & 0xFF00FF00)
{
DbgPrint(" WARNING: Unexpected IO-APIC\n");
}
if (GET_IOAPIC_VERSION(reg1) >= 0x10)
{
DbgPrint(".... register #02: %08X\n", reg2);
DbgPrint("....... : arbitration: %02X\n",
GET_IOAPIC_ARB(reg2));
if (reg2 & 0xF0FFFFFF)
{
DbgPrint(" WARNING: Unexpected IO-APIC\n");
}
}
DbgPrint(".... IRQ redirection table:\n");
DbgPrint(" NR Log Phy Mask Trig IRR Pol"
" Stat Dest Deli Vect: \n");
for (i = 0; i <= GET_IOAPIC_MRE(reg1); i++)
{
IOAPIC_ROUTE_ENTRY entry;
*(((PULONG)&entry)+0) = IOAPICRead(apic, 0x10+i*2);
*(((PULONG)&entry)+1) = IOAPICRead(apic, 0x11+i*2);
DbgPrint(" %02x %03X %02X ",
i,
entry.dest.logical.logical_dest,
entry.dest.physical.physical_dest);
DbgPrint("%C %C %1d %C %C %C %03X %02X\n",
(entry.mask == 0) ? 'U' : 'M', // Unmasked/masked
(entry.trigger == 0) ? 'E' : 'L', // Edge/level sensitive
entry.irr,
(entry.polarity == 0) ? 'H' : 'L', // Active high/active low
(entry.delivery_status == 0) ? 'I' : 'S', // Idle / send pending
(entry.dest_mode == 0) ? 'P' : 'L', // Physical logical
entry.delivery_mode,
entry.vector);
}
}
DbgPrint(".................................... done.\n");
}
VOID
HaliReconfigurePciInterrupts(VOID)
{
ULONG i;
for (i = 0; i < IRQCount; i++)
{
if (BUSMap[IRQMap[i].SrcBusId] == MP_BUS_PCI)
{
DPRINT("%02x: IrqType %02x, IrqFlag %02x, SrcBusId %02x, SrcBusIrq %02x"
", DstApicId %02x, DstApicInt %02x\n",
i, IRQMap[i].IrqType, IRQMap[i].IrqFlag, IRQMap[i].SrcBusId,
IRQMap[i].SrcBusIrq, IRQMap[i].DstApicId, IRQMap[i].DstApicInt);
if(1 != HalSetBusDataByOffset(PCIConfiguration,
IRQMap[i].SrcBusId,
(IRQMap[i].SrcBusIrq >> 2) & 0x1f,
&IRQMap[i].DstApicInt,
0x3c /*PCI_INTERRUPT_LINE*/,
1))
{
CHECKPOINT;
}
}
}
}
VOID Disable8259AIrq(ULONG irq)
{
ULONG tmp;
if (irq >= 8)
{
tmp = READ_PORT_UCHAR((PUCHAR)0xA1);
tmp |= (1 << (irq - 8));
WRITE_PORT_UCHAR((PUCHAR)0xA1, tmp);
}
else
{
tmp = READ_PORT_UCHAR((PUCHAR)0x21);
tmp |= (1 << irq);
WRITE_PORT_UCHAR((PUCHAR)0x21, tmp);
}
}
ULONG IOAPICRead(ULONG Apic, ULONG Offset)
{
PULONG Base;
Base = (PULONG)IOAPICMap[Apic].ApicAddress;
*Base = Offset;
return *((PULONG)((ULONG)Base + IOAPIC_IOWIN));
}
VOID IOAPICWrite(ULONG Apic, ULONG Offset, ULONG Value)
{
PULONG Base;
Base = (PULONG)IOAPICMap[Apic].ApicAddress;
*Base = Offset;
*((PULONG)((ULONG)Base + IOAPIC_IOWIN)) = Value;
}
/* EOF */

View file

@ -0,0 +1,649 @@
/* $Id$
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: hal/halx86/generic/mpconfig.c
* PURPOSE:
* PROGRAMMER:
*/
/* INCLUDES *****************************************************************/
#include <ddk/ntddk.h>
#include <ntos/types.h>
#include <hal.h>
#include <mps.h>
#include <apic.h>
#include <ioapic.h>
//#define NDEBUG
#include <internal/debug.h>
/* GLOBALS ******************************************************************/
MP_FLOATING_POINTER* Mpf = NULL;
/* FUNCTIONS ****************************************************************/
static UCHAR
MPChecksum(PUCHAR Base,
ULONG Size)
/*
* Checksum an MP configuration block
*/
{
UCHAR Sum = 0;
while (Size--)
Sum += *Base++;
return Sum;
}
static VOID
HaliMPIntSrcInfo(PMP_CONFIGURATION_INTSRC m)
{
DPRINT("Int: type %d, pol %d, trig %d, bus %d,"
" IRQ %02x, APIC ID %x, APIC INT %02x\n",
m->IrqType, m->IrqFlag & 3,
(m->IrqFlag >> 2) & 3, m->SrcBusId,
m->SrcBusIrq, m->DstApicId, m->DstApicInt);
if (IRQCount > MAX_IRQ_SOURCE)
{
DPRINT1("Max # of irq sources exceeded!!\n");
KEBUGCHECK(0);
}
IRQMap[IRQCount] = *m;
IRQCount++;
}
static PCHAR
HaliMPFamily(ULONG Family,
ULONG Model)
{
static CHAR str[64];
static PCHAR CPUs[] =
{
"80486DX", "80486DX",
"80486SX", "80486DX/2 or 80487",
"80486SL", "Intel5X2(tm)",
"Unknown", "Unknown",
"80486DX/4"
};
if (Family == 0x6)
return ("Pentium(tm) Pro");
if (Family == 0x5)
return ("Pentium(tm)");
if (Family == 0x0F && Model == 0x0F)
return("Special controller");
if (Family == 0x0F && Model == 0x00)
return("Pentium 4(tm)");
if (Family == 0x04 && Model < 9)
return CPUs[Model];
sprintf(str, "Unknown CPU with family ID %ld and model ID %ld", Family, Model);
return str;
}
static VOID
HaliMPProcessorInfo(PMP_CONFIGURATION_PROCESSOR m)
{
ULONG ver;
if (!(m->CpuFlags & CPU_FLAG_ENABLED))
return;
DPRINT("Processor #%d %s APIC version %d\n",
m->ApicId,
HaliMPFamily((m->FeatureFlags & CPU_FAMILY_MASK) >> 8,
(m->FeatureFlags & CPU_MODEL_MASK) >> 4),
m->ApicVersion);
if (m->FeatureFlags & (1 << 0))
DPRINT(" Floating point unit present.\n");
if (m->FeatureFlags & (1 << 7))
DPRINT(" Machine Exception supported.\n");
if (m->FeatureFlags & (1 << 8))
DPRINT(" 64 bit compare & exchange supported.\n");
if (m->FeatureFlags & (1 << 9))
DPRINT(" Internal APIC present.\n");
if (m->FeatureFlags & (1 << 11))
DPRINT(" SEP present.\n");
if (m->FeatureFlags & (1 << 12))
DPRINT(" MTRR present.\n");
if (m->FeatureFlags & (1 << 13))
DPRINT(" PGE present.\n");
if (m->FeatureFlags & (1 << 14))
DPRINT(" MCA present.\n");
if (m->FeatureFlags & (1 << 15))
DPRINT(" CMOV present.\n");
if (m->FeatureFlags & (1 << 16))
DPRINT(" PAT present.\n");
if (m->FeatureFlags & (1 << 17))
DPRINT(" PSE present.\n");
if (m->FeatureFlags & (1 << 18))
DPRINT(" PSN present.\n");
if (m->FeatureFlags & (1 << 19))
DPRINT(" Cache Line Flush Instruction present.\n");
/* 20 Reserved */
if (m->FeatureFlags & (1 << 21))
DPRINT(" Debug Trace and EMON Store present.\n");
if (m->FeatureFlags & (1 << 22))
DPRINT(" ACPI Thermal Throttle Registers present.\n");
if (m->FeatureFlags & (1 << 23))
DPRINT(" MMX present.\n");
if (m->FeatureFlags & (1 << 24))
DPRINT(" FXSR present.\n");
if (m->FeatureFlags & (1 << 25))
DPRINT(" XMM present.\n");
if (m->FeatureFlags & (1 << 26))
DPRINT(" Willamette New Instructions present.\n");
if (m->FeatureFlags & (1 << 27))
DPRINT(" Self Snoop present.\n");
/* 28 Reserved */
if (m->FeatureFlags & (1 << 29))
DPRINT(" Thermal Monitor present.\n");
/* 30, 31 Reserved */
CPUMap[CPUCount].APICId = m->ApicId;
CPUMap[CPUCount].Flags = CPU_USABLE;
if (m->CpuFlags & CPU_FLAG_BSP)
{
DPRINT(" Bootup CPU\n");
CPUMap[CPUCount].Flags |= CPU_BSP;
BootCPU = m->ApicId;
}
if (m->ApicId > MAX_CPU)
{
DPRINT("Processor #%d INVALID. (Max ID: %d).\n", m->ApicId, MAX_CPU);
return;
}
ver = m->ApicVersion;
/*
* Validate version
*/
if (ver == 0x0)
{
DPRINT("BIOS bug, APIC version is 0 for CPU#%d! fixing up to 0x10. (tell your hw vendor)\n", m->ApicId);
ver = 0x10;
}
// ApicVersion[m->ApicId] = Ver;
// BiosCpuApicId[CPUCount] = m->ApicId;
CPUMap[CPUCount].APICVersion = ver;
CPUCount++;
}
static VOID
HaliMPBusInfo(PMP_CONFIGURATION_BUS m)
{
static ULONG CurrentPCIBusId = 0;
DPRINT("Bus #%d is %.*s\n", m->BusId, 6, m->BusType);
if (strncmp(m->BusType, BUSTYPE_ISA, sizeof(BUSTYPE_ISA)-1) == 0)
{
BUSMap[m->BusId] = MP_BUS_ISA;
}
else if (strncmp(m->BusType, BUSTYPE_EISA, sizeof(BUSTYPE_EISA)-1) == 0)
{
BUSMap[m->BusId] = MP_BUS_EISA;
}
else if (strncmp(m->BusType, BUSTYPE_PCI, sizeof(BUSTYPE_PCI)-1) == 0)
{
BUSMap[m->BusId] = MP_BUS_PCI;
PCIBUSMap[m->BusId] = CurrentPCIBusId;
CurrentPCIBusId++;
}
else if (strncmp(m->BusType, BUSTYPE_MCA, sizeof(BUSTYPE_MCA)-1) == 0)
{
BUSMap[m->BusId] = MP_BUS_MCA;
}
else
{
DPRINT("Unknown bustype %.*s - ignoring\n", 6, m->BusType);
}
}
static VOID
HaliMPIOApicInfo(PMP_CONFIGURATION_IOAPIC m)
{
if (!(m->ApicFlags & CPU_FLAG_ENABLED))
return;
DPRINT("I/O APIC #%d Version %d at 0x%lX.\n",
m->ApicId, m->ApicVersion, m->ApicAddress);
if (IOAPICCount > MAX_IOAPIC)
{
DPRINT("Max # of I/O APICs (%d) exceeded (found %d).\n",
MAX_IOAPIC, IOAPICCount);
DPRINT1("Recompile with bigger MAX_IOAPIC!.\n");
KEBUGCHECK(0);
}
IOAPICMap[IOAPICCount].ApicId = m->ApicId;
IOAPICMap[IOAPICCount].ApicVersion = m->ApicVersion;
IOAPICMap[IOAPICCount].ApicAddress = m->ApicAddress;
IOAPICCount++;
}
static VOID
HaliMPIntLocalInfo(PMP_CONFIGURATION_INTLOCAL m)
{
DPRINT("Lint: type %d, pol %d, trig %d, bus %d,"
" IRQ %02x, APIC ID %x, APIC LINT %02x\n",
m->IrqType, m->SrcBusIrq & 3,
(m->SrcBusIrq >> 2) & 3, m->SrcBusId,
m->SrcBusIrq, m->DstApicId, m->DstApicLInt);
/*
* Well it seems all SMP boards in existence
* use ExtINT/LVT1 == LINT0 and
* NMI/LVT2 == LINT1 - the following check
* will show us if this assumptions is false.
* Until then we do not have to add baggage.
*/
if ((m->IrqType == INT_EXTINT) && (m->DstApicLInt != 0))
{
DPRINT1("Invalid MP table!\n");
KEBUGCHECK(0);
}
if ((m->IrqType == INT_NMI) && (m->DstApicLInt != 1))
{
DPRINT1("Invalid MP table!\n");
KEBUGCHECK(0);
}
}
static BOOLEAN
HaliReadMPConfigTable(PMP_CONFIGURATION_TABLE Table)
/*
PARAMETERS:
Table = Pointer to MP configuration table
*/
{
PUCHAR Entry;
ULONG Count;
if (Table->Signature != MPC_SIGNATURE)
{
PUCHAR pc = (PUCHAR)&Table->Signature;
DPRINT1("Bad MP configuration block signature: %c%c%c%c\n",
pc[0], pc[1], pc[2], pc[3]);
KEBUGCHECK(0);
return FALSE;
}
if (MPChecksum((PUCHAR)Table, Table->Length))
{
DPRINT1("Bad MP configuration block checksum\n");
KEBUGCHECK(0);
return FALSE;
}
if (Table->Specification != 0x01 && Table->Specification != 0x04)
{
DPRINT1("Bad MP configuration table version (%d)\n",
Table->Specification);
KEBUGCHECK(0);
return FALSE;
}
if (Table->LocalAPICAddress != APIC_DEFAULT_BASE)
{
DPRINT1("APIC base address is at 0x%X. I cannot handle non-standard adresses\n",
Table->LocalAPICAddress);
KEBUGCHECK(0);
return FALSE;
}
DPRINT("Oem: %.*s, ProductId: %.*s\n", 8, Table->Oem, 12, Table->ProductId);
DPRINT("APIC at: %08x\n", Table->LocalAPICAddress);
Entry = (PUCHAR)((PVOID)Table + sizeof(MP_CONFIGURATION_TABLE));
Count = 0;
while (Count < (Table->Length - sizeof(MP_CONFIGURATION_TABLE)))
{
/* Switch on type */
switch (*Entry)
{
case MPCTE_PROCESSOR:
{
HaliMPProcessorInfo((PMP_CONFIGURATION_PROCESSOR)Entry);
Entry += sizeof(MP_CONFIGURATION_PROCESSOR);
Count += sizeof(MP_CONFIGURATION_PROCESSOR);
break;
}
case MPCTE_BUS:
{
HaliMPBusInfo((PMP_CONFIGURATION_BUS)Entry);
Entry += sizeof(MP_CONFIGURATION_BUS);
Count += sizeof(MP_CONFIGURATION_BUS);
break;
}
case MPCTE_IOAPIC:
{
HaliMPIOApicInfo((PMP_CONFIGURATION_IOAPIC)Entry);
Entry += sizeof(MP_CONFIGURATION_IOAPIC);
Count += sizeof(MP_CONFIGURATION_IOAPIC);
break;
}
case MPCTE_INTSRC:
{
HaliMPIntSrcInfo((PMP_CONFIGURATION_INTSRC)Entry);
Entry += sizeof(MP_CONFIGURATION_INTSRC);
Count += sizeof(MP_CONFIGURATION_INTSRC);
break;
}
case MPCTE_LINTSRC:
{
HaliMPIntLocalInfo((PMP_CONFIGURATION_INTLOCAL)Entry);
Entry += sizeof(MP_CONFIGURATION_INTLOCAL);
Count += sizeof(MP_CONFIGURATION_INTLOCAL);
break;
}
default:
DPRINT1("Unknown entry in MPC table\n");
KEBUGCHECK(0);
return FALSE;
}
}
return TRUE;
}
static VOID
HaliConstructDefaultIOIrqMPTable(ULONG Type)
{
MP_CONFIGURATION_INTSRC intsrc;
ULONG i;
intsrc.Type = MPCTE_INTSRC;
intsrc.IrqFlag = 0; /* conforming */
intsrc.SrcBusId = 0;
intsrc.DstApicId = IOAPICMap[0].ApicId;
intsrc.IrqType = INT_VECTORED;
for (i = 0; i < 16; i++) {
switch (Type) {
case 2:
if (i == 0 || i == 13)
continue; /* IRQ0 & IRQ13 not connected */
/* Fall through */
default:
if (i == 2)
continue; /* IRQ2 is never connected */
}
intsrc.SrcBusIrq = i;
intsrc.DstApicInt = i ? i : 2; /* IRQ0 to INTIN2 */
HaliMPIntSrcInfo(&intsrc);
}
intsrc.IrqType = INT_EXTINT;
intsrc.SrcBusIrq = 0;
intsrc.DstApicInt = 0; /* 8259A to INTIN0 */
HaliMPIntSrcInfo(&intsrc);
}
static VOID
HaliConstructDefaultISAMPTable(ULONG Type)
{
MP_CONFIGURATION_PROCESSOR processor;
MP_CONFIGURATION_BUS bus;
MP_CONFIGURATION_IOAPIC ioapic;
MP_CONFIGURATION_INTLOCAL lintsrc;
ULONG linttypes[2] = { INT_EXTINT, INT_NMI };
ULONG i;
/*
* 2 CPUs, numbered 0 & 1.
*/
processor.Type = MPCTE_PROCESSOR;
/* Either an integrated APIC or a discrete 82489DX. */
processor.ApicVersion = Type > 4 ? 0x10 : 0x01;
processor.CpuFlags = CPU_FLAG_ENABLED | CPU_FLAG_BSP;
/* FIXME: Get this from the bootstrap processor */
processor.CpuSignature = 0;
processor.FeatureFlags = 0;
processor.Reserved[0] = 0;
processor.Reserved[1] = 0;
for (i = 0; i < 2; i++)
{
processor.ApicId = i;
HaliMPProcessorInfo(&processor);
processor.CpuFlags &= ~CPU_FLAG_BSP;
}
bus.Type = MPCTE_BUS;
bus.BusId = 0;
switch (Type)
{
default:
DPRINT("Unknown standard configuration %d\n", Type);
/* Fall through */
case 1:
case 5:
memcpy(bus.BusType, "ISA ", 6);
break;
case 2:
case 6:
case 3:
memcpy(bus.BusType, "EISA ", 6);
break;
case 4:
case 7:
memcpy(bus.BusType, "MCA ", 6);
}
HaliMPBusInfo(&bus);
if (Type > 4)
{
bus.Type = MPCTE_BUS;
bus.BusId = 1;
memcpy(bus.BusType, "PCI ", 6);
HaliMPBusInfo(&bus);
}
ioapic.Type = MPCTE_IOAPIC;
ioapic.ApicId = 2;
ioapic.ApicVersion = Type > 4 ? 0x10 : 0x01;
ioapic.ApicFlags = MP_IOAPIC_USABLE;
ioapic.ApicAddress = IOAPIC_DEFAULT_BASE;
HaliMPIOApicInfo(&ioapic);
/*
* We set up most of the low 16 IO-APIC pins according to MPS rules.
*/
HaliConstructDefaultIOIrqMPTable(Type);
lintsrc.Type = MPCTE_LINTSRC;
lintsrc.IrqType = 0;
lintsrc.IrqFlag = 0; /* conforming */
lintsrc.SrcBusId = 0;
lintsrc.SrcBusIrq = 0;
lintsrc.DstApicId = MP_APIC_ALL;
for (i = 0; i < 2; i++)
{
lintsrc.IrqType = linttypes[i];
lintsrc.DstApicLInt = i;
HaliMPIntLocalInfo(&lintsrc);
}
}
static BOOLEAN
HaliScanForMPConfigTable(ULONG Base,
ULONG Size)
{
/*
PARAMETERS:
Base = Base address of region
Size = Length of region to check
RETURNS:
TRUE if a valid MP configuration table was found
*/
PULONG bp = (PULONG)Base;
MP_FLOATING_POINTER* mpf;
UCHAR Checksum;
while (Size > 0)
{
mpf = (MP_FLOATING_POINTER*)bp;
if (mpf->Signature == MPF_SIGNATURE)
{
Checksum = MPChecksum((PUCHAR)bp, 16);
DPRINT("Found MPF signature at %x, checksum %x\n", bp, Checksum);
if (Checksum == 0 &&
mpf->Length == 1)
{
DPRINT("Intel MultiProcessor Specification v1.%d compliant system.\n",
mpf->Specification);
if (mpf->Feature2 & FEATURE2_IMCRP)
{
DPRINT("Running in IMCR and PIC compatibility mode.\n");
}
else
{
DPRINT("Running in Virtual Wire compatibility mode.\n");
}
switch (mpf->Feature1)
{
case 0:
/* Non standard configuration */
break;
case 1:
DPRINT("ISA\n");
break;
case 2:
DPRINT("EISA with no IRQ8 chaining\n");
break;
case 3:
DPRINT("EISA\n");
break;
case 4:
DPRINT("MCA\n");
break;
case 5:
DPRINT("ISA and PCI\n");
break;
case 6:
DPRINT("EISA and PCI\n");
break;
case 7:
DPRINT("MCA and PCI\n");
break;
default:
DPRINT("Unknown standard configuration %d\n", mpf->Feature1);
return FALSE;
}
Mpf = mpf;
return TRUE;
}
}
bp += 4;
Size -= 16;
}
return FALSE;
}
static BOOLEAN
HaliGetSmpConfig(VOID)
{
if (Mpf == NULL)
{
return FALSE;
}
if (Mpf->Feature2 & FEATURE2_IMCRP)
{
DPRINT("Running in IMCR and PIC compatibility mode.\n");
APICMode = amPIC;
}
else
{
DPRINT("Running in Virtual Wire compatibility mode.\n");
APICMode = amVWIRE;
}
if (Mpf->Feature1 == 0 && Mpf->Address)
{
if(!HaliReadMPConfigTable((PMP_CONFIGURATION_TABLE)Mpf->Address))
{
DPRINT("BIOS bug, MP table errors detected!...\n");
DPRINT("... disabling SMP support. (tell your hw vendor)\n");
return FALSE;
}
if (IRQCount == 0)
{
MP_CONFIGURATION_BUS bus;
DPRINT("BIOS bug, no explicit IRQ entries, using default mptable. (tell your hw vendor)\n");
bus.BusId = 1;
memcpy(bus.BusType, "ISA ", 6);
HaliMPBusInfo(&bus);
HaliConstructDefaultIOIrqMPTable(bus.BusId);
}
}
else if(Mpf->Feature1 != 0)
{
HaliConstructDefaultISAMPTable(Mpf->Feature1);
}
else
{
KEBUGCHECK(0);
}
return TRUE;
}
BOOLEAN
HaliFindSmpConfig(VOID)
{
/*
Scan the system memory for an MP configuration table
1) Scan the first KB of system base memory
2) Scan the last KB of system base memory
3) Scan the BIOS ROM address space between 0F0000h and 0FFFFFh
4) Scan the first KB from the Extended BIOS Data Area
*/
if (!HaliScanForMPConfigTable(0x0, 0x400))
{
if (!HaliScanForMPConfigTable(0x9FC00, 0x400))
{
if (!HaliScanForMPConfigTable(0xF0000, 0x10000))
{
if (!HaliScanForMPConfigTable(*((PUSHORT)0x040E) << 4, 0x400))
{
DPRINT("No multiprocessor compliant system found.\n");
return FALSE;
}
}
}
}
if (HaliGetSmpConfig())
{
return TRUE;
}
else
{
DPRINT("No MP config table found\n");
return FALSE;
}
}
/* EOF */

View file

@ -19,6 +19,7 @@
#include <hal.h>
#include <mps.h>
#include <apic.h>
#include <ioapic.h>
#define NDEBUG
#include <internal/debug.h>

File diff suppressed because it is too large Load diff