NOTE => NOTES
[AROS.git] / arch / i386-pc / cpu / smp.c
blob454068fe346c5250c83dbc6e054a54942978db50
1 /* AROS Multi Processor Support Functions by NicJA. */
2 #ifndef _SMP_C
3 #define _SMP_C
5 #ifndef _CPU_INTERN_H
6 # include "cpu_intern.h"
7 #endif
9 /**********************************************************************/
10 void parse_MP_Processor (struct mpc_config_processor *mc, struct SMP_Definition *SMP_Group )
12 struct CPU_Definition *ThisCPU, *CPUList;
13 struct i386_compat_intern *ThisCPU_intern;
14 int cpuapicver, apicid;
15 //physid_mask_t tmp;
17 CPUList = CPUBase->CPUB_Processors;
19 //apicid = mpc_apic_id(mc, translation_table[SMP_Group->SMP_RecordCount]);
21 kprintf(DEBUG_NAME_STR ": Parsing MP Processor Features :-\n");
23 if (mc->mpc_featureflag&(1<<0)) kprintf(DEBUG_NAME_STR ": *Floating point unit present.\n");
24 if (mc->mpc_featureflag&(1<<7)) kprintf(DEBUG_NAME_STR ": *Machine Exception supported.\n");
25 if (mc->mpc_featureflag&(1<<8)) kprintf(DEBUG_NAME_STR ": *64 bit compare & exchange supported.\n");
26 if (mc->mpc_featureflag&(1<<9)) kprintf(DEBUG_NAME_STR ": *Internal APIC present.\n");
27 if (mc->mpc_featureflag&(1<<11)) kprintf(DEBUG_NAME_STR ": *SEP present.\n");
28 if (mc->mpc_featureflag&(1<<12)) kprintf(DEBUG_NAME_STR ": *MTRR present.\n");
29 if (mc->mpc_featureflag&(1<<13)) kprintf(DEBUG_NAME_STR ": *PGE present.\n");
30 if (mc->mpc_featureflag&(1<<14)) kprintf(DEBUG_NAME_STR ": *MCA present.\n");
31 if (mc->mpc_featureflag&(1<<15)) kprintf(DEBUG_NAME_STR ": *CMOV present.\n");
32 if (mc->mpc_featureflag&(1<<16)) kprintf(DEBUG_NAME_STR ": *PAT present.\n");
33 if (mc->mpc_featureflag&(1<<17)) kprintf(DEBUG_NAME_STR ": *PSE present.\n");
34 if (mc->mpc_featureflag&(1<<18)) kprintf(DEBUG_NAME_STR ": *PSN present.\n");
35 if (mc->mpc_featureflag&(1<<19)) kprintf(DEBUG_NAME_STR ": *Cache Line Flush Instruction present.\n");
36 /* 20 Reserved */
37 if (mc->mpc_featureflag&(1<<21)) kprintf(DEBUG_NAME_STR ": *Debug Trace and EMON Store present.\n");
38 if (mc->mpc_featureflag&(1<<22)) kprintf(DEBUG_NAME_STR ": *ACPI Thermal Throttle Registers present.\n");
39 if (mc->mpc_featureflag&(1<<23)) kprintf(DEBUG_NAME_STR ": *MMX present.\n");
40 if (mc->mpc_featureflag&(1<<24)) kprintf(DEBUG_NAME_STR ": *FXSR present.\n");
41 if (mc->mpc_featureflag&(1<<25)) kprintf(DEBUG_NAME_STR ": *XMM present.\n");
42 if (mc->mpc_featureflag&(1<<26)) kprintf(DEBUG_NAME_STR ": *Willamette New Instructions present.\n");
43 if (mc->mpc_featureflag&(1<<27)) kprintf(DEBUG_NAME_STR ": *Self Snoop present.\n");
44 if (mc->mpc_featureflag&(1<<28)) kprintf(DEBUG_NAME_STR ": *HT present.\n");
45 if (mc->mpc_featureflag&(1<<29)) kprintf(DEBUG_NAME_STR ": *Thermal Monitor present.\n");
46 /* 30, 31 Reserved */
48 /*if (SMP_Group->SMP_CPUCount >= MAX_CPU)
50 kprintf(DEBUG_NAME_STR ": WARNING - Reached MAX_CPU count [%i]. CPU(apicid 0x%x) not booted.\n", MAX_CPU, mc->mpc_apicid);
51 return;
52 }*/
54 if (MAX_APICS - mc->mpc_apicid <= 0)
56 kprintf(DEBUG_NAME_STR ": WARNING - INVALID Processor [#%d - Max ID: %d].\n", mc->mpc_apicid, MAX_APICS);
57 return;
60 if (mc->mpc_cpuflag & CPU_BOOTPROCESSOR)
62 kprintf(DEBUG_NAME_STR ": Bootup CPU\n"); /* CPU booted system.. */
63 CPUBase->CPUB_BOOT_Physical = mc->mpc_apicid;
64 CPUBase->CPUB_BOOT_Logical = apicid;
65 ThisCPU = (struct CPU_Definition *)CPUList->CPU_CPUList.mlh_Head;
66 ThisCPU->CPU_Physical = mc->mpc_apicid;
67 ThisCPU->CPU_Enabled = TRUE; /* got to be enabled or we wouldnt be here.. */
68 ThisCPU->CPU_IsOnline = TRUE; /* CPU is online .. */
69 ThisCPU->CPU_BootCPU = TRUE;
70 ThisCPU->CPU_SMPGroup = SMP_Group;
71 kprintf(DEBUG_NAME_STR ": CPU List item for BOOT CPU updated..[PhysicalID=%d]!\n", ThisCPU->CPU_Physical);
73 else
75 ThisCPU = AllocMem( sizeof(struct CPU_Definition), MEMF_CLEAR | MEMF_PUBLIC ); /* Add this CPU to the CPU List */
77 if( ThisCPU == NULL )
79 kprintf(DEBUG_NAME_STR ":ERROR - Couldnt allocate CPU list item memory!\n");
81 else
83 CPUList->CPU_Physical += 1; /* Increment the System Processor count */
85 ThisCPU->CPU_Family = CPU_Family_i386; /* we are i386 compatable.. */
86 ThisCPU->CPU_Model = CPU_i386_386; /* will probe more later .. */
87 ThisCPU->CPU_Physical = mc->mpc_apicid;
88 ThisCPU->CPU_Enabled = (mc->mpc_cpuflag & CPU_ENABLED);
89 ThisCPU->CPU_ID = CPUList->CPU_Physical; /* we are the only CPU at this time .. */
90 ThisCPU->CPU_IsOnline = FALSE; /* CPU is online .. */
91 ThisCPU->CPU_BootCPU = FALSE; /* CPU bootd system.. */
92 ThisCPU->CPU_SMPGroup = SMP_Group;
94 kprintf(DEBUG_NAME_STR ": New CPU List item created @ %p, for [PhysicalID=%d]\n", ThisCPU_intern, ThisCPU->CPU_Physical);
96 ThisCPU_intern = AllocMem(sizeof(struct i386_compat_intern), MEMF_CLEAR | MEMF_PUBLIC ); /* Create its per CPU internal struct */
98 if( ThisCPU_intern == NULL )
100 kprintf(DEBUG_NAME_STR ":ERROR - Couldnt allocate CPU private struct!\n");
102 else
104 kprintf(DEBUG_NAME_STR ": i386 private structure allocated @ %p\n",ThisCPU_intern);
105 ThisCPU->CPU_Private1 = ThisCPU_intern; /* We dont fill it in yet - probed l8r */
107 AddTail(&CPUList->CPU_CPUList,&ThisCPU->CPU_CPUList); /* Add the CPU to the system List */
111 SMP_Group->SMP_CPUCount += 1; /* Increment the groups CPU count */
113 cpuapicver = mc->mpc_apicver;
115 //tmp = apicid_to_cpu_present(apicid);
116 //physids_or(phys_cpu_present_map, phys_cpu_present_map, tmp);
118 /* Validate version */
119 if ( cpuapicver == 0x0 )
121 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);
122 cpuapicver = 0x10;
125 //apic_version[m->mpc_apicid] = ver;
126 //bios_cpu_apicid[num_processors - 1] = m->mpc_apicid;
129 void parse_MP_IOAPIC (struct mpc_config_ioapic *mc, struct SMP_Definition *SMP_Group )
131 if (!(mc->mpc_flags & MPC_APIC_USABLE)) return;
133 kprintf(DEBUG_NAME_STR ": I/O APIC #%d Version %d at 0x%lX.\n", mc->mpc_apicid, mc->mpc_apicver, mc->mpc_apicaddr);
135 //if (nr_ioapics >= MAX_IO_APICS)
137 // kprintf(DEBUG_NAME_STR ": CRITICAL - Max # of I/O APICs (%d) exceeded (found %d).\n",MAX_IO_APICS, nr_ioapics);
140 if (!mc->mpc_apicaddr)
142 kprintf(DEBUG_NAME_STR ":ERROR - bogus zero I/O APIC address found in MP table, skipping!\n");
143 return;
146 //mp_ioapics[nr_ioapics] = *mc;
147 //nr_ioapics++;
150 void parse_MP_IntSrc (struct mpc_config_intsrc *mc, struct SMP_Definition *SMP_Group )
152 //mp_irqs [mp_irq_entries] = *mc;
153 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);
155 #warning TODO: Replace the following print with ALERT
156 //if (++mp_irq_entries == MAX_IRQ_SOURCES) kprintf(DEBUG_NAME_STR ": DIE HERE!!! (BUG) ");
159 void parse_MP_LIntSrc (struct mpc_config_lintsrc *mc, struct SMP_Definition *SMP_Group )
161 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);
163 Apparently all exisitng SMP boards use ExtINT/LVT1 == LINT0 and NMI/LVT2 == LINT1
164 The following check will show us if this assumptions is false. Until then we do not have to add baggage.
166 #warning TODO: Replace the following prints with ALERTS
168 if ((mc->mpc_irqtype == mp_ExtINT) && (mc->mpc_destapiclint != 0)) kprintf(DEBUG_NAME_STR ": DIE HERE!!! (BUG) ");//BUG();
170 if ((mc->mpc_irqtype == mp_NMI) && (mc->mpc_destapiclint != 1)) kprintf(DEBUG_NAME_STR ": DIE HERE!!! (BUG) ");//BUG();
173 void parse_MP_Bus (struct mpc_config_bus *mc, struct SMP_Definition *SMP_Group )
175 char str[7];
177 memcpy(str, mc->mpc_bustype, 6);
178 str[6] = 0;
180 #warning TODO: Implemenet parse_MP_Bus
181 //mpc_oem_bus_info(mc, str, translation_table[SMP_Group->SMP_RecordCount]);
183 //if (strncmp(str, BUSTYPE_ISA, sizeof(BUSTYPE_ISA)-1) == 0)
185 // mp_bus_id_to_type[mc->mpc_busid] = MP_BUS_ISA;
187 //else if (strncmp(str, BUSTYPE_EISA, sizeof(BUSTYPE_EISA)-1) == 0) mp_bus_id_to_type[mc->mpc_busid] = MP_BUS_EISA;
188 //else if (strncmp(str, BUSTYPE_PCI, sizeof(BUSTYPE_PCI)-1) == 0)
190 // mpc_oem_pci_bus(mc, translation_table[SMP_Group->SMP_RecordCount]);
191 // mp_bus_id_to_type[mc->mpc_busid] = MP_BUS_PCI;
192 // mp_bus_id_to_pci_bus[mc->mpc_busid] = mp_current_pci_id;
193 // mp_current_pci_id++;
195 //else if (strncmp(str, BUSTYPE_MCA, sizeof(BUSTYPE_MCA)-1) == 0) mp_bus_id_to_type[mc->mpc_busid] = MP_BUS_MCA;
196 //else if (strncmp(str, BUSTYPE_NEC98, sizeof(BUSTYPE_NEC98)-1) == 0) mp_bus_id_to_type[mc->mpc_busid] = MP_BUS_NEC98;
197 //else kprintf(DEBUG_NAME_STR ": WARNING - Unknown bustype %s - ignoring\n", str);
200 void parse_MP_Translation (struct mpc_config_translation *mc, struct SMP_Definition *SMP_Group)
202 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);
204 if (SMP_Group->SMP_RecordCount >= MAX_MPC_ENTRY) kprintf(DEBUG_NAME_STR ": ERROR - MAX_MPC_ENTRY exceeded!\n");
205 //else translation_table[SMP_Group->SMP_RecordCount] = mc; /* stash this for later */
207 //if (mc->trans_quad+1 > numnodes) numnodes = mc->trans_quad+1;
210 /**************************************************************************/
212 int mpfcb_checksum(unsigned char *mpcb, int len)
214 int sum = 0; /* Quickly grab the checksum of the config block */
216 while (len--) sum += *mpcb++;
218 return sum & 0xFF;
221 /**************************************************************************/
223 void smp_read_mpc_oem(struct mp_config_oemtable *oemtable, unsigned short oemsize, struct SMP_Definition *SMP_Group )
225 int count = sizeof (*oemtable); /* the header size */
226 unsigned char *oemptr = ((unsigned char *)oemtable)+count;
228 SMP_Group->SMP_RecordCount = 0;
229 kprintf(DEBUG_NAME_STR ": Found an OEM MPC table at %8p - parsing it ... \n", oemtable);
231 if (memcmp(oemtable->oem_signature,MPC_OEM_SIGNATURE,4))
233 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]);
234 return;
237 if (mpfcb_checksum((unsigned char *)oemtable,oemtable->oem_length))
239 kprintf(DEBUG_NAME_STR ": WARNING - SMP oem mptable: checksum error\n");
240 return;
243 while (count < oemtable->oem_length)
245 switch (*oemptr) {
246 case MP_TRANSLATION:
248 struct mpc_config_translation *mc=(struct mpc_config_translation *)oemptr;
249 parse_MP_Translation( mc, SMP_Group );
250 oemptr += sizeof(*mc);
251 count += sizeof(*mc);
252 ++SMP_Group->SMP_RecordCount;
253 break;
255 default:
257 kprintf(DEBUG_NAME_STR ": WARNING - Unrecognised OEM table entry type - %d\n", (int) *oemptr);
258 return;
264 void mps_oem_check(struct mp_config_table *mpcf, char *oem, char *productid, struct SMP_Definition *SMP_Group )
266 if (strncmp(oem, "IBM NUMA", 8)) kprintf( DEBUG_NAME_STR ": WARNING - May not be a NUMA-Q system.\n");
267 if (mpcf->mpc_oemptr) smp_read_mpc_oem((struct mp_config_oemtable *) mpcf->mpc_oemptr, mpcf->mpc_oemsize, SMP_Group);
270 /****************************************************************************************/
271 /* We are called very early to get the low memory for the SMP bootup trampoline page. */
273 int smp_alloc_memory(void)
275 ULONG trampoline_base;
276 #warning TODO: properly allocate SMP memory
277 //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. */
279 trampoline_base = 0x0009E000;
282 return trampoline_base;
285 /**************************************************************************/
287 int scan_for_smpconfig (unsigned long base, unsigned long length)
289 unsigned int *basepointer = base;
290 struct intel_mp_confblock *mpcfb;
292 kprintf(DEBUG_NAME_STR ": Scan for SMP = %p for %ld bytes.\n", basepointer,length);
294 while (length > 0)
296 mpcfb = (struct intel_mp_floating *)basepointer;
298 if ((*basepointer == SMP_MAGIC_IDENT))
300 if ( (mpcfb->mpcf_length == 1) && !mpfcb_checksum( (unsigned char *)basepointer, 16) )
302 if ( ( ( mpcfb->mpcf_specification == 1 ) || ( mpcfb->mpcf_specification == 4 ) ) )
304 return basepointer;
309 basepointer += 4;
310 length -= 16;
312 return NULL;
315 int find_smp_config (void)
317 unsigned int confAddr;
319 if ((confAddr = scan_for_smpconfig(0x00000000,0x400))) return confAddr; /* Scan the bottom 1K for a signature */
320 if ((confAddr = scan_for_smpconfig(0x0009FC00,0x400))) return confAddr; /* Scan the top 1K of base RAM (639*0x400) */
321 if ((confAddr = scan_for_smpconfig(0x000F0000,0x10000))) return confAddr; /* Scan the 64K of bios */
323 /* If it is an SMP machine we should know now, unless the
324 configuration is in an EISA/MCA bus machine with an
325 extended bios data area.
327 there is a real-mode segmented pointer pointing to the
328 4K EBDA area at 0x0000040E, calculate and scan it here.
330 Some Linux loaders corrupt the EBDA area, so this kind
331 of SMP config may be less reliable, because the SMP
332 table may have been corrupted during early boot. These
333 loaders are buggy and should be fixed. */
335 confAddr = *(unsigned short *)(0x0000040E);
336 confAddr <<= 4;
337 return scan_for_smpconfig(confAddr, 0x1000);
340 void get_smp_config ( struct intel_mp_confblock *mpcfb, struct CPUBase *CPUBase)
342 struct SMP_Definition *SMP_Group;
343 BOOL SMPERROR = FALSE;
344 ULONG pic_mode;
345 struct ACPIBase *ACPIBase;
347 ACPIBase = CPUBase->CPUB_ACPIBase;
349 kprintf(DEBUG_NAME_STR ": Processing SMP config...\n");
352 ACPI may be used to obtain the entire SMP configuration or just to
353 enumerate/configure processors (CONFIG_ACPI_HT).
355 Note that ACPI supports both logical (e.g. Hyper-Threading) and physical
356 processors, where MPS only supports physical. */
358 if (ACPIBase)
360 if (ACPIBase->ACPIB_ACPI_LAPIC && ACPIBase->ACPIB_ACPI_IOAPIC) {
361 kprintf(DEBUG_NAME_STR ": Using ACPI (MADT) for SMP configuration information\n");
362 return;
364 else if (ACPIBase->ACPIB_ACPI_LAPIC) kprintf(DEBUG_NAME_STR ": Using ACPI for processor (LAPIC) configuration information\n");
366 kprintf(DEBUG_NAME_STR ": Intel MultiProcessor Specification v1.%d\n", mpcfb->mpcf_specification);
368 if (mpcfb->mpcf_feature2 & (1<<7)) /* test bit 7 (IMCR|PIC) */
370 kprintf(DEBUG_NAME_STR ": IMCR and PIC compatibility mode.\n");
371 pic_mode = 1;
373 else
375 kprintf(DEBUG_NAME_STR ": Virtual Wire compatibility mode.\n");
376 pic_mode = 0;
379 /* Now see if we need to read further. */
380 if (mpcfb->mpcf_feature1 != 0)
382 kprintf(DEBUG_NAME_STR ": Default MP configuration #%d\n", mpcfb->mpcf_feature1);
383 //construct_default_ISA_mptable(mpf->mpf_feature1);
385 else if (mpcfb->mpcf_physptr)
388 /* Read the physical hardware table. Anything here will override the defaults. */
389 if (!(SMP_Group = smp_read_mpcfb((void *)mpcfb->mpcf_physptr, CPUBase)) )
391 SMPERROR = TRUE;
392 kprintf(DEBUG_NAME_STR ": ERROR - BIOS bug, MP table errors detected!...\n");
395 SMP_Group->SMP_PIC_Mode = pic_mode;
398 If there are no explicit MP IRQ entries, then we are
399 broken. We set up most of the low 16 IO-APIC pins to
400 ISA defaults and hope it will work. */
402 /*if (!mp_irq_entries)
404 struct mpc_config_bus bus;
406 kprintf(DEBUG_NAME_STR ": BIOS bug, no explicit IRQ entries, using default mptable. (tell your hw vendor)\n");
408 bus.mpc_type = MP_BUS;
409 bus.mpc_busid = 0;
410 memcpy(bus.mpc_bustype, "ISA ", 6);
411 parse_MP_Bus(&bus);
413 construct_default_ioirq_mptable(0);
414 } */
417 else SMPERROR = TRUE;
419 if ( SMPERROR == TRUE )
421 mpcfb = NULL;
422 kprintf(DEBUG_NAME_STR ": ERROR - disabling SMP support. (tell your hw vendor)\n");
424 else kprintf(DEBUG_NAME_STR ": Processors: %d\n", SMP_Group->SMP_CPUCount);
425 /* Only use the first configuration found. */
428 int smp_read_mpcfb(struct mp_config_table *mpcf, struct CPUBase *CPUBase)
430 char str[16];
431 char oem[10];
432 int count = sizeof(*mpcf);
433 unsigned char *mpt = ((unsigned char *)mpcf) + count;
434 struct SMP_Definition *SMP_Group;
435 struct ACPIBase *ACPIBase;
437 ACPIBase = CPUBase->CPUB_ACPIBase;
439 if (memcmp(mpcf->mpc_signature,MPC_SIGNATURE,4))
441 kprintf(DEBUG_NAME_STR ": ERROR - SMP mptable: bad signature [0x%x]!\n", *(ULONG *)mpcf->mpc_signature);
442 return 0;
445 if (mpfcb_checksum((unsigned char *)mpcf,mpcf->mpc_length))
447 kprintf(DEBUG_NAME_STR ": ERROR - SMP mptable: checksum error!\n");
448 return 0;
451 if (mpcf->mpc_spec != 0x01 && mpcf->mpc_spec != 0x04)
453 kprintf(DEBUG_NAME_STR ": ERROR - SMP mptable: bad table version (%d)!!\n",mpcf->mpc_spec);
454 return 0;
457 if (!mpcf->mpc_lapic)
459 kprintf(DEBUG_NAME_STR ": ERROR - SMP mptable: null local APIC address!\n");
460 return 0;
463 /* Create the SMP group block */
464 SMP_Group = AllocMem( sizeof(struct SMP_Definition), MEMF_CLEAR | MEMF_PUBLIC );
465 if (CPUBase->CPUB_SMP_Groups)
467 AddTail(CPUBase->CPUB_SMP_Groups,&SMP_Group->SMP_SMPList); /* Add this SMP group to the list */
468 kprintf(DEBUG_NAME_STR ": SMP Group Item @ 0x%p, Inserted into List @ 0x%p\n",&SMP_Group->SMP_SMPList,CPUBase->CPUB_SMP_Groups);
470 InitSemaphore( &SMP_Group->SMP_GrpLock);
471 kprintf(DEBUG_NAME_STR ": Initialised SMP Group Semaphore\n");
473 else
475 NEWLIST((struct List *)&(SMP_Group->SMP_SMPList)); /* Create This SMP group list */
476 kprintf(DEBUG_NAME_STR ": First SMP List & Group created @ 0x%p\n",&SMP_Group->SMP_SMPList);
478 InitSemaphore( &SMP_Group->SMP_GrpLock);
479 kprintf(DEBUG_NAME_STR ": Initialised SMP Group Semaphore\n");
481 CPUBase->CPUB_SMP_Groups = SMP_Group;
484 memcpy(oem,mpcf->mpc_oem,8);
485 oem[8]=0;
487 memcpy(str,mpcf->mpc_productid,12);
488 str[12]=0;
490 kprintf(DEBUG_NAME_STR ": OEM ID: %s Product ID: %s \n",oem,str);
492 mps_oem_check( mpcf, oem, str, SMP_Group );
494 kprintf(DEBUG_NAME_STR ": APIC at: 0x%lX\n",mpcf->mpc_lapic);
496 /* Save the local APIC address (it might be non-default) - though only if we're not using ACPI. */
498 if (!( ACPIBase )||( (ACPIBase) && (!ACPIBase->ACPIB_ACPI_LAPIC) )) SMP_Group->SMP_APIC = mpcf->mpc_lapic;
500 /* Now process the configuration blocks. */
502 SMP_Group->SMP_RecordCount = 0;
503 while (count < mpcf->mpc_length)
505 switch(*mpt)
507 case MP_PROCESSOR:
509 struct mpc_config_processor *mc= (struct mpc_config_processor *)mpt;
511 if (!( ACPIBase )||( (ACPIBase) && (!ACPIBase->ACPIB_ACPI_LAPIC) )) parse_MP_Processor( mc, SMP_Group ); /* ACPI may have already provided this data */
513 mpt += sizeof( *mc );
514 count += sizeof( *mc );
515 break;
517 case MP_IOAPIC:
519 struct mpc_config_ioapic *mc= (struct mpc_config_ioapic *)mpt;
521 parse_MP_IOAPIC( mc, SMP_Group );
522 mpt += sizeof( *mc );
523 count += sizeof( *mc );
524 break;
526 case MP_INTSRC:
528 struct mpc_config_intsrc *mc= (struct mpc_config_intsrc *)mpt;
530 parse_MP_IntSrc( mc, SMP_Group );
531 mpt += sizeof( *mc );
532 count += sizeof( *mc );
533 break;
535 case MP_LINTSRC:
537 struct mpc_config_lintsrc *mc= (struct mpc_config_lintsrc *)mpt;
539 parse_MP_LIntSrc( mc, SMP_Group );
540 mpt += sizeof( *mc );
541 count += sizeof( *mc );
542 break;
544 case MP_BUS:
546 struct mpc_config_bus *mc= (struct mpc_config_bus *)mpt;
548 parse_MP_Bus( mc, SMP_Group );
549 mpt += sizeof( *mc );
550 count += sizeof( *mc );
551 break;
553 default:
555 count = mpcf->mpc_length;
556 break;
559 ++SMP_Group->SMP_RecordCount;
562 //clustered_apic_check();
563 if (!SMP_Group->SMP_CPUCount) kprintf(DEBUG_NAME_STR ": SMP mptable - NO Processors Registered!\n");
564 return SMP_Group;
567 /**************************************************************************/
569 #endif /* _SMP_C */