3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: hal/halx86/generic/mpconfig.c
10 /* INCLUDES *****************************************************************/
16 /* GLOBALS ******************************************************************/
18 MP_FLOATING_POINTER
* Mpf
= NULL
;
20 /* FUNCTIONS ****************************************************************/
23 MPChecksum(PUCHAR Base
,
26 * Checksum an MP configuration block
38 HaliMPIntSrcInfo(PMP_CONFIGURATION_INTSRC m
)
40 DPRINT("Int: type %d, pol %d, trig %d, bus %d,"
41 " IRQ %02x, APIC ID %x, APIC INT %02x\n",
42 m
->IrqType
, m
->IrqFlag
& 3,
43 (m
->IrqFlag
>> 2) & 3, m
->SrcBusId
,
44 m
->SrcBusIrq
, m
->DstApicId
, m
->DstApicInt
);
45 if (IRQCount
> MAX_IRQ_SOURCE
)
47 DPRINT1("Max # of irq sources exceeded!!\n");
51 IRQMap
[IRQCount
] = *m
;
56 HaliMPFamily(ULONG Family
,
63 "80486SX", "80486DX/2 or 80487",
64 "80486SL", "Intel5X2(tm)",
69 return ("Pentium(tm) Pro");
71 return ("Pentium(tm)");
72 if (Family
== 0x0F && Model
== 0x0F)
73 return("Special controller");
74 if (Family
== 0x0F && Model
== 0x00)
75 return("Pentium 4(tm)");
76 if (Family
== 0x04 && Model
< 9)
78 sprintf(str
, "Unknown CPU with family ID %ld and model ID %ld", Family
, Model
);
84 HaliMPProcessorInfo(PMP_CONFIGURATION_PROCESSOR m
)
88 if (!(m
->CpuFlags
& CPU_FLAG_ENABLED
))
91 DPRINT("Processor #%d %s APIC version %d\n",
93 HaliMPFamily((m
->FeatureFlags
& CPU_FAMILY_MASK
) >> 8,
94 (m
->FeatureFlags
& CPU_MODEL_MASK
) >> 4),
97 if (m
->FeatureFlags
& (1 << 0))
98 DPRINT(" Floating point unit present.\n");
99 if (m
->FeatureFlags
& (1 << 7))
100 DPRINT(" Machine Exception supported.\n");
101 if (m
->FeatureFlags
& (1 << 8))
102 DPRINT(" 64 bit compare & exchange supported.\n");
103 if (m
->FeatureFlags
& (1 << 9))
104 DPRINT(" Internal APIC present.\n");
105 if (m
->FeatureFlags
& (1 << 11))
106 DPRINT(" SEP present.\n");
107 if (m
->FeatureFlags
& (1 << 12))
108 DPRINT(" MTRR present.\n");
109 if (m
->FeatureFlags
& (1 << 13))
110 DPRINT(" PGE present.\n");
111 if (m
->FeatureFlags
& (1 << 14))
112 DPRINT(" MCA present.\n");
113 if (m
->FeatureFlags
& (1 << 15))
114 DPRINT(" CMOV present.\n");
115 if (m
->FeatureFlags
& (1 << 16))
116 DPRINT(" PAT present.\n");
117 if (m
->FeatureFlags
& (1 << 17))
118 DPRINT(" PSE present.\n");
119 if (m
->FeatureFlags
& (1 << 18))
120 DPRINT(" PSN present.\n");
121 if (m
->FeatureFlags
& (1 << 19))
122 DPRINT(" Cache Line Flush Instruction present.\n");
124 if (m
->FeatureFlags
& (1 << 21))
125 DPRINT(" Debug Trace and EMON Store present.\n");
126 if (m
->FeatureFlags
& (1 << 22))
127 DPRINT(" ACPI Thermal Throttle Registers present.\n");
128 if (m
->FeatureFlags
& (1 << 23))
129 DPRINT(" MMX present.\n");
130 if (m
->FeatureFlags
& (1 << 24))
131 DPRINT(" FXSR present.\n");
132 if (m
->FeatureFlags
& (1 << 25))
133 DPRINT(" XMM present.\n");
134 if (m
->FeatureFlags
& (1 << 26))
135 DPRINT(" Willamette New Instructions present.\n");
136 if (m
->FeatureFlags
& (1 << 27))
137 DPRINT(" Self Snoop present.\n");
139 if (m
->FeatureFlags
& (1 << 29))
140 DPRINT(" Thermal Monitor present.\n");
141 /* 30, 31 Reserved */
143 CPUMap
[CPUCount
].APICId
= m
->ApicId
;
145 CPUMap
[CPUCount
].Flags
= CPU_USABLE
;
147 if (m
->CpuFlags
& CPU_FLAG_BSP
)
149 DPRINT(" Bootup CPU\n");
150 CPUMap
[CPUCount
].Flags
|= CPU_BSP
;
154 if (m
->ApicId
> MAX_CPU
)
156 DPRINT("Processor #%d INVALID. (Max ID: %d).\n", m
->ApicId
, MAX_CPU
);
159 ver
= m
->ApicVersion
;
166 DPRINT("BIOS bug, APIC version is 0 for CPU#%d! fixing up to 0x10. (tell your hw vendor)\n", m
->ApicId
);
169 // ApicVersion[m->ApicId] = Ver;
170 // BiosCpuApicId[CPUCount] = m->ApicId;
171 CPUMap
[CPUCount
].APICVersion
= ver
;
177 HaliMPBusInfo(PMP_CONFIGURATION_BUS m
)
179 static ULONG CurrentPCIBusId
= 0;
181 DPRINT("Bus #%d is %.*s\n", m
->BusId
, 6, m
->BusType
);
183 if (strncmp(m
->BusType
, BUSTYPE_ISA
, sizeof(BUSTYPE_ISA
)-1) == 0)
185 BUSMap
[m
->BusId
] = MP_BUS_ISA
;
187 else if (strncmp(m
->BusType
, BUSTYPE_EISA
, sizeof(BUSTYPE_EISA
)-1) == 0)
189 BUSMap
[m
->BusId
] = MP_BUS_EISA
;
191 else if (strncmp(m
->BusType
, BUSTYPE_PCI
, sizeof(BUSTYPE_PCI
)-1) == 0)
193 BUSMap
[m
->BusId
] = MP_BUS_PCI
;
194 PCIBUSMap
[m
->BusId
] = CurrentPCIBusId
;
197 else if (strncmp(m
->BusType
, BUSTYPE_MCA
, sizeof(BUSTYPE_MCA
)-1) == 0)
199 BUSMap
[m
->BusId
] = MP_BUS_MCA
;
203 DPRINT("Unknown bustype %.*s - ignoring\n", 6, m
->BusType
);
208 HaliMPIOApicInfo(PMP_CONFIGURATION_IOAPIC m
)
210 if (!(m
->ApicFlags
& CPU_FLAG_ENABLED
))
213 DPRINT("I/O APIC #%d Version %d at 0x%lX.\n",
214 m
->ApicId
, m
->ApicVersion
, m
->ApicAddress
);
215 if (IOAPICCount
> MAX_IOAPIC
)
217 DPRINT("Max # of I/O APICs (%d) exceeded (found %d).\n",
218 MAX_IOAPIC
, IOAPICCount
);
219 DPRINT1("Recompile with bigger MAX_IOAPIC!.\n");
223 IOAPICMap
[IOAPICCount
].ApicId
= m
->ApicId
;
224 IOAPICMap
[IOAPICCount
].ApicVersion
= m
->ApicVersion
;
225 IOAPICMap
[IOAPICCount
].ApicAddress
= m
->ApicAddress
;
231 HaliMPIntLocalInfo(PMP_CONFIGURATION_INTLOCAL m
)
233 DPRINT("Lint: type %d, pol %d, trig %d, bus %d,"
234 " IRQ %02x, APIC ID %x, APIC LINT %02x\n",
235 m
->IrqType
, m
->SrcBusIrq
& 3,
236 (m
->SrcBusIrq
>> 2) & 3, m
->SrcBusId
,
237 m
->SrcBusIrq
, m
->DstApicId
, m
->DstApicLInt
);
239 * Well it seems all SMP boards in existence
240 * use ExtINT/LVT1 == LINT0 and
241 * NMI/LVT2 == LINT1 - the following check
242 * will show us if this assumptions is false.
243 * Until then we do not have to add baggage.
245 if ((m
->IrqType
== INT_EXTINT
) && (m
->DstApicLInt
!= 0))
247 DPRINT1("Invalid MP table!\n");
250 if ((m
->IrqType
== INT_NMI
) && (m
->DstApicLInt
!= 1))
252 DPRINT1("Invalid MP table!\n");
259 HaliReadMPConfigTable(PMP_CONFIGURATION_TABLE Table
)
262 Table = Pointer to MP configuration table
268 if (Table
->Signature
!= MPC_SIGNATURE
)
270 PUCHAR pc
= (PUCHAR
)&Table
->Signature
;
272 DPRINT1("Bad MP configuration block signature: %c%c%c%c\n",
273 pc
[0], pc
[1], pc
[2], pc
[3]);
274 KEBUGCHECKEX(0, pc
[0], pc
[1], pc
[2], pc
[3]);
278 if (MPChecksum((PUCHAR
)Table
, Table
->Length
))
280 DPRINT1("Bad MP configuration block checksum\n");
285 if (Table
->Specification
!= 0x01 && Table
->Specification
!= 0x04)
287 DPRINT1("Bad MP configuration table version (%d)\n",
288 Table
->Specification
);
293 if (Table
->LocalAPICAddress
!= APIC_DEFAULT_BASE
)
295 DPRINT1("APIC base address is at 0x%X. I cannot handle non-standard adresses\n",
296 Table
->LocalAPICAddress
);
301 DPRINT("Oem: %.*s, ProductId: %.*s\n", 8, Table
->Oem
, 12, Table
->ProductId
);
302 DPRINT("APIC at: %08x\n", Table
->LocalAPICAddress
);
305 Entry
= (PUCHAR
)((ULONG_PTR
)Table
+ sizeof(MP_CONFIGURATION_TABLE
));
307 while (Count
< (Table
->Length
- sizeof(MP_CONFIGURATION_TABLE
)))
312 case MPCTE_PROCESSOR
:
314 HaliMPProcessorInfo((PMP_CONFIGURATION_PROCESSOR
)Entry
);
315 Entry
+= sizeof(MP_CONFIGURATION_PROCESSOR
);
316 Count
+= sizeof(MP_CONFIGURATION_PROCESSOR
);
321 HaliMPBusInfo((PMP_CONFIGURATION_BUS
)Entry
);
322 Entry
+= sizeof(MP_CONFIGURATION_BUS
);
323 Count
+= sizeof(MP_CONFIGURATION_BUS
);
328 HaliMPIOApicInfo((PMP_CONFIGURATION_IOAPIC
)Entry
);
329 Entry
+= sizeof(MP_CONFIGURATION_IOAPIC
);
330 Count
+= sizeof(MP_CONFIGURATION_IOAPIC
);
335 HaliMPIntSrcInfo((PMP_CONFIGURATION_INTSRC
)Entry
);
336 Entry
+= sizeof(MP_CONFIGURATION_INTSRC
);
337 Count
+= sizeof(MP_CONFIGURATION_INTSRC
);
342 HaliMPIntLocalInfo((PMP_CONFIGURATION_INTLOCAL
)Entry
);
343 Entry
+= sizeof(MP_CONFIGURATION_INTLOCAL
);
344 Count
+= sizeof(MP_CONFIGURATION_INTLOCAL
);
348 DPRINT1("Unknown entry in MPC table\n");
357 HaliConstructDefaultIOIrqMPTable(ULONG Type
)
359 MP_CONFIGURATION_INTSRC intsrc
;
362 intsrc
.Type
= MPCTE_INTSRC
;
363 intsrc
.IrqFlag
= 0; /* conforming */
365 intsrc
.DstApicId
= IOAPICMap
[0].ApicId
;
367 intsrc
.IrqType
= INT_VECTORED
;
368 for (i
= 0; i
< 16; i
++) {
371 if (i
== 0 || i
== 13)
372 continue; /* IRQ0 & IRQ13 not connected */
376 continue; /* IRQ2 is never connected */
379 intsrc
.SrcBusIrq
= i
;
380 intsrc
.DstApicInt
= i
? i
: 2; /* IRQ0 to INTIN2 */
381 HaliMPIntSrcInfo(&intsrc
);
384 intsrc
.IrqType
= INT_EXTINT
;
385 intsrc
.SrcBusIrq
= 0;
386 intsrc
.DstApicInt
= 0; /* 8259A to INTIN0 */
387 HaliMPIntSrcInfo(&intsrc
);
391 HaliConstructDefaultISAMPTable(ULONG Type
)
393 MP_CONFIGURATION_PROCESSOR processor
;
394 MP_CONFIGURATION_BUS bus
;
395 MP_CONFIGURATION_IOAPIC ioapic
;
396 MP_CONFIGURATION_INTLOCAL lintsrc
;
397 ULONG linttypes
[2] = { INT_EXTINT
, INT_NMI
};
401 * 2 CPUs, numbered 0 & 1.
403 processor
.Type
= MPCTE_PROCESSOR
;
404 /* Either an integrated APIC or a discrete 82489DX. */
405 processor
.ApicVersion
= Type
> 4 ? 0x10 : 0x01;
406 processor
.CpuFlags
= CPU_FLAG_ENABLED
| CPU_FLAG_BSP
;
407 /* FIXME: Get this from the bootstrap processor */
408 processor
.CpuSignature
= 0;
409 processor
.FeatureFlags
= 0;
410 processor
.Reserved
[0] = 0;
411 processor
.Reserved
[1] = 0;
412 for (i
= 0; i
< 2; i
++)
414 processor
.ApicId
= i
;
415 HaliMPProcessorInfo(&processor
);
416 processor
.CpuFlags
&= ~CPU_FLAG_BSP
;
419 bus
.Type
= MPCTE_BUS
;
424 DPRINT("Unknown standard configuration %d\n", Type
);
428 memcpy(bus
.BusType
, "ISA ", 6);
433 memcpy(bus
.BusType
, "EISA ", 6);
437 memcpy(bus
.BusType
, "MCA ", 6);
442 bus
.Type
= MPCTE_BUS
;
444 memcpy(bus
.BusType
, "PCI ", 6);
448 ioapic
.Type
= MPCTE_IOAPIC
;
450 ioapic
.ApicVersion
= Type
> 4 ? 0x10 : 0x01;
451 ioapic
.ApicFlags
= MP_IOAPIC_USABLE
;
452 ioapic
.ApicAddress
= IOAPIC_DEFAULT_BASE
;
453 HaliMPIOApicInfo(&ioapic
);
456 * We set up most of the low 16 IO-APIC pins according to MPS rules.
458 HaliConstructDefaultIOIrqMPTable(Type
);
460 lintsrc
.Type
= MPCTE_LINTSRC
;
462 lintsrc
.IrqFlag
= 0; /* conforming */
463 lintsrc
.SrcBusId
= 0;
464 lintsrc
.SrcBusIrq
= 0;
465 lintsrc
.DstApicId
= MP_APIC_ALL
;
466 for (i
= 0; i
< 2; i
++)
468 lintsrc
.IrqType
= linttypes
[i
];
469 lintsrc
.DstApicLInt
= i
;
470 HaliMPIntLocalInfo(&lintsrc
);
476 HaliScanForMPConfigTable(ULONG Base
,
481 Base = Base address of region
482 Size = Length of region to check
484 TRUE if a valid MP configuration table was found
487 PULONG bp
= (PULONG
)Base
;
488 MP_FLOATING_POINTER
* mpf
;
493 mpf
= (MP_FLOATING_POINTER
*)bp
;
494 if (mpf
->Signature
== MPF_SIGNATURE
)
496 Checksum
= MPChecksum((PUCHAR
)bp
, 16);
497 DPRINT("Found MPF signature at %x, checksum %x\n", bp
, Checksum
);
501 DPRINT("Intel MultiProcessor Specification v1.%d compliant system.\n",
504 if (mpf
->Feature2
& FEATURE2_IMCRP
)
506 DPRINT("Running in IMCR and PIC compatibility mode.\n");
510 DPRINT("Running in Virtual Wire compatibility mode.\n");
514 switch (mpf
->Feature1
)
517 /* Non standard configuration */
523 DPRINT("EISA with no IRQ8 chaining\n");
532 DPRINT("ISA and PCI\n");
535 DPRINT("EISA and PCI\n");
538 DPRINT("MCA and PCI\n");
541 DPRINT("Unknown standard configuration %d\n", mpf
->Feature1
);
555 HaliGetSmpConfig(VOID
)
562 if (Mpf
->Feature2
& FEATURE2_IMCRP
)
564 DPRINT("Running in IMCR and PIC compatibility mode.\n");
569 DPRINT("Running in Virtual Wire compatibility mode.\n");
573 if (Mpf
->Feature1
== 0 && Mpf
->Address
)
575 if(!HaliReadMPConfigTable((PMP_CONFIGURATION_TABLE
)Mpf
->Address
))
577 DPRINT("BIOS bug, MP table errors detected!...\n");
578 DPRINT("... disabling SMP support. (tell your hw vendor)\n");
583 MP_CONFIGURATION_BUS bus
;
585 DPRINT("BIOS bug, no explicit IRQ entries, using default mptable. (tell your hw vendor)\n");
588 memcpy(bus
.BusType
, "ISA ", 6);
590 HaliConstructDefaultIOIrqMPTable(bus
.BusId
);
594 else if(Mpf
->Feature1
!= 0)
596 HaliConstructDefaultISAMPTable(Mpf
->Feature1
);
606 HaliFindSmpConfig(VOID
)
609 Scan the system memory for an MP configuration table
610 1) Scan the first KB of system base memory
611 2) Scan the last KB of system base memory
612 3) Scan the BIOS ROM address space between 0F0000h and 0FFFFFh
613 4) Scan the first KB from the Extended BIOS Data Area
616 if (!HaliScanForMPConfigTable(0x0, 0x400))
618 if (!HaliScanForMPConfigTable(0x9FC00, 0x400))
620 if (!HaliScanForMPConfigTable(0xF0000, 0x10000))
622 if (!HaliScanForMPConfigTable(*((PUSHORT
)0x040E) << 4, 0x400))
624 DPRINT("No multiprocessor compliant system found.\n");
631 if (HaliGetSmpConfig())
637 DPRINT("No MP config table found\n");