3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Hardware detection routines for NEC PC-98 series
5 * COPYRIGHT: Copyright 2020 Dmitry Borisov (di.sean@protonmail.com)
8 /* INCLUDES *******************************************************************/
11 #include <cportlib/cportlib.h>
12 #include <drivers/pc98/pit.h>
13 #include <drivers/pc98/fdc.h>
16 DBG_DEFAULT_CHANNEL(HWDETECT
);
18 /* Used for BIOS disks pre-enumeration performed when detecting the boot devices in InitializeBootDevices() */
19 extern UCHAR PcBiosDiskCount
;
21 extern BOOLEAN HiResoMachine
;
23 GET_HARDDISK_CONFIG_DATA GetHarddiskConfigurationData
= NULL
;
25 /* GLOBALS ********************************************************************/
31 static unsigned int delay_count
= 1;
34 GetHarddiskIdentifier(UCHAR DriveNumber
);
36 /* FUNCTIONS ******************************************************************/
39 __StallExecutionProcessor(ULONG Loops
)
41 register volatile unsigned int i
;
42 for (i
= 0; i
< Loops
; i
++);
45 VOID
StallExecutionProcessor(ULONG Microseconds
)
47 ULONGLONG LoopCount
= ((ULONGLONG
)delay_count
* (ULONGLONG
)Microseconds
) / 1000ULL;
48 __StallExecutionProcessor((ULONG
)LoopCount
);
52 WaitFor8253Wraparound(VOID
)
55 ULONG PreviousCount
= ~0;
58 CurrentCount
= Read8253Timer(PitChannel0
);
62 PreviousCount
= CurrentCount
;
63 CurrentCount
= Read8253Timer(PitChannel0
);
64 Delta
= CurrentCount
- PreviousCount
;
70 HalpCalibrateStallExecution(VOID
)
75 TIMER_CONTROL_PORT_REGISTER TimerControl
;
76 USHORT Count
= (*(PUCHAR
)MEM_BIOS_FLAG1
& SYSTEM_CLOCK_8MHZ_FLAG
) ?
77 (TIMER_FREQUENCY_1
/ HZ
) : (TIMER_FREQUENCY_2
/ HZ
);
79 /* Initialize timer interrupt with MILLISECOND ms interval */
80 TimerControl
.BcdMode
= FALSE
;
81 TimerControl
.OperatingMode
= PitOperatingMode2
;
82 TimerControl
.AccessMode
= PitAccessModeLowHigh
;
83 TimerControl
.Channel
= PitChannel0
;
84 Write8253Timer(TimerControl
, Count
);
86 /* Stage 1: Coarse calibration */
92 /* Next delay count to try */
95 WaitFor8253Wraparound();
98 __StallExecutionProcessor(delay_count
);
100 CurCount
= Read8253Timer(PitChannel0
);
102 while (CurCount
> Count
/ 2);
104 /* Get bottom value for delay */
107 /* Stage 2: Fine calibration */
109 /* Which bit are we going to test */
110 calib_bit
= delay_count
;
112 for (i
= 0; i
< PRECISION
; i
++)
114 /* Next bit to calibrate */
117 /* If we have done all bits, stop */
121 /* Set the bit in delay_count */
122 delay_count
|= calib_bit
;
124 WaitFor8253Wraparound();
127 __StallExecutionProcessor(delay_count
);
129 CurCount
= Read8253Timer(PitChannel0
);
131 /* If a tick has passed, turn the calibrated bit back off */
132 if (CurCount
<= Count
/ 2)
133 delay_count
&= ~calib_bit
;
136 /* We're finished: Do the finishing touches */
138 /* Calculate delay_count for 1ms */
139 delay_count
/= (MILLISEC
/ 2);
143 GetFloppyType(UCHAR FloppyNumber
)
150 DetectBiosFloppyPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey
)
152 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
153 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
154 PCM_FLOPPY_DEVICE_DATA FloppyData
;
156 PCONFIGURATION_COMPONENT_DATA PeripheralKey
;
160 ULONG MaxDensity
[6] = {0, 360, 1200, 720, 1440, 2880};
162 for (FloppyNumber
= 0; FloppyNumber
< Pc98GetFloppyCount(); FloppyNumber
++)
164 FloppyType
= GetFloppyType(FloppyNumber
);
166 if ((FloppyType
> 5) || (FloppyType
== 0))
169 /* TODO: Properly detect */
171 RtlStringCbPrintfA(Identifier
, sizeof(Identifier
), "FLOPPY%d", FloppyNumber
+ 1);
173 /* Set 'Configuration Data' value */
174 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
175 sizeof(CM_FLOPPY_DEVICE_DATA
);
176 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
177 if (PartialResourceList
== NULL
)
179 ERR("Failed to allocate resource descriptor\n");
182 RtlZeroMemory(PartialResourceList
, Size
);
183 PartialResourceList
->Version
= 1;
184 PartialResourceList
->Revision
= 1;
185 PartialResourceList
->Count
= 1;
187 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[0];
188 PartialDescriptor
->Type
= CmResourceTypeDeviceSpecific
;
189 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
190 PartialDescriptor
->u
.DeviceSpecificData
.DataSize
= sizeof(CM_FLOPPY_DEVICE_DATA
);
192 /* FIXME: Don't use default parameters for 1.44 MB floppy */
193 FloppyData
= (PVOID
)(((ULONG_PTR
)PartialResourceList
) + sizeof(CM_PARTIAL_RESOURCE_LIST
));
194 FloppyData
->Version
= 2;
195 FloppyData
->Revision
= 0;
196 FloppyData
->MaxDensity
= MaxDensity
[FloppyType
];
197 FloppyData
->MountDensity
= 0;
198 FloppyData
->StepRateHeadUnloadTime
= 175;
199 FloppyData
->HeadLoadTime
= 2;
200 FloppyData
->MotorOffTime
= 37;
201 FloppyData
->SectorLengthCode
= 2;
202 FloppyData
->SectorPerTrack
= 18;
203 FloppyData
->ReadWriteGapLength
= 27;
204 FloppyData
->DataTransferLength
= 255;
205 FloppyData
->FormatGapLength
= 108;
206 FloppyData
->FormatFillCharacter
= 0xF6;
207 FloppyData
->HeadSettleTime
= 15;
208 FloppyData
->MotorSettleTime
= 8;
209 FloppyData
->MaximumTrackValue
= (FloppyType
== 1) ? 39 : 79;
210 FloppyData
->DataTransferRate
= 0;
212 FldrCreateComponentKey(ControllerKey
,
214 FloppyDiskPeripheral
,
222 TRACE("Created key: FloppyDiskPeripheral\\%d\n", FloppyNumber
);
226 static PCONFIGURATION_COMPONENT_DATA
227 DetectBiosFloppyController(PCONFIGURATION_COMPONENT_DATA BusKey
)
229 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
230 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
231 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
237 FloppyCount
= Pc98GetFloppyCount();
239 /* Always create a BIOS disk controller, no matter if we have floppy drives or not */
240 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
241 6 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
242 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
243 if (PartialResourceList
== NULL
)
245 ERR("Failed to allocate resource descriptor\n");
248 RtlZeroMemory(PartialResourceList
, Size
);
249 PartialResourceList
->Version
= 1;
250 PartialResourceList
->Revision
= 1;
251 PartialResourceList
->Count
= 7;
254 for (i
= 0; i
< 3; i
++)
256 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[Index
++];
257 PartialDescriptor
->Type
= CmResourceTypePort
;
258 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
259 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
260 PartialDescriptor
->u
.Port
.Start
.LowPart
= 0x90 + i
* 2;
261 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0;
262 PartialDescriptor
->u
.Port
.Length
= 1;
264 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[Index
++];
265 PartialDescriptor
->Type
= CmResourceTypePort
;
266 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
267 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
268 PartialDescriptor
->u
.Port
.Start
.LowPart
= 0xBE;
269 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0;
270 PartialDescriptor
->u
.Port
.Length
= 1;
272 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[Index
++];
273 PartialDescriptor
->Type
= CmResourceTypePort
;
274 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
275 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
276 PartialDescriptor
->u
.Port
.Start
.LowPart
= 0x4BE;
277 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0;
278 PartialDescriptor
->u
.Port
.Length
= 1;
281 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[Index
++];
282 PartialDescriptor
->Type
= CmResourceTypeInterrupt
;
283 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
284 PartialDescriptor
->Flags
= CM_RESOURCE_INTERRUPT_LATCHED
;
285 PartialDescriptor
->u
.Interrupt
.Level
= 11;
286 PartialDescriptor
->u
.Interrupt
.Vector
= 11;
287 PartialDescriptor
->u
.Interrupt
.Affinity
= 0xFFFFFFFF;
289 /* Set DMA channel */
290 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[Index
++];
291 PartialDescriptor
->Type
= CmResourceTypeDma
;
292 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
293 PartialDescriptor
->Flags
= 0;
294 PartialDescriptor
->u
.Dma
.Channel
= 2;
295 PartialDescriptor
->u
.Dma
.Port
= 0;
297 /* Create floppy disk controller */
298 FldrCreateComponentKey(BusKey
,
308 TRACE("Created key: DiskController\\0\n");
311 DetectBiosFloppyPeripheral(ControllerKey
);
313 return ControllerKey
;
316 static PCM_PARTIAL_RESOURCE_LIST
317 Pc98GetHarddiskConfigurationData(UCHAR DriveNumber
, ULONG
* pSize
)
319 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
320 PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry
;
326 /* Set 'Configuration Data' value */
327 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
328 sizeof(CM_DISK_GEOMETRY_DEVICE_DATA
);
329 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
330 if (PartialResourceList
== NULL
)
332 ERR("Failed to allocate resource descriptor\n");
335 RtlZeroMemory(PartialResourceList
, Size
);
336 PartialResourceList
->Version
= 1;
337 PartialResourceList
->Revision
= 1;
338 PartialResourceList
->Count
= 1;
339 PartialResourceList
->PartialDescriptors
[0].Type
= CmResourceTypeDeviceSpecific
;
340 // PartialResourceList->PartialDescriptors[0].ShareDisposition =
341 // PartialResourceList->PartialDescriptors[0].Flags =
342 PartialResourceList
->PartialDescriptors
[0].u
.DeviceSpecificData
.DataSize
=
343 sizeof(CM_DISK_GEOMETRY_DEVICE_DATA
);
345 /* Get pointer to geometry data */
346 DiskGeometry
= (PVOID
)(((ULONG_PTR
)PartialResourceList
) + sizeof(CM_PARTIAL_RESOURCE_LIST
));
348 /* Get the disk geometry. Extended geometry isn't supported by hardware */
349 if (Pc98DiskGetDriveGeometry(DriveNumber
, &Geometry
))
351 DiskGeometry
->BytesPerSector
= Geometry
.BytesPerSector
;
352 DiskGeometry
->NumberOfCylinders
= Geometry
.Cylinders
;
353 DiskGeometry
->SectorsPerTrack
= Geometry
.Sectors
;
354 DiskGeometry
->NumberOfHeads
= Geometry
.Heads
;
358 TRACE("Reading disk geometry failed\n");
359 FrLdrHeapFree(PartialResourceList
, TAG_HW_RESOURCE_LIST
);
362 TRACE("Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n",
364 DiskGeometry
->NumberOfCylinders
,
365 DiskGeometry
->NumberOfHeads
,
366 DiskGeometry
->SectorsPerTrack
,
367 DiskGeometry
->BytesPerSector
);
370 return PartialResourceList
;
375 PCONFIGURATION_COMPONENT_DATA SystemKey
,
376 PCONFIGURATION_COMPONENT_DATA BusKey
)
378 PCONFIGURATION_COMPONENT_DATA ControllerKey
, DiskKey
;
379 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
380 PCM_INT13_DRIVE_PARAMETER Int13Drives
;
382 UCHAR DiskCount
, DriveNumber
;
386 /* The pre-enumeration of the BIOS disks was already done in InitializeBootDevices() */
387 DiskCount
= PcBiosDiskCount
;
389 /* Use the floppy disk controller as our controller */
390 ControllerKey
= DetectBiosFloppyController(BusKey
);
393 ERR("Failed to detect BIOS disk controller\n");
397 /* Set 'Configuration Data' value */
398 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
399 sizeof(CM_INT13_DRIVE_PARAMETER
) * DiskCount
;
400 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
401 if (PartialResourceList
== NULL
)
403 ERR("Failed to allocate resource descriptor\n");
406 RtlZeroMemory(PartialResourceList
, Size
);
407 PartialResourceList
->Version
= 1;
408 PartialResourceList
->Revision
= 1;
409 PartialResourceList
->Count
= 1;
411 PartialResourceList
->PartialDescriptors
[0].Type
= CmResourceTypeDeviceSpecific
;
412 PartialResourceList
->PartialDescriptors
[0].ShareDisposition
= 0;
413 PartialResourceList
->PartialDescriptors
[0].Flags
= 0;
414 PartialResourceList
->PartialDescriptors
[0].u
.DeviceSpecificData
.DataSize
=
415 sizeof(CM_INT13_DRIVE_PARAMETER
) * DiskCount
;
417 /* Get hard disk Int13 geometry data */
418 Int13Drives
= (PVOID
)(((ULONG_PTR
)PartialResourceList
) + sizeof(CM_PARTIAL_RESOURCE_LIST
));
419 for (i
= 0; i
< DiskCount
; i
++)
421 DriveNumber
= 0x80 + i
;
423 if (Pc98DiskGetDriveGeometry(DriveNumber
, &Geometry
))
425 Int13Drives
[i
].DriveSelect
= DriveNumber
;
426 Int13Drives
[i
].MaxCylinders
= Geometry
.Cylinders
- 1;
427 Int13Drives
[i
].SectorsPerTrack
= (USHORT
)Geometry
.Sectors
;
428 Int13Drives
[i
].MaxHeads
= (USHORT
)Geometry
.Heads
- 1;
429 Int13Drives
[i
].NumberDrives
= DiskCount
;
431 TRACE("Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n",
433 Geometry
.Cylinders
- 1,
436 Geometry
.BytesPerSector
);
440 /* Update the 'System' key's configuration data with BIOS INT13h information */
441 FldrSetConfigurationData(SystemKey
, PartialResourceList
, Size
);
443 /* Create and fill subkey for each harddisk */
444 for (i
= 0; i
< DiskCount
; i
++)
448 DriveNumber
= 0x80 + i
;
450 /* Get disk values */
451 PartialResourceList
= GetHarddiskConfigurationData(DriveNumber
, &Size
);
452 Identifier
= GetHarddiskIdentifier(DriveNumber
);
454 /* Create disk key */
455 FldrCreateComponentKey(ControllerKey
,
465 TRACE("Created key: DiskPeripheral\\%d\n", i
);
470 DetectPointerPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey
)
472 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
473 PCONFIGURATION_COMPONENT_DATA PeripheralKey
;
476 /* TODO: Properly detect */
478 /* Set 'Configuration Data' value */
479 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) -
480 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
481 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
482 if (PartialResourceList
== NULL
)
484 ERR("Failed to allocate resource descriptor\n");
487 RtlZeroMemory(PartialResourceList
, Size
);
488 PartialResourceList
->Version
= 1;
489 PartialResourceList
->Revision
= 1;
490 PartialResourceList
->Count
= 0;
492 /* Create 'PointerPeripheral' key */
493 FldrCreateComponentKey(ControllerKey
,
499 "NEC PC-9800 BUS MOUSE",
503 TRACE("Created key: PointerPeripheral\\0\n");
507 DetectPointerController(PCONFIGURATION_COMPONENT_DATA BusKey
)
509 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
510 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
511 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
516 /* Set 'Configuration Data' value */
517 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
518 (HiResoMachine
? 6 : 5) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
519 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
520 if (PartialResourceList
== NULL
)
522 ERR("Failed to allocate resource descriptor\n");
525 RtlZeroMemory(PartialResourceList
, Size
);
526 PartialResourceList
->Version
= 1;
527 PartialResourceList
->Revision
= 1;
528 PartialResourceList
->Count
= (HiResoMachine
? 7 : 6);
531 for (i
= 0; i
< 4; i
++)
533 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[Index
++];
534 PartialDescriptor
->Type
= CmResourceTypePort
;
535 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
536 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
537 PartialDescriptor
->u
.Port
.Start
.LowPart
= (HiResoMachine
? 0x61 : 0x7FD9) + i
* 2;
538 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0;
539 PartialDescriptor
->u
.Port
.Length
= 1;
541 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[Index
++];
542 PartialDescriptor
->Type
= CmResourceTypePort
;
543 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
544 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
545 PartialDescriptor
->u
.Port
.Start
.LowPart
= (HiResoMachine
? 0x869 : 0xBFDB);
546 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0;
547 PartialDescriptor
->u
.Port
.Length
= 1;
550 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[Index
++];
551 PartialDescriptor
->Type
= CmResourceTypePort
;
552 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
553 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
554 PartialDescriptor
->u
.Port
.Start
.LowPart
= 0x98D7;
555 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0;
556 PartialDescriptor
->u
.Port
.Length
= 1;
560 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[Index
++];
561 PartialDescriptor
->Type
= CmResourceTypeInterrupt
;
562 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
563 PartialDescriptor
->Flags
= CM_RESOURCE_INTERRUPT_LATCHED
;
564 PartialDescriptor
->u
.Interrupt
.Level
= 13;
565 PartialDescriptor
->u
.Interrupt
.Vector
= 13;
566 PartialDescriptor
->u
.Interrupt
.Affinity
= 0xFFFFFFFF;
568 /* Create controller key */
569 FldrCreateComponentKey(BusKey
,
579 TRACE("Created key: PointerController\\0\n");
581 DetectPointerPeripheral(ControllerKey
);
585 DetectKeyboardPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey
)
587 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
588 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
589 PCM_KEYBOARD_DEVICE_DATA KeyboardData
;
590 PCONFIGURATION_COMPONENT_DATA PeripheralKey
;
594 UCHAR KeyboardType
= ((*(PUCHAR
)MEM_KEYB_TYPE
& 0x40) >> 5) |
595 ((*(PUCHAR
)MEM_KEYB_TYPE
& 0x08) >> 3);
597 /* TODO: Properly detect */
599 /* Set 'Configuration Data' value */
600 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
601 sizeof(CM_KEYBOARD_DEVICE_DATA
);
602 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
603 if (PartialResourceList
== NULL
)
605 ERR("Failed to allocate resource descriptor\n");
608 RtlZeroMemory(PartialResourceList
, Size
);
609 PartialResourceList
->Version
= 1;
610 PartialResourceList
->Revision
= 1;
611 PartialResourceList
->Count
= 1;
613 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[0];
614 PartialDescriptor
->Type
= CmResourceTypeDeviceSpecific
;
615 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
616 PartialDescriptor
->u
.DeviceSpecificData
.DataSize
= sizeof(CM_KEYBOARD_DEVICE_DATA
);
619 * KEYBOARD - GET SHIFT FLAGS
625 Int386(0x18, &Regs
, &Regs
);
627 KeyboardData
= (PCM_KEYBOARD_DEVICE_DATA
)(PartialDescriptor
+ 1);
628 KeyboardData
->Version
= 1;
629 KeyboardData
->Revision
= 1;
630 KeyboardData
->Type
= 7;
631 KeyboardData
->Subtype
= 1;
632 KeyboardData
->KeyboardFlags
= (Regs
.b
.al
& 0x08) |
633 ((Regs
.b
.al
& 0x02) << 6) |
634 ((Regs
.b
.al
& 0x10) << 2) |
635 ((Regs
.b
.al
& 0x01) << 1);
637 if (KeyboardType
== 0)
638 RtlStringCbPrintfA(Identifier
, sizeof(Identifier
), "PC98_NmodeKEY");
639 else if (KeyboardType
== 2)
640 RtlStringCbPrintfA(Identifier
, sizeof(Identifier
), "PC98_106KEY");
642 RtlStringCbPrintfA(Identifier
, sizeof(Identifier
), "PC98_LaptopKEY");
644 /* Create controller key */
645 FldrCreateComponentKey(ControllerKey
,
655 TRACE("Created key: KeyboardPeripheral\\0\n");
659 DetectKeyboardController(PCONFIGURATION_COMPONENT_DATA BusKey
)
661 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
662 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
663 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
667 if (!CpDoesPortExist((PUCHAR
)0x41))
670 /* Set 'Configuration Data' value */
671 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
672 2 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
673 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
674 if (PartialResourceList
== NULL
)
676 ERR("Failed to allocate resource descriptor\n");
679 RtlZeroMemory(PartialResourceList
, Size
);
680 PartialResourceList
->Version
= 1;
681 PartialResourceList
->Revision
= 1;
682 PartialResourceList
->Count
= 3;
685 for (i
= 0; i
< 2; i
++)
687 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[i
];
688 PartialDescriptor
->Type
= CmResourceTypePort
;
689 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
690 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
691 PartialDescriptor
->u
.Port
.Start
.LowPart
= 0x41 + i
* 2;
692 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0;
693 PartialDescriptor
->u
.Port
.Length
= 1;
697 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[2];
698 PartialDescriptor
->Type
= CmResourceTypeInterrupt
;
699 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
700 PartialDescriptor
->Flags
= CM_RESOURCE_INTERRUPT_LATCHED
;
701 PartialDescriptor
->u
.Interrupt
.Level
= 1;
702 PartialDescriptor
->u
.Interrupt
.Vector
= 1;
703 PartialDescriptor
->u
.Interrupt
.Affinity
= 0xFFFFFFFF;
705 /* Create controller key */
706 FldrCreateComponentKey(BusKey
,
716 TRACE("Created key: KeyboardController\\0\n");
718 DetectKeyboardPeripheral(ControllerKey
);
722 DetectParallelPorts(PCONFIGURATION_COMPONENT_DATA BusKey
)
724 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
725 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
726 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
731 /* TODO: Properly detect */
733 /* Set 'Configuration Data' value */
734 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
735 7 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
736 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
737 if (PartialResourceList
== NULL
)
739 ERR("Failed to allocate resource descriptor\n");
742 RtlZeroMemory(PartialResourceList
, Size
);
743 PartialResourceList
->Version
= 1;
744 PartialResourceList
->Revision
= 1;
745 PartialResourceList
->Count
= 8;
748 for (i
= 0; i
< 4; i
++)
750 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[Index
++];
751 PartialDescriptor
->Type
= CmResourceTypePort
;
752 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
753 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
754 PartialDescriptor
->u
.Port
.Start
.LowPart
= 0x40 + i
* 2;
755 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0;
756 PartialDescriptor
->u
.Port
.Length
= 3;
759 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[Index
++];
760 PartialDescriptor
->Type
= CmResourceTypePort
;
761 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
762 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
763 PartialDescriptor
->u
.Port
.Start
.LowPart
= 0x140;
764 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0;
765 PartialDescriptor
->u
.Port
.Length
= 3;
767 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[Index
++];
768 PartialDescriptor
->Type
= CmResourceTypePort
;
769 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
770 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
771 PartialDescriptor
->u
.Port
.Start
.LowPart
= 0x149;
772 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0;
773 PartialDescriptor
->u
.Port
.Length
= 1;
775 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[Index
++];
776 PartialDescriptor
->Type
= CmResourceTypePort
;
777 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
778 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
779 PartialDescriptor
->u
.Port
.Start
.LowPart
= 0x14B;
780 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0;
781 PartialDescriptor
->u
.Port
.Length
= 4;
784 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[Index
++];
785 PartialDescriptor
->Type
= CmResourceTypeInterrupt
;
786 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
787 PartialDescriptor
->Flags
= CM_RESOURCE_INTERRUPT_LATCHED
;
788 PartialDescriptor
->u
.Interrupt
.Level
= 14;
789 PartialDescriptor
->u
.Interrupt
.Vector
= 14;
790 PartialDescriptor
->u
.Interrupt
.Affinity
= 0xFFFFFFFF;
792 /* Create controller key */
793 FldrCreateComponentKey(BusKey
,
803 TRACE("Created key: ParallelController\\0\n");
807 DetectSerialPorts(PCONFIGURATION_COMPONENT_DATA BusKey
)
809 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
810 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
811 PCM_SERIAL_DEVICE_DATA SerialDeviceData
;
812 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
819 ULONG ControllerNumber
= 0;
821 if (CpDoesPortExist((PUCHAR
)0x30))
823 RtlStringCbPrintfA(Identifier
, sizeof(Identifier
), "COM%d", ControllerNumber
+ 1);
825 FifoStatus
= READ_PORT_UCHAR((PUCHAR
)0x136) & 0x40;
826 StallExecutionProcessor(5);
827 HasFifo
= ((READ_PORT_UCHAR((PUCHAR
)0x136) & 0x40) != FifoStatus
);
829 /* Set 'Configuration Data' value */
830 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
831 (HasFifo
? 10 : 3) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
) +
832 sizeof(CM_SERIAL_DEVICE_DATA
);
833 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
834 if (PartialResourceList
== NULL
)
836 ERR("Failed to allocate resource descriptor\n");
839 RtlZeroMemory(PartialResourceList
, Size
);
840 PartialResourceList
->Version
= 1;
841 PartialResourceList
->Revision
= 1;
842 PartialResourceList
->Count
= (HasFifo
? 11 : 4);
845 for (i
= 0; i
< 2; i
++)
847 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[Index
++];
848 PartialDescriptor
->Type
= CmResourceTypePort
;
849 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
850 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
851 PartialDescriptor
->u
.Port
.Start
.LowPart
= 0x30 + i
* 2;
852 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0;
853 PartialDescriptor
->u
.Port
.Length
= 1;
857 for (i
= 0; i
< 7; i
++)
859 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[Index
++];
860 PartialDescriptor
->Type
= CmResourceTypePort
;
861 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
862 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
863 PartialDescriptor
->u
.Port
.Start
.LowPart
= 0x130 + i
* 2;
864 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0;
865 PartialDescriptor
->u
.Port
.Length
= 1;
870 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[Index
++];
871 PartialDescriptor
->Type
= CmResourceTypeInterrupt
;
872 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
873 PartialDescriptor
->Flags
= CM_RESOURCE_INTERRUPT_LATCHED
;
874 PartialDescriptor
->u
.Interrupt
.Level
= 4;
875 PartialDescriptor
->u
.Interrupt
.Vector
= 4;
876 PartialDescriptor
->u
.Interrupt
.Affinity
= 0xFFFFFFFF;
878 /* Set serial data (device specific) */
879 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[Index
++];
880 PartialDescriptor
->Type
= CmResourceTypeDeviceSpecific
;
881 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
882 PartialDescriptor
->Flags
= 0;
883 PartialDescriptor
->u
.DeviceSpecificData
.DataSize
= sizeof(CM_SERIAL_DEVICE_DATA
);
885 SerialDeviceData
= (PCM_SERIAL_DEVICE_DATA
)&PartialResourceList
->PartialDescriptors
[Index
++];
886 SerialDeviceData
->BaudClock
= (*(PUCHAR
)MEM_BIOS_FLAG1
& SYSTEM_CLOCK_8MHZ_FLAG
) ?
887 TIMER_FREQUENCY_1
: TIMER_FREQUENCY_2
;
889 /* Create controller key */
890 FldrCreateComponentKey(BusKey
,
893 Output
| Input
| ConsoleIn
| ConsoleOut
,
900 TRACE("Created key: SerialController\\%d\n", ControllerNumber
);
905 if (CpDoesPortExist((PUCHAR
)0x238))
909 RtlStringCbPrintfA(Identifier
, sizeof(Identifier
), "COM%d", ControllerNumber
+ 1);
911 /* Set 'Configuration Data' value */
912 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
913 2 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
) +
914 sizeof(CM_SERIAL_DEVICE_DATA
);
915 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
916 if (PartialResourceList
== NULL
)
918 ERR("Failed to allocate resource descriptor\n");
921 RtlZeroMemory(PartialResourceList
, Size
);
922 PartialResourceList
->Version
= 1;
923 PartialResourceList
->Revision
= 1;
924 PartialResourceList
->Count
= 3;
927 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[Index
++];
928 PartialDescriptor
->Type
= CmResourceTypePort
;
929 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
930 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
931 PartialDescriptor
->u
.Port
.Start
.LowPart
= 0x238;
932 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0;
933 PartialDescriptor
->u
.Port
.Length
= 8;
936 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[Index
++];
937 PartialDescriptor
->Type
= CmResourceTypeInterrupt
;
938 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
939 PartialDescriptor
->Flags
= CM_RESOURCE_INTERRUPT_LATCHED
;
940 PartialDescriptor
->u
.Interrupt
.Level
= 5;
941 PartialDescriptor
->u
.Interrupt
.Vector
= 5;
942 PartialDescriptor
->u
.Interrupt
.Affinity
= 0xFFFFFFFF;
944 /* Set serial data (device specific) */
945 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[Index
++];
946 PartialDescriptor
->Type
= CmResourceTypeDeviceSpecific
;
947 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
948 PartialDescriptor
->Flags
= 0;
949 PartialDescriptor
->u
.DeviceSpecificData
.DataSize
= sizeof(CM_SERIAL_DEVICE_DATA
);
951 SerialDeviceData
= (PCM_SERIAL_DEVICE_DATA
)&PartialResourceList
->PartialDescriptors
[Index
++];
952 SerialDeviceData
->BaudClock
= 1843200;
954 /* Create controller key */
955 FldrCreateComponentKey(BusKey
,
958 Output
| Input
| ConsoleIn
| ConsoleOut
,
965 TRACE("Created key: SerialController\\%d\n", ControllerNumber
);
972 DetectCBusBios(PCONFIGURATION_COMPONENT_DATA SystemKey
, ULONG
*BusNumber
)
974 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
975 PCONFIGURATION_COMPONENT_DATA BusKey
;
978 /* Set 'Configuration Data' value */
979 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) -
980 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
981 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
982 if (PartialResourceList
== NULL
)
984 ERR("Failed to allocate resource descriptor\n");
987 RtlZeroMemory(PartialResourceList
, Size
);
988 PartialResourceList
->Version
= 1;
989 PartialResourceList
->Revision
= 1;
990 PartialResourceList
->Count
= 0;
993 FldrCreateComponentKey(SystemKey
,
995 MultiFunctionAdapter
,
1000 PartialResourceList
,
1004 /* Increment bus number */
1007 /* Detect C-bus/BIOS devices */
1008 DetectBiosDisks(SystemKey
, BusKey
);
1009 DetectSerialPorts(BusKey
);
1010 DetectParallelPorts(BusKey
);
1011 DetectKeyboardController(BusKey
);
1012 DetectPointerController(BusKey
);
1014 /* FIXME: Detect more C-bus devices */
1018 DetectNesaBios(PCONFIGURATION_COMPONENT_DATA SystemKey
, ULONG
*BusNumber
)
1020 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
1021 PCONFIGURATION_COMPONENT_DATA BusKey
;
1024 if (!((*(PUCHAR
)MEM_BIOS_FLAG5
) & NESA_BUS_FLAG
))
1027 /* Set 'Configuration Data' value */
1028 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) -
1029 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1030 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
1031 if (PartialResourceList
== NULL
)
1033 ERR("Failed to allocate resource descriptor\n");
1036 RtlZeroMemory(PartialResourceList
, Size
);
1037 PartialResourceList
->Version
= 1;
1038 PartialResourceList
->Revision
= 1;
1039 PartialResourceList
->Count
= 0;
1041 /* Create bus key */
1042 FldrCreateComponentKey(SystemKey
,
1044 MultiFunctionAdapter
,
1049 PartialResourceList
,
1053 /* Increment bus number */
1057 // FIXME: Copied from machpc.c
1059 DetectPnpBios(PCONFIGURATION_COMPONENT_DATA SystemKey
, ULONG
*BusNumber
)
1061 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
1062 PCM_PNP_BIOS_DEVICE_NODE DeviceNode
;
1063 PCM_PNP_BIOS_INSTALLATION_CHECK InstData
;
1064 PCONFIGURATION_COMPONENT_DATA BusKey
;
1067 ULONG NodeCount
= 0;
1069 ULONG FoundNodeCount
;
1071 ULONG PnpBufferSize
;
1072 ULONG PnpBufferSizeLimit
;
1076 InstData
= (PCM_PNP_BIOS_INSTALLATION_CHECK
)PnpBiosSupported();
1077 if (InstData
== NULL
|| strncmp((CHAR
*)InstData
->Signature
, "$PnP", 4))
1079 TRACE("PnP-BIOS not supported\n");
1083 TRACE("PnP-BIOS supported\n");
1084 TRACE("Signature '%c%c%c%c'\n",
1085 InstData
->Signature
[0], InstData
->Signature
[1],
1086 InstData
->Signature
[2], InstData
->Signature
[3]);
1088 x
= PnpBiosGetDeviceNodeCount(&NodeSize
, &NodeCount
);
1091 TRACE("PnP-BIOS function 'Get Number of System Device Nodes' not supported\n");
1095 NodeCount
&= 0xFF; // needed since some fscked up BIOSes return
1096 // wrong info (e.g. Mac Virtual PC)
1097 // e.g. look: http://my.execpc.com/~geezer/osd/pnp/pnp16.c
1098 if (x
!= 0 || NodeSize
== 0 || NodeCount
== 0)
1100 ERR("PnP-BIOS failed to enumerate device nodes\n");
1103 TRACE("MaxNodeSize %u NodeCount %u\n", NodeSize
, NodeCount
);
1104 TRACE("Estimated buffer size %u\n", NodeSize
* NodeCount
);
1106 /* Set 'Configuration Data' value */
1107 PnpBufferSizeLimit
= sizeof(CM_PNP_BIOS_INSTALLATION_CHECK
)
1108 + (NodeSize
* NodeCount
);
1109 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) + PnpBufferSizeLimit
;
1110 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
1111 if (PartialResourceList
== NULL
)
1113 ERR("Failed to allocate resource descriptor\n");
1116 RtlZeroMemory(PartialResourceList
, Size
);
1118 /* Initialize resource descriptor */
1119 PartialResourceList
->Version
= 1;
1120 PartialResourceList
->Revision
= 1;
1121 PartialResourceList
->Count
= 1;
1122 PartialResourceList
->PartialDescriptors
[0].Type
=
1123 CmResourceTypeDeviceSpecific
;
1124 PartialResourceList
->PartialDescriptors
[0].ShareDisposition
=
1125 CmResourceShareUndetermined
;
1127 /* The buffer starts after PartialResourceList->PartialDescriptors[0] */
1128 Ptr
= (char *)(PartialResourceList
+ 1);
1130 /* Set installation check data */
1131 RtlCopyMemory(Ptr
, InstData
, sizeof(CM_PNP_BIOS_INSTALLATION_CHECK
));
1132 Ptr
+= sizeof(CM_PNP_BIOS_INSTALLATION_CHECK
);
1133 PnpBufferSize
= sizeof(CM_PNP_BIOS_INSTALLATION_CHECK
);
1135 /* Copy device nodes */
1137 for (i
= 0; i
< 0xFF; i
++)
1139 NodeNumber
= (UCHAR
)i
;
1141 x
= PnpBiosGetDeviceNode(&NodeNumber
, DiskReadBuffer
);
1144 DeviceNode
= (PCM_PNP_BIOS_DEVICE_NODE
)DiskReadBuffer
;
1146 TRACE("Node: %u Size %u (0x%x)\n",
1151 if (PnpBufferSize
+ DeviceNode
->Size
> PnpBufferSizeLimit
)
1153 ERR("Buffer too small! Ignoring remaining device nodes.\n");
1157 RtlCopyMemory(Ptr
, DeviceNode
, DeviceNode
->Size
);
1159 Ptr
+= DeviceNode
->Size
;
1160 PnpBufferSize
+= DeviceNode
->Size
;
1163 if (FoundNodeCount
>= NodeCount
)
1168 /* Set real data size */
1169 PartialResourceList
->PartialDescriptors
[0].u
.DeviceSpecificData
.DataSize
=
1171 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) + PnpBufferSize
;
1173 TRACE("Real buffer size: %u\n", PnpBufferSize
);
1174 TRACE("Resource size: %u\n", Size
);
1176 /* Create component key */
1177 FldrCreateComponentKey(SystemKey
,
1179 MultiFunctionAdapter
,
1184 PartialResourceList
,
1191 PCONFIGURATION_COMPONENT_DATA
1194 PCONFIGURATION_COMPONENT_DATA SystemKey
;
1195 ULONG BusNumber
= 0;
1197 TRACE("DetectHardware()\n");
1199 /* Create the 'System' key */
1200 FldrCreateSystemKey(&SystemKey
);
1201 FldrSetIdentifier(SystemKey
, "NEC PC-98");
1203 GetHarddiskConfigurationData
= Pc98GetHarddiskConfigurationData
;
1204 FindPciBios
= PcFindPciBios
;
1207 DetectPciBios(SystemKey
, &BusNumber
);
1208 DetectApmBios(SystemKey
, &BusNumber
);
1209 DetectPnpBios(SystemKey
, &BusNumber
);
1210 DetectNesaBios(SystemKey
, &BusNumber
);
1211 DetectCBusBios(SystemKey
, &BusNumber
);
1212 DetectAcpiBios(SystemKey
, &BusNumber
);
1213 // TODO: Detect more buses
1215 // TODO: Collect the ROM blocks and append their
1216 // CM_ROM_BLOCK data into the 'System' key's configuration data.
1218 TRACE("DetectHardware() Done\n");
1223 Pc98GetFloppyCount(VOID
)
1225 USHORT DiskEquipment
= *(PUSHORT
)MEM_DISK_EQUIP
& ~(*(PUCHAR
)MEM_RDISK_EQUIP
);
1227 UCHAR FloppyCount
= 0;
1229 for (DiskMask
= 0x01; DiskMask
!= 0; DiskMask
<<= 1)
1231 if (FIRSTBYTE(DiskEquipment
) & DiskMask
)
1235 for (DiskMask
= 0x10; DiskMask
!= 0; DiskMask
<<= 1)
1237 if (SECONDBYTE(DiskEquipment
) & DiskMask
)
1244 VOID __cdecl
DiskStopFloppyMotor(VOID
)
1246 WRITE_PORT_UCHAR((PUCHAR
)(FDC1_IO_BASE
+ FDC_o_CONTROL
), 0);
1247 WRITE_PORT_UCHAR((PUCHAR
)(FDC2_IO_BASE
+ FDC_o_CONTROL
), 0);
1250 // FIXME: 1) Copied from pchw.c 2) Should be done inside MachInit.
1252 FrLdrCheckCpuCompatibility(VOID
)
1254 INT CpuInformation
[4] = {-1};
1257 /* Check if the processor first supports ID 1 */
1258 __cpuid(CpuInformation
, 0);
1260 NumberOfIds
= CpuInformation
[0];
1262 if (NumberOfIds
== 0)
1264 FrLdrBugCheckWithMessage(MISSING_HARDWARE_REQUIREMENTS
,
1267 "ReactOS requires the CPUID instruction to return "
1268 "more than one supported ID.\n\n");
1271 /* NumberOfIds will be greater than 1 if the processor is new enough */
1272 if (NumberOfIds
== 1)
1274 INT ProcessorFamily
;
1276 /* Get information */
1277 __cpuid(CpuInformation
, 1);
1279 ProcessorFamily
= (CpuInformation
[0] >> 8) & 0xF;
1281 /* If it's Family 4 or lower, bugcheck */
1282 if (ProcessorFamily
< 5)
1284 FrLdrBugCheckWithMessage(MISSING_HARDWARE_REQUIREMENTS
,
1287 "Processor is too old (family %u < 5)\n"
1288 "ReactOS requires a Pentium-level processor or newer.",