[SETUPLIB] Add two hacks in partlist.c for temporarily setting consistently the disk...
[reactos.git] / boot / freeldr / freeldr / arch / i386 / pc98 / pc98hw.c
1 /*
2 * PROJECT: FreeLoader
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)
6 */
7
8 /* INCLUDES *******************************************************************/
9
10 #include <freeldr.h>
11 #include <cportlib/cportlib.h>
12 #include <drivers/pc98/pit.h>
13 #include <drivers/pc98/fdc.h>
14
15 #include <debug.h>
16 DBG_DEFAULT_CHANNEL(HWDETECT);
17
18 /* Used for BIOS disks pre-enumeration performed when detecting the boot devices in InitializeBootDevices() */
19 extern UCHAR PcBiosDiskCount;
20
21 extern BOOLEAN HiResoMachine;
22
23 GET_HARDDISK_CONFIG_DATA GetHarddiskConfigurationData = NULL;
24
25 /* GLOBALS ********************************************************************/
26
27 #define MILLISEC 10
28 #define PRECISION 8
29 #define HZ 100
30
31 static unsigned int delay_count = 1;
32
33 PCHAR
34 GetHarddiskIdentifier(UCHAR DriveNumber);
35
36 /* FUNCTIONS ******************************************************************/
37
38 static VOID
39 __StallExecutionProcessor(ULONG Loops)
40 {
41 register volatile unsigned int i;
42 for (i = 0; i < Loops; i++);
43 }
44
45 VOID StallExecutionProcessor(ULONG Microseconds)
46 {
47 ULONGLONG LoopCount = ((ULONGLONG)delay_count * (ULONGLONG)Microseconds) / 1000ULL;
48 __StallExecutionProcessor((ULONG)LoopCount);
49 }
50
51 static VOID
52 WaitFor8253Wraparound(VOID)
53 {
54 ULONG CurrentCount;
55 ULONG PreviousCount = ~0;
56 LONG Delta;
57
58 CurrentCount = Read8253Timer(PitChannel0);
59
60 do
61 {
62 PreviousCount = CurrentCount;
63 CurrentCount = Read8253Timer(PitChannel0);
64 Delta = CurrentCount - PreviousCount;
65 }
66 while (Delta < 300);
67 }
68
69 VOID
70 HalpCalibrateStallExecution(VOID)
71 {
72 ULONG i;
73 ULONG calib_bit;
74 ULONG CurCount;
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);
78
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);
85
86 /* Stage 1: Coarse calibration */
87
88 delay_count = 1;
89
90 do
91 {
92 /* Next delay count to try */
93 delay_count <<= 1;
94
95 WaitFor8253Wraparound();
96
97 /* Do the delay */
98 __StallExecutionProcessor(delay_count);
99
100 CurCount = Read8253Timer(PitChannel0);
101 }
102 while (CurCount > Count / 2);
103
104 /* Get bottom value for delay */
105 delay_count >>= 1;
106
107 /* Stage 2: Fine calibration */
108
109 /* Which bit are we going to test */
110 calib_bit = delay_count;
111
112 for (i = 0; i < PRECISION; i++)
113 {
114 /* Next bit to calibrate */
115 calib_bit >>= 1;
116
117 /* If we have done all bits, stop */
118 if (!calib_bit)
119 break;
120
121 /* Set the bit in delay_count */
122 delay_count |= calib_bit;
123
124 WaitFor8253Wraparound();
125
126 /* Do the delay */
127 __StallExecutionProcessor(delay_count);
128
129 CurCount = Read8253Timer(PitChannel0);
130
131 /* If a tick has passed, turn the calibrated bit back off */
132 if (CurCount <= Count / 2)
133 delay_count &= ~calib_bit;
134 }
135
136 /* We're finished: Do the finishing touches */
137
138 /* Calculate delay_count for 1ms */
139 delay_count /= (MILLISEC / 2);
140 }
141
142 static UCHAR
143 GetFloppyType(UCHAR FloppyNumber)
144 {
145 /* FIXME */
146 return 5;
147 }
148
149 static VOID
150 DetectBiosFloppyPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey)
151 {
152 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
153 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
154 PCM_FLOPPY_DEVICE_DATA FloppyData;
155 CHAR Identifier[20];
156 PCONFIGURATION_COMPONENT_DATA PeripheralKey;
157 ULONG Size;
158 UCHAR FloppyNumber;
159 UCHAR FloppyType;
160 ULONG MaxDensity[6] = {0, 360, 1200, 720, 1440, 2880};
161
162 for (FloppyNumber = 0; FloppyNumber < Pc98GetFloppyCount(); FloppyNumber++)
163 {
164 FloppyType = GetFloppyType(FloppyNumber);
165
166 if ((FloppyType > 5) || (FloppyType == 0))
167 continue;
168
169 /* TODO: Properly detect */
170
171 RtlStringCbPrintfA(Identifier, sizeof(Identifier), "FLOPPY%d", FloppyNumber + 1);
172
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)
178 {
179 ERR("Failed to allocate resource descriptor\n");
180 return;
181 }
182 RtlZeroMemory(PartialResourceList, Size);
183 PartialResourceList->Version = 1;
184 PartialResourceList->Revision = 1;
185 PartialResourceList->Count = 1;
186
187 PartialDescriptor = &PartialResourceList->PartialDescriptors[0];
188 PartialDescriptor->Type = CmResourceTypeDeviceSpecific;
189 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
190 PartialDescriptor->u.DeviceSpecificData.DataSize = sizeof(CM_FLOPPY_DEVICE_DATA);
191
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;
211
212 FldrCreateComponentKey(ControllerKey,
213 PeripheralClass,
214 FloppyDiskPeripheral,
215 Input | Output,
216 FloppyNumber,
217 0xFFFFFFFF,
218 Identifier,
219 PartialResourceList,
220 Size,
221 &PeripheralKey);
222 TRACE("Created key: FloppyDiskPeripheral\\%d\n", FloppyNumber);
223 }
224 }
225
226 static PCONFIGURATION_COMPONENT_DATA
227 DetectBiosFloppyController(PCONFIGURATION_COMPONENT_DATA BusKey)
228 {
229 PCONFIGURATION_COMPONENT_DATA ControllerKey;
230 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
231 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
232 ULONG Size;
233 ULONG FloppyCount;
234 UCHAR i;
235 UCHAR Index = 0;
236
237 FloppyCount = Pc98GetFloppyCount();
238
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)
244 {
245 ERR("Failed to allocate resource descriptor\n");
246 return NULL;
247 }
248 RtlZeroMemory(PartialResourceList, Size);
249 PartialResourceList->Version = 1;
250 PartialResourceList->Revision = 1;
251 PartialResourceList->Count = 7;
252
253 /* Set I/O ports */
254 for (i = 0; i < 3; i++)
255 {
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;
263 }
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;
271
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;
279
280 /* Set Interrupt */
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;
288
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;
296
297 /* Create floppy disk controller */
298 FldrCreateComponentKey(BusKey,
299 ControllerClass,
300 DiskController,
301 Output | Input,
302 0,
303 0xFFFFFFFF,
304 NULL,
305 PartialResourceList,
306 Size,
307 &ControllerKey);
308 TRACE("Created key: DiskController\\0\n");
309
310 if (FloppyCount)
311 DetectBiosFloppyPeripheral(ControllerKey);
312
313 return ControllerKey;
314 }
315
316 static PCM_PARTIAL_RESOURCE_LIST
317 Pc98GetHarddiskConfigurationData(UCHAR DriveNumber, ULONG* pSize)
318 {
319 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
320 PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry;
321 GEOMETRY Geometry;
322 ULONG Size;
323
324 *pSize = 0;
325
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)
331 {
332 ERR("Failed to allocate resource descriptor\n");
333 return NULL;
334 }
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);
344
345 /* Get pointer to geometry data */
346 DiskGeometry = (PVOID)(((ULONG_PTR)PartialResourceList) + sizeof(CM_PARTIAL_RESOURCE_LIST));
347
348 /* Get the disk geometry. Extended geometry isn't supported by hardware */
349 if (Pc98DiskGetDriveGeometry(DriveNumber, &Geometry))
350 {
351 DiskGeometry->BytesPerSector = Geometry.BytesPerSector;
352 DiskGeometry->NumberOfCylinders = Geometry.Cylinders;
353 DiskGeometry->SectorsPerTrack = Geometry.Sectors;
354 DiskGeometry->NumberOfHeads = Geometry.Heads;
355 }
356 else
357 {
358 TRACE("Reading disk geometry failed\n");
359 FrLdrHeapFree(PartialResourceList, TAG_HW_RESOURCE_LIST);
360 return NULL;
361 }
362 TRACE("Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n",
363 DriveNumber,
364 DiskGeometry->NumberOfCylinders,
365 DiskGeometry->NumberOfHeads,
366 DiskGeometry->SectorsPerTrack,
367 DiskGeometry->BytesPerSector);
368
369 *pSize = Size;
370 return PartialResourceList;
371 }
372
373 VOID
374 DetectBiosDisks(
375 PCONFIGURATION_COMPONENT_DATA SystemKey,
376 PCONFIGURATION_COMPONENT_DATA BusKey)
377 {
378 PCONFIGURATION_COMPONENT_DATA ControllerKey, DiskKey;
379 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
380 PCM_INT13_DRIVE_PARAMETER Int13Drives;
381 GEOMETRY Geometry;
382 UCHAR DiskCount, DriveNumber;
383 USHORT i;
384 ULONG Size;
385
386 /* The pre-enumeration of the BIOS disks was already done in InitializeBootDevices() */
387 DiskCount = PcBiosDiskCount;
388
389 /* Use the floppy disk controller as our controller */
390 ControllerKey = DetectBiosFloppyController(BusKey);
391 if (!ControllerKey)
392 {
393 ERR("Failed to detect BIOS disk controller\n");
394 return;
395 }
396
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)
402 {
403 ERR("Failed to allocate resource descriptor\n");
404 return;
405 }
406 RtlZeroMemory(PartialResourceList, Size);
407 PartialResourceList->Version = 1;
408 PartialResourceList->Revision = 1;
409 PartialResourceList->Count = 1;
410
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;
416
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++)
420 {
421 DriveNumber = 0x80 + i;
422
423 if (Pc98DiskGetDriveGeometry(DriveNumber, &Geometry))
424 {
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;
430
431 TRACE("Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n",
432 DriveNumber,
433 Geometry.Cylinders - 1,
434 Geometry.Heads - 1,
435 Geometry.Sectors,
436 Geometry.BytesPerSector);
437 }
438 }
439
440 /* Update the 'System' key's configuration data with BIOS INT13h information */
441 FldrSetConfigurationData(SystemKey, PartialResourceList, Size);
442
443 /* Create and fill subkey for each harddisk */
444 for (i = 0; i < DiskCount; i++)
445 {
446 PCHAR Identifier;
447
448 DriveNumber = 0x80 + i;
449
450 /* Get disk values */
451 PartialResourceList = GetHarddiskConfigurationData(DriveNumber, &Size);
452 Identifier = GetHarddiskIdentifier(DriveNumber);
453
454 /* Create disk key */
455 FldrCreateComponentKey(ControllerKey,
456 PeripheralClass,
457 DiskPeripheral,
458 Output | Input,
459 i,
460 0xFFFFFFFF,
461 Identifier,
462 PartialResourceList,
463 Size,
464 &DiskKey);
465 TRACE("Created key: DiskPeripheral\\%d\n", i);
466 }
467 }
468
469 static VOID
470 DetectPointerPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey)
471 {
472 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
473 PCONFIGURATION_COMPONENT_DATA PeripheralKey;
474 ULONG Size;
475
476 /* TODO: Properly detect */
477
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)
483 {
484 ERR("Failed to allocate resource descriptor\n");
485 return;
486 }
487 RtlZeroMemory(PartialResourceList, Size);
488 PartialResourceList->Version = 1;
489 PartialResourceList->Revision = 1;
490 PartialResourceList->Count = 0;
491
492 /* Create 'PointerPeripheral' key */
493 FldrCreateComponentKey(ControllerKey,
494 PeripheralClass,
495 PointerPeripheral,
496 Input,
497 0,
498 0xFFFFFFFF,
499 "NEC PC-9800 BUS MOUSE",
500 PartialResourceList,
501 Size,
502 &PeripheralKey);
503 TRACE("Created key: PointerPeripheral\\0\n");
504 }
505
506 static VOID
507 DetectPointerController(PCONFIGURATION_COMPONENT_DATA BusKey)
508 {
509 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
510 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
511 PCONFIGURATION_COMPONENT_DATA ControllerKey;
512 ULONG Size;
513 UCHAR i;
514 UCHAR Index = 0;
515
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)
521 {
522 ERR("Failed to allocate resource descriptor\n");
523 return;
524 }
525 RtlZeroMemory(PartialResourceList, Size);
526 PartialResourceList->Version = 1;
527 PartialResourceList->Revision = 1;
528 PartialResourceList->Count = (HiResoMachine ? 7 : 6);
529
530 /* Set I/O ports */
531 for (i = 0; i < 4; i++)
532 {
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;
540 }
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;
548 if (HiResoMachine)
549 {
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;
557 }
558
559 /* Set Interrupt */
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;
567
568 /* Create controller key */
569 FldrCreateComponentKey(BusKey,
570 ControllerClass,
571 PointerController,
572 Input,
573 0,
574 0xFFFFFFFF,
575 NULL,
576 PartialResourceList,
577 Size,
578 &ControllerKey);
579 TRACE("Created key: PointerController\\0\n");
580
581 DetectPointerPeripheral(ControllerKey);
582 }
583
584 static VOID
585 DetectKeyboardPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey)
586 {
587 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
588 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
589 PCM_KEYBOARD_DEVICE_DATA KeyboardData;
590 PCONFIGURATION_COMPONENT_DATA PeripheralKey;
591 CHAR Identifier[80];
592 ULONG Size;
593 REGS Regs;
594 UCHAR KeyboardType = ((*(PUCHAR)MEM_KEYB_TYPE & 0x40) >> 5) |
595 ((*(PUCHAR)MEM_KEYB_TYPE & 0x08) >> 3);
596
597 /* TODO: Properly detect */
598
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)
604 {
605 ERR("Failed to allocate resource descriptor\n");
606 return;
607 }
608 RtlZeroMemory(PartialResourceList, Size);
609 PartialResourceList->Version = 1;
610 PartialResourceList->Revision = 1;
611 PartialResourceList->Count = 1;
612
613 PartialDescriptor = &PartialResourceList->PartialDescriptors[0];
614 PartialDescriptor->Type = CmResourceTypeDeviceSpecific;
615 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
616 PartialDescriptor->u.DeviceSpecificData.DataSize = sizeof(CM_KEYBOARD_DEVICE_DATA);
617
618 /* Int 18h AH=02h
619 * KEYBOARD - GET SHIFT FLAGS
620 *
621 * Return:
622 * AL - shift flags
623 */
624 Regs.b.ah = 0x02;
625 Int386(0x18, &Regs, &Regs);
626
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);
636
637 if (KeyboardType == 0)
638 RtlStringCbPrintfA(Identifier, sizeof(Identifier), "PC98_NmodeKEY");
639 else if (KeyboardType == 2)
640 RtlStringCbPrintfA(Identifier, sizeof(Identifier), "PC98_106KEY");
641 else
642 RtlStringCbPrintfA(Identifier, sizeof(Identifier), "PC98_LaptopKEY");
643
644 /* Create controller key */
645 FldrCreateComponentKey(ControllerKey,
646 PeripheralClass,
647 KeyboardPeripheral,
648 Input | ConsoleIn,
649 0,
650 0xFFFFFFFF,
651 Identifier,
652 PartialResourceList,
653 Size,
654 &PeripheralKey);
655 TRACE("Created key: KeyboardPeripheral\\0\n");
656 }
657
658 static VOID
659 DetectKeyboardController(PCONFIGURATION_COMPONENT_DATA BusKey)
660 {
661 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
662 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
663 PCONFIGURATION_COMPONENT_DATA ControllerKey;
664 ULONG Size;
665 UCHAR i;
666
667 if (!CpDoesPortExist((PUCHAR)0x41))
668 return;
669
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)
675 {
676 ERR("Failed to allocate resource descriptor\n");
677 return;
678 }
679 RtlZeroMemory(PartialResourceList, Size);
680 PartialResourceList->Version = 1;
681 PartialResourceList->Revision = 1;
682 PartialResourceList->Count = 3;
683
684 /* Set I/O ports */
685 for (i = 0; i < 2; i++)
686 {
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;
694 }
695
696 /* Set Interrupt */
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;
704
705 /* Create controller key */
706 FldrCreateComponentKey(BusKey,
707 ControllerClass,
708 KeyboardController,
709 Input | ConsoleIn,
710 0,
711 0xFFFFFFFF,
712 NULL,
713 PartialResourceList,
714 Size,
715 &ControllerKey);
716 TRACE("Created key: KeyboardController\\0\n");
717
718 DetectKeyboardPeripheral(ControllerKey);
719 }
720
721 static VOID
722 DetectParallelPorts(PCONFIGURATION_COMPONENT_DATA BusKey)
723 {
724 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
725 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
726 PCONFIGURATION_COMPONENT_DATA ControllerKey;
727 ULONG Size;
728 UCHAR i;
729 UCHAR Index = 0;
730
731 /* TODO: Properly detect */
732
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)
738 {
739 ERR("Failed to allocate resource descriptor\n");
740 return;
741 }
742 RtlZeroMemory(PartialResourceList, Size);
743 PartialResourceList->Version = 1;
744 PartialResourceList->Revision = 1;
745 PartialResourceList->Count = 8;
746
747 /* Set I/O ports */
748 for (i = 0; i < 4; i++)
749 {
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;
757 }
758
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;
766
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;
774
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;
782
783 /* Set Interrupt */
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;
791
792 /* Create controller key */
793 FldrCreateComponentKey(BusKey,
794 ControllerClass,
795 ParallelController,
796 Output,
797 0,
798 0xFFFFFFFF,
799 "PARALLEL1",
800 PartialResourceList,
801 Size,
802 &ControllerKey);
803 TRACE("Created key: ParallelController\\0\n");
804 }
805
806 static VOID
807 DetectSerialPorts(PCONFIGURATION_COMPONENT_DATA BusKey)
808 {
809 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
810 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
811 PCM_SERIAL_DEVICE_DATA SerialDeviceData;
812 PCONFIGURATION_COMPONENT_DATA ControllerKey;
813 CHAR Identifier[80];
814 UCHAR i;
815 ULONG Size;
816 UCHAR FifoStatus;
817 BOOLEAN HasFifo;
818 UCHAR Index = 0;
819 ULONG ControllerNumber = 0;
820
821 if (CpDoesPortExist((PUCHAR)0x30))
822 {
823 RtlStringCbPrintfA(Identifier, sizeof(Identifier), "COM%d", ControllerNumber + 1);
824
825 FifoStatus = READ_PORT_UCHAR((PUCHAR)0x136) & 0x40;
826 StallExecutionProcessor(5);
827 HasFifo = ((READ_PORT_UCHAR((PUCHAR)0x136) & 0x40) != FifoStatus);
828
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)
835 {
836 ERR("Failed to allocate resource descriptor\n");
837 return;
838 }
839 RtlZeroMemory(PartialResourceList, Size);
840 PartialResourceList->Version = 1;
841 PartialResourceList->Revision = 1;
842 PartialResourceList->Count = (HasFifo ? 11 : 4);
843
844 /* Set I/O ports */
845 for (i = 0; i < 2; i++)
846 {
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;
854 }
855 if (HasFifo)
856 {
857 for (i = 0; i < 7; i++)
858 {
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;
866 }
867 }
868
869 /* Set Interrupt */
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;
877
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);
884
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;
888
889 /* Create controller key */
890 FldrCreateComponentKey(BusKey,
891 ControllerClass,
892 SerialController,
893 Output | Input | ConsoleIn | ConsoleOut,
894 ControllerNumber,
895 0xFFFFFFFF,
896 Identifier,
897 PartialResourceList,
898 Size,
899 &ControllerKey);
900 TRACE("Created key: SerialController\\%d\n", ControllerNumber);
901
902 ++ControllerNumber;
903 }
904
905 if (CpDoesPortExist((PUCHAR)0x238))
906 {
907 Index = 0;
908
909 RtlStringCbPrintfA(Identifier, sizeof(Identifier), "COM%d", ControllerNumber + 1);
910
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)
917 {
918 ERR("Failed to allocate resource descriptor\n");
919 return;
920 }
921 RtlZeroMemory(PartialResourceList, Size);
922 PartialResourceList->Version = 1;
923 PartialResourceList->Revision = 1;
924 PartialResourceList->Count = 3;
925
926 /* Set I/O ports */
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;
934
935 /* Set Interrupt */
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;
943
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);
950
951 SerialDeviceData = (PCM_SERIAL_DEVICE_DATA)&PartialResourceList->PartialDescriptors[Index++];
952 SerialDeviceData->BaudClock = 1843200;
953
954 /* Create controller key */
955 FldrCreateComponentKey(BusKey,
956 ControllerClass,
957 SerialController,
958 Output | Input | ConsoleIn | ConsoleOut,
959 ControllerNumber,
960 0xFFFFFFFF,
961 Identifier,
962 PartialResourceList,
963 Size,
964 &ControllerKey);
965 TRACE("Created key: SerialController\\%d\n", ControllerNumber);
966
967 ++ControllerNumber;
968 }
969 }
970
971 static VOID
972 DetectCBusBios(PCONFIGURATION_COMPONENT_DATA SystemKey, ULONG *BusNumber)
973 {
974 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
975 PCONFIGURATION_COMPONENT_DATA BusKey;
976 ULONG Size;
977
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)
983 {
984 ERR("Failed to allocate resource descriptor\n");
985 return;
986 }
987 RtlZeroMemory(PartialResourceList, Size);
988 PartialResourceList->Version = 1;
989 PartialResourceList->Revision = 1;
990 PartialResourceList->Count = 0;
991
992 /* Create bus key */
993 FldrCreateComponentKey(SystemKey,
994 AdapterClass,
995 MultiFunctionAdapter,
996 0x0,
997 0,
998 0xFFFFFFFF,
999 "ISA",
1000 PartialResourceList,
1001 Size,
1002 &BusKey);
1003
1004 /* Increment bus number */
1005 (*BusNumber)++;
1006
1007 /* Detect C-bus/BIOS devices */
1008 DetectBiosDisks(SystemKey, BusKey);
1009 DetectSerialPorts(BusKey);
1010 DetectParallelPorts(BusKey);
1011 DetectKeyboardController(BusKey);
1012 DetectPointerController(BusKey);
1013
1014 /* FIXME: Detect more C-bus devices */
1015 }
1016
1017 static VOID
1018 DetectNesaBios(PCONFIGURATION_COMPONENT_DATA SystemKey, ULONG *BusNumber)
1019 {
1020 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
1021 PCONFIGURATION_COMPONENT_DATA BusKey;
1022 ULONG Size;
1023
1024 if (!((*(PUCHAR)MEM_BIOS_FLAG5) & NESA_BUS_FLAG))
1025 return;
1026
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)
1032 {
1033 ERR("Failed to allocate resource descriptor\n");
1034 return;
1035 }
1036 RtlZeroMemory(PartialResourceList, Size);
1037 PartialResourceList->Version = 1;
1038 PartialResourceList->Revision = 1;
1039 PartialResourceList->Count = 0;
1040
1041 /* Create bus key */
1042 FldrCreateComponentKey(SystemKey,
1043 AdapterClass,
1044 MultiFunctionAdapter,
1045 0x0,
1046 0,
1047 0xFFFFFFFF,
1048 "EISA",
1049 PartialResourceList,
1050 Size,
1051 &BusKey);
1052
1053 /* Increment bus number */
1054 (*BusNumber)++;
1055 }
1056
1057 // FIXME: Copied from machpc.c
1058 static VOID
1059 DetectPnpBios(PCONFIGURATION_COMPONENT_DATA SystemKey, ULONG *BusNumber)
1060 {
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;
1065 ULONG x;
1066 ULONG NodeSize = 0;
1067 ULONG NodeCount = 0;
1068 UCHAR NodeNumber;
1069 ULONG FoundNodeCount;
1070 int i;
1071 ULONG PnpBufferSize;
1072 ULONG PnpBufferSizeLimit;
1073 ULONG Size;
1074 char *Ptr;
1075
1076 InstData = (PCM_PNP_BIOS_INSTALLATION_CHECK)PnpBiosSupported();
1077 if (InstData == NULL || strncmp((CHAR*)InstData->Signature, "$PnP", 4))
1078 {
1079 TRACE("PnP-BIOS not supported\n");
1080 return;
1081 }
1082
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]);
1087
1088 x = PnpBiosGetDeviceNodeCount(&NodeSize, &NodeCount);
1089 if (x == 0x82)
1090 {
1091 TRACE("PnP-BIOS function 'Get Number of System Device Nodes' not supported\n");
1092 return;
1093 }
1094
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)
1099 {
1100 ERR("PnP-BIOS failed to enumerate device nodes\n");
1101 return;
1102 }
1103 TRACE("MaxNodeSize %u NodeCount %u\n", NodeSize, NodeCount);
1104 TRACE("Estimated buffer size %u\n", NodeSize * NodeCount);
1105
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)
1112 {
1113 ERR("Failed to allocate resource descriptor\n");
1114 return;
1115 }
1116 RtlZeroMemory(PartialResourceList, Size);
1117
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;
1126
1127 /* The buffer starts after PartialResourceList->PartialDescriptors[0] */
1128 Ptr = (char *)(PartialResourceList + 1);
1129
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);
1134
1135 /* Copy device nodes */
1136 FoundNodeCount = 0;
1137 for (i = 0; i < 0xFF; i++)
1138 {
1139 NodeNumber = (UCHAR)i;
1140
1141 x = PnpBiosGetDeviceNode(&NodeNumber, DiskReadBuffer);
1142 if (x == 0)
1143 {
1144 DeviceNode = (PCM_PNP_BIOS_DEVICE_NODE)DiskReadBuffer;
1145
1146 TRACE("Node: %u Size %u (0x%x)\n",
1147 DeviceNode->Node,
1148 DeviceNode->Size,
1149 DeviceNode->Size);
1150
1151 if (PnpBufferSize + DeviceNode->Size > PnpBufferSizeLimit)
1152 {
1153 ERR("Buffer too small! Ignoring remaining device nodes.\n");
1154 break;
1155 }
1156
1157 RtlCopyMemory(Ptr, DeviceNode, DeviceNode->Size);
1158
1159 Ptr += DeviceNode->Size;
1160 PnpBufferSize += DeviceNode->Size;
1161
1162 FoundNodeCount++;
1163 if (FoundNodeCount >= NodeCount)
1164 break;
1165 }
1166 }
1167
1168 /* Set real data size */
1169 PartialResourceList->PartialDescriptors[0].u.DeviceSpecificData.DataSize =
1170 PnpBufferSize;
1171 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) + PnpBufferSize;
1172
1173 TRACE("Real buffer size: %u\n", PnpBufferSize);
1174 TRACE("Resource size: %u\n", Size);
1175
1176 /* Create component key */
1177 FldrCreateComponentKey(SystemKey,
1178 AdapterClass,
1179 MultiFunctionAdapter,
1180 0x0,
1181 0x0,
1182 0xFFFFFFFF,
1183 "PNP BIOS",
1184 PartialResourceList,
1185 Size,
1186 &BusKey);
1187
1188 (*BusNumber)++;
1189 }
1190
1191 PCONFIGURATION_COMPONENT_DATA
1192 Pc98HwDetect(VOID)
1193 {
1194 PCONFIGURATION_COMPONENT_DATA SystemKey;
1195 ULONG BusNumber = 0;
1196
1197 TRACE("DetectHardware()\n");
1198
1199 /* Create the 'System' key */
1200 FldrCreateSystemKey(&SystemKey);
1201 FldrSetIdentifier(SystemKey, "NEC PC-98");
1202
1203 GetHarddiskConfigurationData = Pc98GetHarddiskConfigurationData;
1204 FindPciBios = PcFindPciBios;
1205
1206 /* Detect buses */
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
1214
1215 // TODO: Collect the ROM blocks and append their
1216 // CM_ROM_BLOCK data into the 'System' key's configuration data.
1217
1218 TRACE("DetectHardware() Done\n");
1219 return SystemKey;
1220 }
1221
1222 UCHAR
1223 Pc98GetFloppyCount(VOID)
1224 {
1225 USHORT DiskEquipment = *(PUSHORT)MEM_DISK_EQUIP & ~(*(PUCHAR)MEM_RDISK_EQUIP);
1226 UCHAR DiskMask;
1227 UCHAR FloppyCount = 0;
1228
1229 for (DiskMask = 0x01; DiskMask != 0; DiskMask <<= 1)
1230 {
1231 if (FIRSTBYTE(DiskEquipment) & DiskMask)
1232 ++FloppyCount;
1233 }
1234
1235 for (DiskMask = 0x10; DiskMask != 0; DiskMask <<= 1)
1236 {
1237 if (SECONDBYTE(DiskEquipment) & DiskMask)
1238 ++FloppyCount;
1239 }
1240
1241 return FloppyCount;
1242 }
1243
1244 VOID __cdecl DiskStopFloppyMotor(VOID)
1245 {
1246 WRITE_PORT_UCHAR((PUCHAR)(FDC1_IO_BASE + FDC_o_CONTROL), 0);
1247 WRITE_PORT_UCHAR((PUCHAR)(FDC2_IO_BASE + FDC_o_CONTROL), 0);
1248 }
1249
1250 // FIXME: 1) Copied from pchw.c 2) Should be done inside MachInit.
1251 VOID
1252 FrLdrCheckCpuCompatibility(VOID)
1253 {
1254 INT CpuInformation[4] = {-1};
1255 ULONG NumberOfIds;
1256
1257 /* Check if the processor first supports ID 1 */
1258 __cpuid(CpuInformation, 0);
1259
1260 NumberOfIds = CpuInformation[0];
1261
1262 if (NumberOfIds == 0)
1263 {
1264 FrLdrBugCheckWithMessage(MISSING_HARDWARE_REQUIREMENTS,
1265 __FILE__,
1266 __LINE__,
1267 "ReactOS requires the CPUID instruction to return "
1268 "more than one supported ID.\n\n");
1269 }
1270
1271 /* NumberOfIds will be greater than 1 if the processor is new enough */
1272 if (NumberOfIds == 1)
1273 {
1274 INT ProcessorFamily;
1275
1276 /* Get information */
1277 __cpuid(CpuInformation, 1);
1278
1279 ProcessorFamily = (CpuInformation[0] >> 8) & 0xF;
1280
1281 /* If it's Family 4 or lower, bugcheck */
1282 if (ProcessorFamily < 5)
1283 {
1284 FrLdrBugCheckWithMessage(MISSING_HARDWARE_REQUIREMENTS,
1285 __FILE__,
1286 __LINE__,
1287 "Processor is too old (family %u < 5)\n"
1288 "ReactOS requires a Pentium-level processor or newer.",
1289 ProcessorFamily);
1290 }
1291 }
1292 }