-revert janderwalds change until because it breaks the gcc 4.x build
[reactos.git] / arch / i386 / hwcpu.c
1 /*
2 * FreeLoader
3 *
4 * Copyright (C) 2003 Eric Kohl
5 * Copyright (C) 2006 Colin Finck <mail@colinfinck.de>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include <freeldr.h>
23
24 #define NDEBUG
25 #include <debug.h>
26
27 #define MP_FP_SIGNATURE 0x5F504D5F /* "_MP_" */
28 #define MP_CT_SIGNATURE 0x504D4350 /* "PCMP" */
29
30
31 typedef struct _MP_FLOATING_POINT_TABLE
32 {
33 ULONG Signature; /* "_MP_" */
34 ULONG PhysicalAddressPointer;
35 UCHAR Length;
36 UCHAR SpecRev;
37 UCHAR Checksum;
38 UCHAR FeatureByte[5];
39 } PACKED MP_FLOATING_POINT_TABLE, *PMP_FLOATING_POINT_TABLE;
40
41
42 typedef struct _MPS_CONFIG_TABLE_HEADER
43 {
44 ULONG Signature; /* "PCMP" */
45 USHORT BaseTableLength;
46 UCHAR SpecRev;
47 UCHAR Checksum;
48 UCHAR OemIdString[8];
49 UCHAR ProductIdString[12];
50 ULONG OemTablePointer;
51 USHORT OemTableLength;
52 USHORT EntryCount;
53 ULONG AddressOfLocalAPIC;
54 USHORT ExtendedTableLength;
55 UCHAR ExtendedTableChecksum;
56 UCHAR Reserved;
57 } PACKED MP_CONFIGURATION_TABLE, *PMP_CONFIGURATION_TABLE;
58
59
60 typedef struct _MP_PROCESSOR_ENTRY
61 {
62 UCHAR EntryType;
63 UCHAR LocalApicId;
64 UCHAR LocalApicVersion;
65 UCHAR CpuFlags;
66 ULONG CpuSignature;
67 ULONG FeatureFlags;
68 ULONG Reserved1;
69 ULONG Reserved2;
70 } PACKED MP_PROCESSOR_ENTRY, *PMP_PROCESSOR_ENTRY;
71
72
73 /* FUNCTIONS ****************************************************************/
74
75 static ULONG
76 GetCpuSpeed(VOID)
77 {
78 ULONGLONG Timestamp1;
79 ULONGLONG Timestamp2;
80 ULONGLONG Diff;
81
82 /* Read TSC (Time Stamp Counter) */
83 Timestamp1 = RDTSC();
84
85 /* Wait for 0.1 seconds (= 100 milliseconds = 100000 microseconds)*/
86 StallExecutionProcessor(100000);
87
88 /* Read TSC (Time Stamp Counter) again */
89 Timestamp2 = RDTSC();
90
91 /* Calculate elapsed time (check for counter overrun) */
92 if (Timestamp2 > Timestamp1)
93 {
94 Diff = Timestamp2 - Timestamp1;
95 }
96 else
97 {
98 Diff = Timestamp2 + (((ULONGLONG)-1) - Timestamp1);
99 }
100
101 return (ULONG)(Diff / 100000);
102 }
103
104
105 static VOID
106 DetectCPU(FRLDRHKEY CpuKey,
107 FRLDRHKEY FpuKey)
108 {
109 WCHAR VendorIdentifier[13];
110 WCHAR ProcessorNameString[49];
111 CHAR tmpVendorIdentifier[13];
112 CHAR tmpProcessorNameString[49];
113 WCHAR Identifier[64];
114 ULONG FeatureSet;
115 FRLDRHKEY CpuInstKey;
116 FRLDRHKEY FpuInstKey;
117 ULONG eax = 0;
118 ULONG ebx = 0;
119 ULONG ecx = 0;
120 ULONG edx = 0;
121 ULONG i;
122 ULONG *Ptr;
123 LONG Error;
124 BOOLEAN SupportTSC = FALSE;
125 ULONG CpuSpeed;
126
127
128 /* Create the CPU instance key */
129 Error = RegCreateKey(CpuKey,
130 L"0",
131 &CpuInstKey);
132 if (Error != ERROR_SUCCESS)
133 {
134 DbgPrint((DPRINT_HWDETECT, "RegCreateKey() failed (Error %u)\n", (int)Error));
135 return;
136 }
137
138 /* Create the FPU instance key */
139 Error = RegCreateKey(FpuKey,
140 L"0",
141 &FpuInstKey);
142 if (Error != ERROR_SUCCESS)
143 {
144 DbgPrint((DPRINT_HWDETECT, "RegCreateKey() failed (Error %u)\n", (int)Error));
145 return;
146 }
147
148 eax = CpuidSupported();
149 if (eax & 1)
150 {
151 DbgPrint((DPRINT_HWDETECT, "CPUID supported\n"));
152
153 /* Get vendor identifier */
154 GetCpuid(0, &eax, &ebx, &ecx, &edx);
155 tmpVendorIdentifier[12] = 0;
156 Ptr = (ULONG*)&tmpVendorIdentifier[0];
157 *Ptr = ebx;
158 Ptr++;
159 *Ptr = edx;
160 Ptr++;
161 *Ptr = ecx;
162 swprintf(VendorIdentifier, L"%S", tmpVendorIdentifier);
163
164 /* Get Identifier */
165 GetCpuid(1, &eax, &ebx, &ecx, &edx);
166 swprintf(Identifier,
167 L"x86 Family %u Model %u Stepping %u",
168 (unsigned int)((eax >> 8) & 0x0F),
169 (unsigned int)((eax >> 4) & 0x0F),
170 (unsigned int)(eax & 0x0F));
171 FeatureSet = edx;
172 if (((eax >> 8) & 0x0F) >= 5)
173 SupportTSC = TRUE;
174
175 /* Check if Extended CPUID information is supported */
176 GetCpuid(0x80000000, &eax, &ebx, &ecx, &edx);
177
178 if(eax >= 0x80000004)
179 {
180 /* Get Processor Name String */
181 tmpProcessorNameString[48] = 0;
182 Ptr = (ULONG*)&tmpProcessorNameString[0];
183
184 for (i = 0x80000002; i <= 0x80000004; i++)
185 {
186 GetCpuid(i, &eax, &ebx, &ecx, &edx);
187 *Ptr = eax;
188 Ptr++;
189 *Ptr = ebx;
190 Ptr++;
191 *Ptr = ecx;
192 Ptr++;
193 *Ptr = edx;
194 Ptr++;
195 }
196
197 swprintf(ProcessorNameString, L"%S", tmpProcessorNameString);
198
199
200 /* Set 'ProcessorNameString' value (CPU only) */
201 DbgPrint((DPRINT_HWDETECT, "Processor Name String: %S\n", ProcessorNameString));
202
203 Error = RegSetValue(CpuInstKey,
204 L"ProcessorNameString",
205 REG_SZ,
206 (PCHAR)ProcessorNameString,
207 (wcslen(ProcessorNameString) + 1) * sizeof(WCHAR));
208
209 if (Error != ERROR_SUCCESS)
210 DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error));
211 }
212 }
213 else
214 {
215 DbgPrint((DPRINT_HWDETECT, "CPUID not supported\n"));
216
217 wcscpy(VendorIdentifier, L"Unknown");
218 swprintf(Identifier,
219 L"x86 Family %u Model %u Stepping %u",
220 (unsigned int)((eax >> 8) & 0x0F),
221 (unsigned int)((eax >> 4) & 0x0F),
222 (unsigned int)(eax & 0x0F));
223 FeatureSet = 0;
224 }
225
226 /* Set 'Conmponent Information' value (CPU and FPU) */
227 SetComponentInformation(CpuInstKey, 0, 0, 1);
228 SetComponentInformation(FpuInstKey, 0, 0, 1);
229
230 /* Set 'FeatureSet' value (CPU only) */
231 DbgPrint((DPRINT_HWDETECT, "FeatureSet: %x\n", FeatureSet));
232
233 Error = RegSetValue(CpuInstKey,
234 L"FeatureSet",
235 REG_DWORD,
236 (PCHAR)&FeatureSet,
237 sizeof(ULONG));
238 if (Error != ERROR_SUCCESS)
239 {
240 DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error));
241 }
242
243 /* Set 'Identifier' value (CPU and FPU) */
244 DbgPrint((DPRINT_HWDETECT, "Identifier: %S\n", Identifier));
245
246 Error = RegSetValue(CpuInstKey,
247 L"Identifier",
248 REG_SZ,
249 (PCHAR)Identifier,
250 (wcslen(Identifier) + 1) * sizeof(WCHAR));
251 if (Error != ERROR_SUCCESS)
252 {
253 DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error));
254 }
255
256 Error = RegSetValue(FpuInstKey,
257 L"Identifier",
258 REG_SZ,
259 (PCHAR)Identifier,
260 (wcslen(Identifier) + 1) * sizeof(WCHAR));
261 if (Error != ERROR_SUCCESS)
262 {
263 DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error));
264 }
265
266 /* Set 'VendorIdentifier' value (CPU only) */
267 DbgPrint((DPRINT_HWDETECT, "Vendor Identifier: %S\n", VendorIdentifier));
268
269 Error = RegSetValue(CpuInstKey,
270 L"VendorIdentifier",
271 REG_SZ,
272 (PCHAR)VendorIdentifier,
273 (wcslen(VendorIdentifier) + 1) * sizeof(WCHAR));
274 if (Error != ERROR_SUCCESS)
275 {
276 DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error));
277 }
278
279 /* FIXME: Set 'Update Signature' value (CPU only) */
280
281 /* FIXME: Set 'Update Status' value (CPU only) */
282
283 /* Set '~MHz' value (CPU only) */
284 if (SupportTSC)
285 {
286 CpuSpeed = GetCpuSpeed();
287
288 Error = RegSetValue(CpuInstKey,
289 L"~MHz",
290 REG_DWORD,
291 (PCHAR)&CpuSpeed,
292 sizeof(ULONG));
293 if (Error != ERROR_SUCCESS)
294 {
295 DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error));
296 }
297 }
298 }
299
300
301 static VOID
302 SetMpsProcessor(FRLDRHKEY CpuKey,
303 FRLDRHKEY FpuKey,
304 PMP_PROCESSOR_ENTRY CpuEntry)
305 {
306 WCHAR ProcessorNameString[49];
307 WCHAR VendorIdentifier[13];
308 CHAR tmpProcessorNameString[49];
309 CHAR tmpVendorIdentifier[13];
310 WCHAR Identifier[64];
311 WCHAR Buffer[8];
312 ULONG FeatureSet;
313 FRLDRHKEY CpuInstKey;
314 FRLDRHKEY FpuInstKey;
315 ULONG eax = 0;
316 ULONG ebx = 0;
317 ULONG ecx = 0;
318 ULONG edx = 0;
319 ULONG i;
320 ULONG *Ptr;
321 LONG Error;
322 ULONG CpuSpeed;
323
324 /* Get processor instance number */
325 swprintf(Buffer, L"%u", CpuEntry->LocalApicId);
326
327 /* Create the CPU instance key */
328 Error = RegCreateKey(CpuKey,
329 Buffer,
330 &CpuInstKey);
331 if (Error != ERROR_SUCCESS)
332 {
333 DbgPrint((DPRINT_HWDETECT, "RegCreateKey() failed (Error %u)\n", (int)Error));
334 return;
335 }
336
337 /* Create the FPU instance key */
338 Error = RegCreateKey(FpuKey,
339 Buffer,
340 &FpuInstKey);
341 if (Error != ERROR_SUCCESS)
342 {
343 DbgPrint((DPRINT_HWDETECT, "RegCreateKey() failed (Error %u)\n", (int)Error));
344 return;
345 }
346
347 /* Get 'VendorIdentifier' */
348 GetCpuid(0, &eax, &ebx, &ecx, &edx);
349 tmpVendorIdentifier[12] = 0;
350 Ptr = (ULONG*)&tmpVendorIdentifier[0];
351 *Ptr = ebx;
352 Ptr++;
353 *Ptr = edx;
354 Ptr++;
355 *Ptr = ecx;
356 swprintf(VendorIdentifier, L"%S", tmpVendorIdentifier);
357
358 /* Get 'Identifier' */
359 swprintf(Identifier,
360 L"x86 Family %u Model %u Stepping %u",
361 (ULONG)((CpuEntry->CpuSignature >> 8) & 0x0F),
362 (ULONG)((CpuEntry->CpuSignature >> 4) & 0x0F),
363 (ULONG)(CpuEntry->CpuSignature & 0x0F));
364
365 /* Get FeatureSet */
366 FeatureSet = CpuEntry->FeatureFlags;
367
368 /* Check if Extended CPUID information is supported */
369 GetCpuid(0x80000000, &eax, &ebx, &ecx, &edx);
370
371 if(eax >= 0x80000004)
372 {
373 /* Get 'ProcessorNameString' */
374 tmpProcessorNameString[48] = 0;
375 Ptr = (ULONG*)&tmpProcessorNameString[0];
376
377 for (i = 0x80000002; i <= 0x80000004; i++)
378 {
379 GetCpuid(i, &eax, &ebx, &ecx, &edx);
380 *Ptr = eax;
381 Ptr++;
382 *Ptr = ebx;
383 Ptr++;
384 *Ptr = ecx;
385 Ptr++;
386 *Ptr = edx;
387 Ptr++;
388 }
389
390 swprintf(ProcessorNameString, L"%S", tmpProcessorNameString);
391
392
393 /* Set 'ProcessorNameString' value (CPU only) */
394 DbgPrint((DPRINT_HWDETECT, "Processor Name String: %S\n", ProcessorNameString));
395
396 Error = RegSetValue(CpuInstKey,
397 L"ProcessorNameString",
398 REG_SZ,
399 (PCHAR)ProcessorNameString,
400 (wcslen(ProcessorNameString) + 1) * sizeof(WCHAR));
401 if (Error != ERROR_SUCCESS)
402 DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error));
403 }
404
405 /* Set 'Configuration Data' value (CPU and FPU) */
406 SetComponentInformation(CpuInstKey,
407 0,
408 CpuEntry->LocalApicId,
409 1 << CpuEntry->LocalApicId);
410
411 SetComponentInformation(FpuInstKey,
412 0,
413 CpuEntry->LocalApicId,
414 1 << CpuEntry->LocalApicId);
415
416 /* Set 'FeatureSet' value (CPU only) */
417 DbgPrint((DPRINT_HWDETECT, "FeatureSet: %x\n", FeatureSet));
418
419 Error = RegSetValue(CpuInstKey,
420 L"FeatureSet",
421 REG_DWORD,
422 (PCHAR)&FeatureSet,
423 sizeof(ULONG));
424 if (Error != ERROR_SUCCESS)
425 {
426 DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error));
427 }
428
429 /* Set 'Identifier' value (CPU and FPU) */
430 DbgPrint((DPRINT_HWDETECT, "Identifier: %S\n", Identifier));
431
432 Error = RegSetValue(CpuInstKey,
433 L"Identifier",
434 REG_SZ,
435 (PCHAR)Identifier,
436 (wcslen(Identifier) + 1) * sizeof(WCHAR));
437 if (Error != ERROR_SUCCESS)
438 {
439 DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error));
440 }
441
442 Error = RegSetValue(FpuInstKey,
443 L"Identifier",
444 REG_SZ,
445 (PCHAR)Identifier,
446 (wcslen(Identifier) + 1) * sizeof(WCHAR));
447 if (Error != ERROR_SUCCESS)
448 {
449 DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error));
450 }
451
452 /* Set 'VendorIdentifier' value (CPU only) */
453 DbgPrint((DPRINT_HWDETECT, "Vendor Identifier: %S\n", VendorIdentifier));
454
455 Error = RegSetValue(CpuInstKey,
456 L"VendorIdentifier",
457 REG_SZ,
458 (PCHAR)VendorIdentifier,
459 (wcslen(VendorIdentifier) + 1) * sizeof(WCHAR));
460 if (Error != ERROR_SUCCESS)
461 {
462 DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error));
463 }
464
465 /* FIXME: Set 'Update Signature' value (CPU only) */
466
467 /* FIXME: Set 'Update Status' value (CPU only) */
468
469 /* Set '~MHz' value (CPU only) */
470 if (((CpuEntry->CpuSignature >> 8) & 0x0F) >= 5)
471 {
472 CpuSpeed = GetCpuSpeed();
473
474 Error = RegSetValue(CpuInstKey,
475 L"~MHz",
476 REG_DWORD,
477 (PCHAR)&CpuSpeed,
478 sizeof(ULONG));
479 if (Error != ERROR_SUCCESS)
480 {
481 DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error));
482 }
483 }
484 }
485
486
487 static PMP_FLOATING_POINT_TABLE
488 GetMpFloatingPointTable(VOID)
489 {
490 PMP_FLOATING_POINT_TABLE FpTable;
491 char *Ptr;
492 UCHAR Sum;
493 ULONG Length;
494 ULONG i;
495
496 FpTable = (PMP_FLOATING_POINT_TABLE)0xF0000;
497 while ((ULONG)FpTable < 0x100000)
498 {
499 if (FpTable->Signature == MP_FP_SIGNATURE)
500 {
501 Length = FpTable->Length * 0x10;
502 Ptr = (char *)FpTable;
503 Sum = 0;
504 for (i = 0; i < Length; i++)
505 {
506 Sum += Ptr[i];
507 }
508 DbgPrint((DPRINT_HWDETECT,
509 "Checksum: %u\n",
510 Sum));
511
512 if (Sum != 0)
513 {
514 DbgPrint((DPRINT_HWDETECT,
515 "Invalid MP floating point checksum: %u\n",
516 Sum));
517 return NULL;
518 }
519
520 return FpTable;
521 }
522
523 FpTable = (PMP_FLOATING_POINT_TABLE)((ULONG)FpTable + 0x10);
524 }
525
526 return NULL;
527 }
528
529
530 static PMP_CONFIGURATION_TABLE
531 GetMpConfigurationTable(PMP_FLOATING_POINT_TABLE FpTable)
532 {
533 PMP_CONFIGURATION_TABLE ConfigTable;
534 char *Ptr;
535 UCHAR Sum;
536 ULONG Length;
537 ULONG i;
538
539 if (FpTable->FeatureByte[0] != 0 ||
540 FpTable->PhysicalAddressPointer == 0)
541 return NULL;
542
543 ConfigTable = (PMP_CONFIGURATION_TABLE)FpTable->PhysicalAddressPointer;
544 if (ConfigTable->Signature != MP_CT_SIGNATURE)
545 return NULL;
546
547 DbgPrint((DPRINT_HWDETECT,
548 "MP Configuration Table at: %x\n",
549 (ULONG)ConfigTable));
550
551 /* Calculate base table checksum */
552 Length = ConfigTable->BaseTableLength;
553 Ptr = (char *)ConfigTable;
554 Sum = 0;
555 for (i = 0; i < Length; i++)
556 {
557 Sum += Ptr[i];
558 }
559 DbgPrint((DPRINT_HWDETECT,
560 "MP Configuration Table base checksum: %u\n",
561 Sum));
562
563 if (Sum != 0)
564 {
565 DbgPrint((DPRINT_HWDETECT,
566 "Invalid MP Configuration Table base checksum: %u\n",
567 Sum));
568 return NULL;
569 }
570
571 if (ConfigTable->ExtendedTableLength != 0)
572 {
573 /* FIXME: Check extended table */
574 }
575
576 return ConfigTable;
577 }
578
579
580 static BOOLEAN
581 DetectMps(FRLDRHKEY CpuKey,
582 FRLDRHKEY FpuKey)
583 {
584 PMP_FLOATING_POINT_TABLE FpTable;
585 PMP_CONFIGURATION_TABLE ConfigTable;
586 PMP_PROCESSOR_ENTRY CpuEntry;
587 char *Ptr;
588 ULONG Offset;
589
590 /* Get floating point table */
591 FpTable = GetMpFloatingPointTable();
592 if (FpTable == NULL)
593 return FALSE;
594
595 DbgPrint((DPRINT_HWDETECT,
596 "MP Floating Point Table at: %x\n",
597 (ULONG)FpTable));
598
599 if (FpTable->FeatureByte[0] == 0)
600 {
601 /* Get configuration table */
602 ConfigTable = GetMpConfigurationTable(FpTable);
603 if (ConfigTable == NULL)
604 {
605 DbgPrint((DPRINT_HWDETECT,
606 "Failed to find the MP Configuration Table\n"));
607 return FALSE;
608 }
609
610 Offset = sizeof(MP_CONFIGURATION_TABLE);
611 while (Offset < ConfigTable->BaseTableLength)
612 {
613 Ptr = (char*)((ULONG)ConfigTable + Offset);
614
615 switch (*Ptr)
616 {
617 case 0:
618 CpuEntry = (PMP_PROCESSOR_ENTRY)Ptr;
619
620 DbgPrint((DPRINT_HWDETECT, "Processor Entry\n"));
621 DbgPrint((DPRINT_HWDETECT,
622 "APIC Id %u APIC Version %u Flags %x Signature %x Feature %x\n",
623 CpuEntry->LocalApicId,
624 CpuEntry->LocalApicVersion,
625 CpuEntry->CpuFlags,
626 CpuEntry->CpuSignature,
627 CpuEntry->FeatureFlags));
628 DbgPrint((DPRINT_HWDETECT,
629 "Processor %u: x86 Family %u Model %u Stepping %u\n",
630 CpuEntry->LocalApicId,
631 (ULONG)((CpuEntry->CpuSignature >> 8) & 0x0F),
632 (ULONG)((CpuEntry->CpuSignature >> 4) & 0x0F),
633 (ULONG)(CpuEntry->CpuSignature & 0x0F)));
634
635 SetMpsProcessor(CpuKey, FpuKey, CpuEntry);
636 Offset += 0x14;
637 break;
638
639 case 1:
640 DbgPrint((DPRINT_HWDETECT, "Bus Entry\n"));
641 Offset += 0x08;
642 break;
643
644 case 2:
645 DbgPrint((DPRINT_HWDETECT, "I/0 APIC Entry\n"));
646 Offset += 0x08;
647 break;
648
649 case 3:
650 DbgPrint((DPRINT_HWDETECT, "I/0 Interrupt Assignment Entry\n"));
651 Offset += 0x08;
652 break;
653
654 case 4:
655 DbgPrint((DPRINT_HWDETECT, "Local Interrupt Assignment Entry\n"));
656 Offset += 0x08;
657 break;
658
659 default:
660 DbgPrint((DPRINT_HWDETECT, "Unknown Entry %u\n",(ULONG)*Ptr));
661 return FALSE;
662 }
663 }
664 }
665 else
666 {
667 DbgPrint((DPRINT_HWDETECT,
668 "Unsupported MPS configuration: %x\n",
669 FpTable->FeatureByte[0]));
670
671 /* FIXME: Identify default configurations */
672
673 return FALSE;
674 }
675
676 return TRUE;
677 }
678
679
680
681 VOID
682 DetectCPUs(FRLDRHKEY SystemKey)
683 {
684 FRLDRHKEY CpuKey;
685 FRLDRHKEY FpuKey;
686 LONG Error;
687
688 /* Create the 'CentralProcessor' key */
689 Error = RegCreateKey(SystemKey,
690 L"CentralProcessor",
691 &CpuKey);
692 if (Error != ERROR_SUCCESS)
693 {
694 DbgPrint((DPRINT_HWDETECT, "RegCreateKey() failed (Error %u)\n", (int)Error));
695 return;
696 }
697
698 /* Create the 'FloatingPointProcessor' key */
699 Error = RegCreateKey(SystemKey,
700 L"FloatingPointProcessor",
701 &FpuKey);
702 if (Error != ERROR_SUCCESS)
703 {
704 DbgPrint((DPRINT_HWDETECT, "RegCreateKey() failed (Error %u)\n", (int)Error));
705 return;
706 }
707
708 /* Detect CPUs */
709 if (!DetectMps(CpuKey, FpuKey))
710 {
711 DetectCPU(CpuKey, FpuKey);
712 }
713 }
714
715 /* EOF */