2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
6 /* AROS Multi Processor Support Functions by NicJA. */
11 # include "cpu_intern.h"
14 /**********************************************************************/
15 void parse_MP_Processor (struct mpc_config_processor
*mc
, struct SMP_Definition
*SMP_Group
)
17 struct CPU_Definition
*ThisCPU
, *CPUList
;
18 struct i386_compat_intern
*ThisCPU_intern
= NULL
;
19 int cpuapicver
, apicid
= 0;
22 CPUList
= CPUBase
->CPUB_Processors
;
24 //apicid = mpc_apic_id(mc, translation_table[SMP_Group->SMP_RecordCount]);
26 kprintf(DEBUG_NAME_STR
": Parsing MP Processor Features :-\n");
28 if (mc
->mpc_featureflag
&(1<<0)) kprintf(DEBUG_NAME_STR
": *Floating point unit present.\n");
29 if (mc
->mpc_featureflag
&(1<<7)) kprintf(DEBUG_NAME_STR
": *Machine Exception supported.\n");
30 if (mc
->mpc_featureflag
&(1<<8)) kprintf(DEBUG_NAME_STR
": *64 bit compare & exchange supported.\n");
31 if (mc
->mpc_featureflag
&(1<<9)) kprintf(DEBUG_NAME_STR
": *Internal APIC present.\n");
32 if (mc
->mpc_featureflag
&(1<<11)) kprintf(DEBUG_NAME_STR
": *SEP present.\n");
33 if (mc
->mpc_featureflag
&(1<<12)) kprintf(DEBUG_NAME_STR
": *MTRR present.\n");
34 if (mc
->mpc_featureflag
&(1<<13)) kprintf(DEBUG_NAME_STR
": *PGE present.\n");
35 if (mc
->mpc_featureflag
&(1<<14)) kprintf(DEBUG_NAME_STR
": *MCA present.\n");
36 if (mc
->mpc_featureflag
&(1<<15)) kprintf(DEBUG_NAME_STR
": *CMOV present.\n");
37 if (mc
->mpc_featureflag
&(1<<16)) kprintf(DEBUG_NAME_STR
": *PAT present.\n");
38 if (mc
->mpc_featureflag
&(1<<17)) kprintf(DEBUG_NAME_STR
": *PSE present.\n");
39 if (mc
->mpc_featureflag
&(1<<18)) kprintf(DEBUG_NAME_STR
": *PSN present.\n");
40 if (mc
->mpc_featureflag
&(1<<19)) kprintf(DEBUG_NAME_STR
": *Cache Line Flush Instruction present.\n");
42 if (mc
->mpc_featureflag
&(1<<21)) kprintf(DEBUG_NAME_STR
": *Debug Trace and EMON Store present.\n");
43 if (mc
->mpc_featureflag
&(1<<22)) kprintf(DEBUG_NAME_STR
": *ACPI Thermal Throttle Registers present.\n");
44 if (mc
->mpc_featureflag
&(1<<23)) kprintf(DEBUG_NAME_STR
": *MMX present.\n");
45 if (mc
->mpc_featureflag
&(1<<24)) kprintf(DEBUG_NAME_STR
": *FXSR present.\n");
46 if (mc
->mpc_featureflag
&(1<<25)) kprintf(DEBUG_NAME_STR
": *XMM present.\n");
47 if (mc
->mpc_featureflag
&(1<<26)) kprintf(DEBUG_NAME_STR
": *Willamette New Instructions present.\n");
48 if (mc
->mpc_featureflag
&(1<<27)) kprintf(DEBUG_NAME_STR
": *Self Snoop present.\n");
49 if (mc
->mpc_featureflag
&(1<<28)) kprintf(DEBUG_NAME_STR
": *HT present.\n");
50 if (mc
->mpc_featureflag
&(1<<29)) kprintf(DEBUG_NAME_STR
": *Thermal Monitor present.\n");
53 /*if (SMP_Group->SMP_CPUCount >= MAX_CPU)
55 kprintf(DEBUG_NAME_STR ": WARNING - Reached MAX_CPU count [%i]. CPU(apicid 0x%x) not booted.\n", MAX_CPU, mc->mpc_apicid);
59 if (MAX_APICS
- mc
->mpc_apicid
<= 0)
61 kprintf(DEBUG_NAME_STR
": WARNING - INVALID Processor [#%d - Max ID: %d].\n", mc
->mpc_apicid
, MAX_APICS
);
65 if (mc
->mpc_cpuflag
& CPU_BOOTPROCESSOR
)
67 kprintf(DEBUG_NAME_STR
": Bootup CPU\n"); /* CPU booted system.. */
68 CPUBase
->CPUB_BOOT_Physical
= mc
->mpc_apicid
;
69 CPUBase
->CPUB_BOOT_Logical
= apicid
;
70 ThisCPU
= (struct CPU_Definition
*)CPUList
->CPU_CPUList
.mlh_Head
;
71 ThisCPU
->CPU_Physical
= mc
->mpc_apicid
;
72 ThisCPU
->CPU_Enabled
= TRUE
; /* got to be enabled or we wouldnt be here.. */
73 ThisCPU
->CPU_IsOnline
= TRUE
; /* CPU is online .. */
74 ThisCPU
->CPU_BootCPU
= TRUE
;
75 ThisCPU
->CPU_SMPGroup
= (ULONG
*)SMP_Group
;
76 kprintf(DEBUG_NAME_STR
": CPU List item for BOOT CPU updated..[PhysicalID=%d]!\n", ThisCPU
->CPU_Physical
);
80 ThisCPU
= AllocMem( sizeof(struct CPU_Definition
), MEMF_CLEAR
| MEMF_PUBLIC
); /* Add this CPU to the CPU List */
84 kprintf(DEBUG_NAME_STR
":ERROR - Couldnt allocate CPU list item memory!\n");
88 CPUList
->CPU_Physical
+= 1; /* Increment the System Processor count */
90 ThisCPU
->CPU_Family
= CPU_Family_i386
; /* we are i386 compatable.. */
91 ThisCPU
->CPU_Model
= CPU_i386_386
; /* will probe more later .. */
92 ThisCPU
->CPU_Physical
= mc
->mpc_apicid
;
93 ThisCPU
->CPU_Enabled
= (mc
->mpc_cpuflag
& CPU_ENABLED
);
94 ThisCPU
->CPU_ID
= CPUList
->CPU_Physical
; /* we are the only CPU at this time .. */
95 ThisCPU
->CPU_IsOnline
= FALSE
; /* CPU is online .. */
96 ThisCPU
->CPU_BootCPU
= FALSE
; /* CPU bootd system.. */
97 ThisCPU
->CPU_SMPGroup
= (ULONG
*)SMP_Group
;
99 kprintf(DEBUG_NAME_STR
": New CPU List item created @ %p, for [PhysicalID=%d]\n", ThisCPU_intern
, ThisCPU
->CPU_Physical
);
101 ThisCPU_intern
= AllocMem(sizeof(struct i386_compat_intern
), MEMF_CLEAR
| MEMF_PUBLIC
); /* Create its per CPU internal struct */
103 if( ThisCPU_intern
== NULL
)
105 kprintf(DEBUG_NAME_STR
":ERROR - Couldnt allocate CPU private struct!\n");
109 kprintf(DEBUG_NAME_STR
": i386 private structure allocated @ %p\n",ThisCPU_intern
);
110 ThisCPU
->CPU_Private1
= ThisCPU_intern
; /* We dont fill it in yet - probed l8r */
112 AddTail((struct List
*)&CPUList
->CPU_CPUList
,(struct Node
*)&ThisCPU
->CPU_CPUList
); /* Add the CPU to the system List */
116 SMP_Group
->SMP_CPUCount
+= 1; /* Increment the groups CPU count */
118 cpuapicver
= mc
->mpc_apicver
;
120 //tmp = apicid_to_cpu_present(apicid);
121 //physids_or(phys_cpu_present_map, phys_cpu_present_map, tmp);
123 /* Validate version */
124 if ( cpuapicver
== 0x0 )
126 kprintf(DEBUG_NAME_STR
": WARNING - BIOS bug, APIC version is 0 for CPU#%d! fixing up to 0x10. (tell your hw vendor)\n", mc
->mpc_apicid
);
130 //apic_version[m->mpc_apicid] = ver;
131 //bios_cpu_apicid[num_processors - 1] = m->mpc_apicid;
134 void parse_MP_IOAPIC (struct mpc_config_ioapic
*mc
, struct SMP_Definition
*SMP_Group
)
136 if (!(mc
->mpc_flags
& MPC_APIC_USABLE
)) return;
138 kprintf(DEBUG_NAME_STR
": I/O APIC #%d Version %d at 0x%lX.\n", mc
->mpc_apicid
, mc
->mpc_apicver
, mc
->mpc_apicaddr
);
140 //if (nr_ioapics >= MAX_IO_APICS)
142 // kprintf(DEBUG_NAME_STR ": CRITICAL - Max # of I/O APICs (%d) exceeded (found %d).\n",MAX_IO_APICS, nr_ioapics);
145 if (!mc
->mpc_apicaddr
)
147 kprintf(DEBUG_NAME_STR
":ERROR - bogus zero I/O APIC address found in MP table, skipping!\n");
151 //mp_ioapics[nr_ioapics] = *mc;
155 void parse_MP_IntSrc (struct mpc_config_intsrc
*mc
, struct SMP_Definition
*SMP_Group
)
157 //mp_irqs [mp_irq_entries] = *mc;
158 kprintf(DEBUG_NAME_STR
": Int: type %d, pol %d, trig %d, bus %d, IRQ %02x, APIC ID %x, APIC INT %02x\n", mc
->mpc_irqtype
, mc
->mpc_irqflag
& 3, (mc
->mpc_irqflag
>> 2) & 3, mc
->mpc_srcbus
, mc
->mpc_srcbusirq
, mc
->mpc_dstapic
, mc
->mpc_dstirq
);
160 /* TODO: Replace the following print with ALERT */
161 //if (++mp_irq_entries == MAX_IRQ_SOURCES) kprintf(DEBUG_NAME_STR ": DIE HERE!!! (BUG) ");
164 void parse_MP_LIntSrc (struct mpc_config_lintsrc
*mc
, struct SMP_Definition
*SMP_Group
)
166 kprintf(DEBUG_NAME_STR
": Lint: type %d, pol %d, trig %d, bus %d, IRQ %02x, APIC ID %x, APIC LINT %02x\n", mc
->mpc_irqtype
, mc
->mpc_irqflag
& 3, (mc
->mpc_irqflag
>> 2) &3, mc
->mpc_srcbusid
, mc
->mpc_srcbusirq
, mc
->mpc_destapic
, mc
->mpc_destapiclint
);
168 Apparently all exisitng SMP boards use ExtINT/LVT1 == LINT0 and NMI/LVT2 == LINT1
169 The following check will show us if this assumptions is false. Until then we do not have to add baggage.
171 /* TODO: Replace the following prints with ALERTS */
173 if ((mc
->mpc_irqtype
== mp_ExtINT
) && (mc
->mpc_destapiclint
!= 0)) kprintf(DEBUG_NAME_STR
": DIE HERE!!! (BUG) ");//BUG();
175 if ((mc
->mpc_irqtype
== mp_NMI
) && (mc
->mpc_destapiclint
!= 1)) kprintf(DEBUG_NAME_STR
": DIE HERE!!! (BUG) ");//BUG();
178 void parse_MP_Bus (struct mpc_config_bus
*mc
, struct SMP_Definition
*SMP_Group
)
182 memcpy(str
, mc
->mpc_bustype
, 6);
185 /* TODO: Implemenet parse_MP_Bus */
186 //mpc_oem_bus_info(mc, str, translation_table[SMP_Group->SMP_RecordCount]);
188 //if (strncmp(str, BUSTYPE_ISA, sizeof(BUSTYPE_ISA)-1) == 0)
190 // mp_bus_id_to_type[mc->mpc_busid] = MP_BUS_ISA;
192 //else if (strncmp(str, BUSTYPE_EISA, sizeof(BUSTYPE_EISA)-1) == 0) mp_bus_id_to_type[mc->mpc_busid] = MP_BUS_EISA;
193 //else if (strncmp(str, BUSTYPE_PCI, sizeof(BUSTYPE_PCI)-1) == 0)
195 // mpc_oem_pci_bus(mc, translation_table[SMP_Group->SMP_RecordCount]);
196 // mp_bus_id_to_type[mc->mpc_busid] = MP_BUS_PCI;
197 // mp_bus_id_to_pci_bus[mc->mpc_busid] = mp_current_pci_id;
198 // mp_current_pci_id++;
200 //else if (strncmp(str, BUSTYPE_MCA, sizeof(BUSTYPE_MCA)-1) == 0) mp_bus_id_to_type[mc->mpc_busid] = MP_BUS_MCA;
201 //else if (strncmp(str, BUSTYPE_NEC98, sizeof(BUSTYPE_NEC98)-1) == 0) mp_bus_id_to_type[mc->mpc_busid] = MP_BUS_NEC98;
202 //else kprintf(DEBUG_NAME_STR ": WARNING - Unknown bustype %s - ignoring\n", str);
205 void parse_MP_Translation (struct mpc_config_translation
*mc
, struct SMP_Definition
*SMP_Group
)
207 kprintf(DEBUG_NAME_STR
": Translation: record %d, type %d, quad %d, global %d, local %d\n", SMP_Group
->SMP_RecordCount
, mc
->trans_type
, mc
->trans_quad
, mc
->trans_global
, mc
->trans_local
);
209 if (SMP_Group
->SMP_RecordCount
>= MAX_MPC_ENTRY
) kprintf(DEBUG_NAME_STR
": ERROR - MAX_MPC_ENTRY exceeded!\n");
210 //else translation_table[SMP_Group->SMP_RecordCount] = mc; /* stash this for later */
212 //if (mc->trans_quad+1 > numnodes) numnodes = mc->trans_quad+1;
215 /**************************************************************************/
217 int mpfcb_checksum(unsigned char *mpcb
, int len
)
219 int sum
= 0; /* Quickly grab the checksum of the config block */
221 while (len
--) sum
+= *mpcb
++;
226 /**************************************************************************/
228 void smp_read_mpc_oem(struct mp_config_oemtable
*oemtable
, unsigned short oemsize
, struct SMP_Definition
*SMP_Group
)
230 int count
= sizeof (*oemtable
); /* the header size */
231 unsigned char *oemptr
= ((unsigned char *)oemtable
)+count
;
233 SMP_Group
->SMP_RecordCount
= 0;
234 kprintf(DEBUG_NAME_STR
": Found an OEM MPC table at %8p - parsing it ... \n", oemtable
);
236 if (memcmp(oemtable
->oem_signature
,MPC_OEM_SIGNATURE
,4))
238 kprintf(DEBUG_NAME_STR
": WARNING - SMP mpc oemtable: bad signature [%c%c%c%c]!\n", oemtable
->oem_signature
[0], oemtable
->oem_signature
[1], oemtable
->oem_signature
[2], oemtable
->oem_signature
[3]);
242 if (mpfcb_checksum((unsigned char *)oemtable
,oemtable
->oem_length
))
244 kprintf(DEBUG_NAME_STR
": WARNING - SMP oem mptable: checksum error\n");
248 while (count
< oemtable
->oem_length
)
253 struct mpc_config_translation
*mc
=(struct mpc_config_translation
*)oemptr
;
254 parse_MP_Translation( mc
, SMP_Group
);
255 oemptr
+= sizeof(*mc
);
256 count
+= sizeof(*mc
);
257 ++SMP_Group
->SMP_RecordCount
;
262 kprintf(DEBUG_NAME_STR
": WARNING - Unrecognised OEM table entry type - %d\n", (int) *oemptr
);
269 void mps_oem_check(struct mp_config_table
*mpcf
, char *oem
, char *productid
, struct SMP_Definition
*SMP_Group
)
271 if (strncmp(oem
, "IBM NUMA", 8)) kprintf( DEBUG_NAME_STR
": WARNING - May not be a NUMA-Q system.\n");
272 if (mpcf
->mpc_oemptr
) smp_read_mpc_oem((struct mp_config_oemtable
*) mpcf
->mpc_oemptr
, mpcf
->mpc_oemsize
, SMP_Group
);
275 /****************************************************************************************/
276 /* We are called very early to get the low memory for the SMP bootup trampoline page. */
278 int smp_alloc_memory(void)
280 ULONG trampoline_base
;
281 /* TODO: properly allocate SMP memory */
282 //if ( ( trampoline_base = (void *) alloc_bootmem_low_pages(PAGE_SIZE)) >= 0x0009F000) /* Has to be in very low memory so we can execute real-mode AP code. */
284 trampoline_base
= 0x0009E000;
287 return trampoline_base
;
290 /**************************************************************************/
292 APTR
scan_for_smpconfig (APTR base
, unsigned long length
)
294 ULONG
*basepointer
= base
;
295 struct intel_mp_confblock
*mpcfb
;
297 kprintf(DEBUG_NAME_STR
": Scan for SMP = %p for %ld bytes.\n", basepointer
,length
);
301 mpcfb
= (struct intel_mp_confblock
*)basepointer
;
303 if ((*basepointer
== SMP_MAGIC_IDENT
))
305 if ( (mpcfb
->mpcf_length
== 1) && !mpfcb_checksum( (unsigned char *)basepointer
, 16) )
307 if ( ( ( mpcfb
->mpcf_specification
== 1 ) || ( mpcfb
->mpcf_specification
== 4 ) ) )
320 APTR
find_smp_config (void)
324 if ((confAddr
= scan_for_smpconfig((APTR
)0x00000000,0x400))) return confAddr
; /* Scan the bottom 1K for a signature */
325 if ((confAddr
= scan_for_smpconfig((APTR
)0x0009FC00,0x400))) return confAddr
; /* Scan the top 1K of base RAM (639*0x400) */
326 if ((confAddr
= scan_for_smpconfig((APTR
)0x000F0000,0x10000))) return confAddr
; /* Scan the 64K of bios */
328 /* If it is an SMP machine we should know now, unless the
329 configuration is in an EISA/MCA bus machine with an
330 extended bios data area.
332 there is a real-mode segmented pointer pointing to the
333 4K EBDA area at 0x0000040E, calculate and scan it here.
335 Some Linux loaders corrupt the EBDA area, so this kind
336 of SMP config may be less reliable, because the SMP
337 table may have been corrupted during early boot. These
338 loaders are buggy and should be fixed. */
340 confAddr
= (APTR
)(((IPTR
)*(UWORD
*)(0x0000040E)) << 4);
341 return scan_for_smpconfig(confAddr
, 0x1000);
344 void get_smp_config ( struct intel_mp_confblock
*mpcfb
, struct CPUBase
*CPUBase
)
346 struct SMP_Definition
*SMP_Group
;
347 BOOL SMPERROR
= FALSE
;
350 kprintf(DEBUG_NAME_STR
": Processing SMP config...\n");
353 ACPI may be used to obtain the entire SMP configuration or just to
354 enumerate/configure processors (CONFIG_ACPI_HT).
356 Note that ACPI supports both logical (e.g. Hyper-Threading) and physical
357 processors, where MPS only supports physical. */
362 kprintf(DEBUG_NAME_STR
": FIXME: Use ACPI (MADT) for SMP configuration information\n");
365 kprintf(DEBUG_NAME_STR
": Intel MultiProcessor Specification v1.%d\n", mpcfb
->mpcf_specification
);
367 if (mpcfb
->mpcf_feature2
& (1<<7)) /* test bit 7 (IMCR|PIC) */
369 kprintf(DEBUG_NAME_STR
": IMCR and PIC compatibility mode.\n");
374 kprintf(DEBUG_NAME_STR
": Virtual Wire compatibility mode.\n");
378 /* Now see if we need to read further. */
379 if (mpcfb
->mpcf_feature1
!= 0)
381 kprintf(DEBUG_NAME_STR
": Default MP configuration #%d\n", mpcfb
->mpcf_feature1
);
382 //construct_default_ISA_mptable(mpf->mpf_feature1);
384 else if (mpcfb
->mpcf_physptr
)
387 /* Read the physical hardware table. Anything here will override the defaults. */
388 if (!(SMP_Group
= smp_read_mpcfb((void *)mpcfb
->mpcf_physptr
, CPUBase
)) )
391 kprintf(DEBUG_NAME_STR
": ERROR - BIOS bug, MP table errors detected!...\n");
394 SMP_Group
->SMP_PIC_Mode
= pic_mode
;
397 If there are no explicit MP IRQ entries, then we are
398 broken. We set up most of the low 16 IO-APIC pins to
399 ISA defaults and hope it will work. */
401 /*if (!mp_irq_entries)
403 struct mpc_config_bus bus;
405 kprintf(DEBUG_NAME_STR ": BIOS bug, no explicit IRQ entries, using default mptable. (tell your hw vendor)\n");
407 bus.mpc_type = MP_BUS;
409 memcpy(bus.mpc_bustype, "ISA ", 6);
412 construct_default_ioirq_mptable(0);
416 else SMPERROR
= TRUE
;
418 if ( SMPERROR
== TRUE
)
421 kprintf(DEBUG_NAME_STR
": ERROR - disabling SMP support. (tell your hw vendor)\n");
423 else kprintf(DEBUG_NAME_STR
": Processors: %d\n", SMP_Group
->SMP_CPUCount
);
424 /* Only use the first configuration found. */
427 struct SMP_Definition
*smp_read_mpcfb(struct mp_config_table
*mpcf
, struct CPUBase
*CPUBase
)
431 int count
= sizeof(*mpcf
);
432 unsigned char *mpt
= ((unsigned char *)mpcf
) + count
;
433 struct SMP_Definition
*SMP_Group
;
438 if (memcmp(mpcf
->mpc_signature
,MPC_SIGNATURE
,4))
440 kprintf(DEBUG_NAME_STR
": ERROR - SMP mptable: bad signature [0x%x]!\n", *(ULONG
*)mpcf
->mpc_signature
);
444 if (mpfcb_checksum((unsigned char *)mpcf
,mpcf
->mpc_length
))
446 kprintf(DEBUG_NAME_STR
": ERROR - SMP mptable: checksum error!\n");
450 if (mpcf
->mpc_spec
!= 0x01 && mpcf
->mpc_spec
!= 0x04)
452 kprintf(DEBUG_NAME_STR
": ERROR - SMP mptable: bad table version (%d)!!\n",mpcf
->mpc_spec
);
456 if (!mpcf
->mpc_lapic
)
458 kprintf(DEBUG_NAME_STR
": ERROR - SMP mptable: null local APIC address!\n");
462 /* Create the SMP group block */
463 SMP_Group
= AllocMem( sizeof(struct SMP_Definition
), MEMF_CLEAR
| MEMF_PUBLIC
);
464 if (CPUBase
->CPUB_SMP_Groups
)
466 AddTail((struct List
*)CPUBase
->CPUB_SMP_Groups
,(struct Node
*)&SMP_Group
->SMP_SMPList
); /* Add this SMP group to the list */
467 kprintf(DEBUG_NAME_STR
": SMP Group Item @ 0x%p, Inserted into List @ 0x%p\n",&SMP_Group
->SMP_SMPList
,CPUBase
->CPUB_SMP_Groups
);
469 InitSemaphore( &SMP_Group
->SMP_GrpLock
);
470 kprintf(DEBUG_NAME_STR
": Initialised SMP Group Semaphore\n");
474 NEWLIST((struct List
*)&(SMP_Group
->SMP_SMPList
)); /* Create This SMP group list */
475 kprintf(DEBUG_NAME_STR
": First SMP List & Group created @ 0x%p\n",&SMP_Group
->SMP_SMPList
);
477 InitSemaphore( &SMP_Group
->SMP_GrpLock
);
478 kprintf(DEBUG_NAME_STR
": Initialised SMP Group Semaphore\n");
480 CPUBase
->CPUB_SMP_Groups
= SMP_Group
;
483 memcpy(oem
,mpcf
->mpc_oem
,8);
486 memcpy(str
,mpcf
->mpc_productid
,12);
489 kprintf(DEBUG_NAME_STR
": OEM ID: %s Product ID: %s \n",oem
,str
);
491 mps_oem_check( mpcf
, oem
, str
, SMP_Group
);
493 kprintf(DEBUG_NAME_STR
": APIC at: 0x%lX\n",mpcf
->mpc_lapic
);
495 /* Save the local APIC address (it might be non-default) - though only if we're not using ACPI. */
496 SMP_Group
->SMP_APIC
= (APTR
)mpcf
->mpc_lapic
;
498 /* Now process the configuration blocks. */
500 SMP_Group
->SMP_RecordCount
= 0;
501 while (count
< mpcf
->mpc_length
)
507 struct mpc_config_processor
*mc
= (struct mpc_config_processor
*)mpt
;
509 parse_MP_Processor( mc
, SMP_Group
); /* ACPI may have already provided this data */
511 mpt
+= sizeof( *mc
);
512 count
+= sizeof( *mc
);
517 struct mpc_config_ioapic
*mc
= (struct mpc_config_ioapic
*)mpt
;
519 parse_MP_IOAPIC( mc
, SMP_Group
);
520 mpt
+= sizeof( *mc
);
521 count
+= sizeof( *mc
);
526 struct mpc_config_intsrc
*mc
= (struct mpc_config_intsrc
*)mpt
;
528 parse_MP_IntSrc( mc
, SMP_Group
);
529 mpt
+= sizeof( *mc
);
530 count
+= sizeof( *mc
);
535 struct mpc_config_lintsrc
*mc
= (struct mpc_config_lintsrc
*)mpt
;
537 parse_MP_LIntSrc( mc
, SMP_Group
);
538 mpt
+= sizeof( *mc
);
539 count
+= sizeof( *mc
);
544 struct mpc_config_bus
*mc
= (struct mpc_config_bus
*)mpt
;
546 parse_MP_Bus( mc
, SMP_Group
);
547 mpt
+= sizeof( *mc
);
548 count
+= sizeof( *mc
);
553 count
= mpcf
->mpc_length
;
557 ++SMP_Group
->SMP_RecordCount
;
560 //clustered_apic_check();
561 if (!SMP_Group
->SMP_CPUCount
) kprintf(DEBUG_NAME_STR
": SMP mptable - NO Processors Registered!\n");
565 /**************************************************************************/