sync to trunk head (37853) (except rbuild changes)
[reactos.git] / reactos / boot / freeldr / freeldr / arch / i386 / hardware.c
1 /*
2 * FreeLoader
3 *
4 * Copyright (C) 2003, 2004 Eric Kohl
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include <freeldr.h>
22
23 #define NDEBUG
24 #include <debug.h>
25
26 #define MILLISEC (10)
27 #define PRECISION (8)
28
29 #define HZ (100)
30 #define CLOCK_TICK_RATE (1193182)
31 #define LATCH (CLOCK_TICK_RATE / HZ)
32
33
34 /* No Mouse */
35 #define MOUSE_TYPE_NONE 0
36 /* Microsoft Mouse with 2 buttons */
37 #define MOUSE_TYPE_MICROSOFT 1
38 /* Logitech Mouse with 3 buttons */
39 #define MOUSE_TYPE_LOGITECH 2
40 /* Microsoft Wheel Mouse (aka Z Mouse) */
41 #define MOUSE_TYPE_WHEELZ 3
42 /* Mouse Systems Mouse */
43 #define MOUSE_TYPE_MOUSESYSTEMS 4
44
45
46 /* PS2 stuff */
47
48 /* Controller registers. */
49 #define CONTROLLER_REGISTER_STATUS 0x64
50 #define CONTROLLER_REGISTER_CONTROL 0x64
51 #define CONTROLLER_REGISTER_DATA 0x60
52
53 /* Controller commands. */
54 #define CONTROLLER_COMMAND_READ_MODE 0x20
55 #define CONTROLLER_COMMAND_WRITE_MODE 0x60
56 #define CONTROLLER_COMMAND_GET_VERSION 0xA1
57 #define CONTROLLER_COMMAND_MOUSE_DISABLE 0xA7
58 #define CONTROLLER_COMMAND_MOUSE_ENABLE 0xA8
59 #define CONTROLLER_COMMAND_TEST_MOUSE 0xA9
60 #define CONTROLLER_COMMAND_SELF_TEST 0xAA
61 #define CONTROLLER_COMMAND_KEYBOARD_TEST 0xAB
62 #define CONTROLLER_COMMAND_KEYBOARD_DISABLE 0xAD
63 #define CONTROLLER_COMMAND_KEYBOARD_ENABLE 0xAE
64 #define CONTROLLER_COMMAND_WRITE_MOUSE_OUTPUT_BUFFER 0xD3
65 #define CONTROLLER_COMMAND_WRITE_MOUSE 0xD4
66
67 /* Controller status */
68 #define CONTROLLER_STATUS_OUTPUT_BUFFER_FULL 0x01
69 #define CONTROLLER_STATUS_INPUT_BUFFER_FULL 0x02
70 #define CONTROLLER_STATUS_SELF_TEST 0x04
71 #define CONTROLLER_STATUS_COMMAND 0x08
72 #define CONTROLLER_STATUS_UNLOCKED 0x10
73 #define CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL 0x20
74 #define CONTROLLER_STATUS_GENERAL_TIMEOUT 0x40
75 #define CONTROLLER_STATUS_PARITY_ERROR 0x80
76 #define AUX_STATUS_OUTPUT_BUFFER_FULL (CONTROLLER_STATUS_OUTPUT_BUFFER_FULL | \
77 CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL)
78
79 /* Timeout in ms for sending to keyboard controller. */
80 #define CONTROLLER_TIMEOUT 250
81
82 static CHAR Hex[] = "0123456789abcdef";
83 static unsigned int delay_count = 1;
84
85 extern ULONG reactos_disk_count;
86 extern ARC_DISK_SIGNATURE reactos_arc_disk_info[];
87 extern char reactos_arc_strings[32][256];
88
89 /* FUNCTIONS ****************************************************************/
90
91
92 static VOID
93 __StallExecutionProcessor(ULONG Loops)
94 {
95 register volatile unsigned int i;
96 for (i = 0; i < Loops; i++);
97 }
98
99
100 VOID StallExecutionProcessor(ULONG Microseconds)
101 {
102 ULONGLONG LoopCount = ((ULONGLONG)delay_count * (ULONGLONG)Microseconds) / 1000ULL;
103 __StallExecutionProcessor((ULONG)LoopCount);
104 }
105
106
107 static ULONG
108 Read8254Timer(VOID)
109 {
110 ULONG Count;
111
112 WRITE_PORT_UCHAR((PUCHAR)0x43, 0x00);
113 Count = READ_PORT_UCHAR((PUCHAR)0x40);
114 Count |= READ_PORT_UCHAR((PUCHAR)0x40) << 8;
115
116 return Count;
117 }
118
119
120 static VOID
121 WaitFor8254Wraparound(VOID)
122 {
123 ULONG CurCount;
124 ULONG PrevCount = ~0;
125 LONG Delta;
126
127 CurCount = Read8254Timer();
128
129 do
130 {
131 PrevCount = CurCount;
132 CurCount = Read8254Timer();
133 Delta = CurCount - PrevCount;
134
135 /*
136 * This limit for delta seems arbitrary, but it isn't, it's
137 * slightly above the level of error a buggy Mercury/Neptune
138 * chipset timer can cause.
139 */
140 }
141 while (Delta < 300);
142 }
143
144
145 VOID
146 HalpCalibrateStallExecution(VOID)
147 {
148 ULONG i;
149 ULONG calib_bit;
150 ULONG CurCount;
151
152 /* Initialise timer interrupt with MILLISECOND ms interval */
153 WRITE_PORT_UCHAR((PUCHAR)0x43, 0x34); /* binary, mode 2, LSB/MSB, ch 0 */
154 WRITE_PORT_UCHAR((PUCHAR)0x40, LATCH & 0xff); /* LSB */
155 WRITE_PORT_UCHAR((PUCHAR)0x40, LATCH >> 8); /* MSB */
156
157 /* Stage 1: Coarse calibration */
158
159 WaitFor8254Wraparound();
160
161 delay_count = 1;
162
163 do {
164 delay_count <<= 1; /* Next delay count to try */
165
166 WaitFor8254Wraparound();
167
168 __StallExecutionProcessor(delay_count); /* Do the delay */
169
170 CurCount = Read8254Timer();
171 } while (CurCount > LATCH / 2);
172
173 delay_count >>= 1; /* Get bottom value for delay */
174
175 /* Stage 2: Fine calibration */
176
177 calib_bit = delay_count; /* Which bit are we going to test */
178
179 for(i=0;i<PRECISION;i++) {
180 calib_bit >>= 1; /* Next bit to calibrate */
181 if(!calib_bit) break; /* If we have done all bits, stop */
182
183 delay_count |= calib_bit; /* Set the bit in delay_count */
184
185 WaitFor8254Wraparound();
186
187 __StallExecutionProcessor(delay_count); /* Do the delay */
188
189 CurCount = Read8254Timer();
190 if (CurCount <= LATCH / 2) /* If a tick has passed, turn the */
191 delay_count &= ~calib_bit; /* calibrated bit back off */
192 }
193
194 /* We're finished: Do the finishing touches */
195 delay_count /= (MILLISEC / 2); /* Calculate delay_count for 1ms */
196 }
197
198 static VOID
199 DetectPnpBios(PCONFIGURATION_COMPONENT_DATA SystemKey, ULONG *BusNumber)
200 {
201 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
202 PCM_PNP_BIOS_DEVICE_NODE DeviceNode;
203 PCM_PNP_BIOS_INSTALLATION_CHECK InstData;
204 PCONFIGURATION_COMPONENT_DATA BusKey;
205 ULONG x;
206 ULONG NodeSize = 0;
207 ULONG NodeCount = 0;
208 UCHAR NodeNumber;
209 ULONG FoundNodeCount;
210 int i;
211 ULONG PnpBufferSize;
212 ULONG Size;
213 char *Ptr;
214
215 InstData = (PCM_PNP_BIOS_INSTALLATION_CHECK)PnpBiosSupported();
216 if (InstData == NULL || strncmp((CHAR*)InstData->Signature, "$PnP", 4))
217 {
218 DbgPrint((DPRINT_HWDETECT, "PnP-BIOS not supported\n"));
219 return;
220 }
221 DbgPrint((DPRINT_HWDETECT, "Signature '%c%c%c%c'\n",
222 InstData->Signature[0], InstData->Signature[1],
223 InstData->Signature[2], InstData->Signature[3]));
224
225
226 x = PnpBiosGetDeviceNodeCount(&NodeSize, &NodeCount);
227 NodeCount &= 0xFF; // needed since some fscked up BIOSes return
228 // wrong info (e.g. Mac Virtual PC)
229 // e.g. look: http://my.execpc.com/~geezer/osd/pnp/pnp16.c
230 if (x != 0 || NodeSize == 0 || NodeCount == 0)
231 {
232 DbgPrint((DPRINT_HWDETECT, "PnP-BIOS failed to enumerate device nodes\n"));
233 return;
234 }
235 DbgPrint((DPRINT_HWDETECT, "PnP-BIOS supported\n"));
236 DbgPrint((DPRINT_HWDETECT, "MaxNodeSize %u NodeCount %u\n", NodeSize, NodeCount));
237 DbgPrint((DPRINT_HWDETECT, "Estimated buffer size %u\n", NodeSize * NodeCount));
238
239 /* Create component key */
240 FldrCreateComponentKey(SystemKey,
241 L"MultifunctionAdapter",
242 *BusNumber,
243 AdapterClass,
244 MultiFunctionAdapter,
245 &BusKey);
246 (*BusNumber)++;
247
248 /* Set the component information */
249 FldrSetComponentInformation(BusKey,
250 0x0,
251 0x0,
252 0xFFFFFFFF);
253
254 /* Set the identifier */
255 FldrSetIdentifier(BusKey, "PNP BIOS");
256
257 /* Set 'Configuration Data' value */
258 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) + (NodeSize * NodeCount);
259 PartialResourceList = MmHeapAlloc(Size);
260 if (PartialResourceList == NULL)
261 {
262 DbgPrint((DPRINT_HWDETECT,
263 "Failed to allocate resource descriptor\n"));
264 return;
265 }
266 memset(PartialResourceList, 0, Size);
267
268 /* Initialize resource descriptor */
269 PartialResourceList->Version = 1;
270 PartialResourceList->Revision = 1;
271 PartialResourceList->Count = 1;
272 PartialResourceList->PartialDescriptors[0].Type =
273 CmResourceTypeDeviceSpecific;
274 PartialResourceList->PartialDescriptors[0].ShareDisposition =
275 CmResourceShareUndetermined;
276
277 Ptr = (char *)(((ULONG_PTR)&PartialResourceList->PartialDescriptors[0]) +
278 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
279
280 /* Set instalation check data */
281 memcpy (Ptr, InstData, sizeof(CM_PNP_BIOS_INSTALLATION_CHECK));
282 Ptr += sizeof(CM_PNP_BIOS_INSTALLATION_CHECK);
283
284 /* Copy device nodes */
285 FoundNodeCount = 0;
286 PnpBufferSize = sizeof(CM_PNP_BIOS_INSTALLATION_CHECK);
287 for (i = 0; i < 0xFF; i++)
288 {
289 NodeNumber = (UCHAR)i;
290
291 x = PnpBiosGetDeviceNode(&NodeNumber, (PVOID)DISKREADBUFFER);
292 if (x == 0)
293 {
294 DeviceNode = (PCM_PNP_BIOS_DEVICE_NODE)DISKREADBUFFER;
295
296 DbgPrint((DPRINT_HWDETECT,
297 "Node: %u Size %u (0x%x)\n",
298 DeviceNode->Node,
299 DeviceNode->Size,
300 DeviceNode->Size));
301
302 memcpy (Ptr,
303 DeviceNode,
304 DeviceNode->Size);
305
306 Ptr += DeviceNode->Size;
307 PnpBufferSize += DeviceNode->Size;
308
309 FoundNodeCount++;
310 if (FoundNodeCount >= NodeCount)
311 break;
312 }
313 }
314
315 /* Set real data size */
316 PartialResourceList->PartialDescriptors[0].u.DeviceSpecificData.DataSize =
317 PnpBufferSize;
318 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) + PnpBufferSize;
319
320 DbgPrint((DPRINT_HWDETECT, "Real buffer size: %u\n", PnpBufferSize));
321 DbgPrint((DPRINT_HWDETECT, "Resource size: %u\n", Size));
322
323 FldrSetConfigurationData(BusKey, PartialResourceList, Size);
324 MmHeapFree(PartialResourceList);
325 }
326
327
328
329 static VOID
330 SetHarddiskConfigurationData(PCONFIGURATION_COMPONENT_DATA DiskKey,
331 ULONG DriveNumber)
332 {
333 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
334 PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry;
335 EXTENDED_GEOMETRY ExtGeometry;
336 GEOMETRY Geometry;
337 ULONG Size;
338
339 /* Set 'Configuration Data' value */
340 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) +
341 sizeof(CM_DISK_GEOMETRY_DEVICE_DATA);
342 PartialResourceList = MmHeapAlloc(Size);
343 if (PartialResourceList == NULL)
344 {
345 DbgPrint((DPRINT_HWDETECT,
346 "Failed to allocate a full resource descriptor\n"));
347 return;
348 }
349
350 memset(PartialResourceList, 0, Size);
351 PartialResourceList->Version = 1;
352 PartialResourceList->Revision = 1;
353 PartialResourceList->Count = 1;
354 PartialResourceList->PartialDescriptors[0].Type =
355 CmResourceTypeDeviceSpecific;
356 // PartialResourceList->PartialDescriptors[0].ShareDisposition =
357 // PartialResourceList->PartialDescriptors[0].Flags =
358 PartialResourceList->PartialDescriptors[0].u.DeviceSpecificData.DataSize =
359 sizeof(CM_DISK_GEOMETRY_DEVICE_DATA);
360
361 /* Get pointer to geometry data */
362 DiskGeometry = (PVOID)(((ULONG_PTR)PartialResourceList) + sizeof(CM_PARTIAL_RESOURCE_LIST));
363
364 /* Get the disk geometry */
365 ExtGeometry.Size = sizeof(EXTENDED_GEOMETRY);
366 if (DiskGetExtendedDriveParameters(DriveNumber, &ExtGeometry, ExtGeometry.Size))
367 {
368 DiskGeometry->BytesPerSector = ExtGeometry.BytesPerSector;
369 DiskGeometry->NumberOfCylinders = ExtGeometry.Cylinders;
370 DiskGeometry->SectorsPerTrack = ExtGeometry.SectorsPerTrack;
371 DiskGeometry->NumberOfHeads = ExtGeometry.Heads;
372 }
373 else if(MachDiskGetDriveGeometry(DriveNumber, &Geometry))
374 {
375 DiskGeometry->BytesPerSector = Geometry.BytesPerSector;
376 DiskGeometry->NumberOfCylinders = Geometry.Cylinders;
377 DiskGeometry->SectorsPerTrack = Geometry.Sectors;
378 DiskGeometry->NumberOfHeads = Geometry.Heads;
379 }
380 else
381 {
382 DbgPrint((DPRINT_HWDETECT, "Reading disk geometry failed\n"));
383 MmHeapFree(PartialResourceList);
384 return;
385 }
386 DbgPrint((DPRINT_HWDETECT,
387 "Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n",
388 DriveNumber,
389 DiskGeometry->NumberOfCylinders,
390 DiskGeometry->NumberOfHeads,
391 DiskGeometry->SectorsPerTrack,
392 DiskGeometry->BytesPerSector));
393
394 FldrSetConfigurationData(DiskKey, PartialResourceList, Size);
395 MmHeapFree(PartialResourceList);
396 }
397
398
399 static VOID
400 SetHarddiskIdentifier(PCONFIGURATION_COMPONENT_DATA DiskKey,
401 ULONG DriveNumber)
402 {
403 PMASTER_BOOT_RECORD Mbr;
404 ULONG *Buffer;
405 ULONG i;
406 ULONG Checksum;
407 ULONG Signature;
408 CHAR Identifier[20];
409 CHAR ArcName[256];
410
411 /* Read the MBR */
412 if (!MachDiskReadLogicalSectors(DriveNumber, 0ULL, 1, (PVOID)DISKREADBUFFER))
413 {
414 DbgPrint((DPRINT_HWDETECT, "Reading MBR failed\n"));
415 return;
416 }
417
418 Buffer = (ULONG*)DISKREADBUFFER;
419 Mbr = (PMASTER_BOOT_RECORD)DISKREADBUFFER;
420
421 Signature = Mbr->Signature;
422 DbgPrint((DPRINT_HWDETECT, "Signature: %x\n", Signature));
423
424 /* Calculate the MBR checksum */
425 Checksum = 0;
426 for (i = 0; i < 128; i++)
427 {
428 Checksum += Buffer[i];
429 }
430 Checksum = ~Checksum + 1;
431 DbgPrint((DPRINT_HWDETECT, "Checksum: %x\n", Checksum));
432
433 /* Fill out the ARC disk block */
434 reactos_arc_disk_info[reactos_disk_count].Signature = Signature;
435 reactos_arc_disk_info[reactos_disk_count].CheckSum = Checksum;
436 sprintf(ArcName, "multi(0)disk(0)rdisk(%lu)", reactos_disk_count);
437 strcpy(reactos_arc_strings[reactos_disk_count], ArcName);
438 reactos_arc_disk_info[reactos_disk_count].ArcName =
439 reactos_arc_strings[reactos_disk_count];
440 reactos_disk_count++;
441
442 /* Convert checksum and signature to identifier string */
443 Identifier[0] = Hex[(Checksum >> 28) & 0x0F];
444 Identifier[1] = Hex[(Checksum >> 24) & 0x0F];
445 Identifier[2] = Hex[(Checksum >> 20) & 0x0F];
446 Identifier[3] = Hex[(Checksum >> 16) & 0x0F];
447 Identifier[4] = Hex[(Checksum >> 12) & 0x0F];
448 Identifier[5] = Hex[(Checksum >> 8) & 0x0F];
449 Identifier[6] = Hex[(Checksum >> 4) & 0x0F];
450 Identifier[7] = Hex[Checksum & 0x0F];
451 Identifier[8] = '-';
452 Identifier[9] = Hex[(Signature >> 28) & 0x0F];
453 Identifier[10] = Hex[(Signature >> 24) & 0x0F];
454 Identifier[11] = Hex[(Signature >> 20) & 0x0F];
455 Identifier[12] = Hex[(Signature >> 16) & 0x0F];
456 Identifier[13] = Hex[(Signature >> 12) & 0x0F];
457 Identifier[14] = Hex[(Signature >> 8) & 0x0F];
458 Identifier[15] = Hex[(Signature >> 4) & 0x0F];
459 Identifier[16] = Hex[Signature & 0x0F];
460 Identifier[17] = '-';
461 Identifier[18] = 'A';
462 Identifier[19] = 0;
463 DbgPrint((DPRINT_HWDETECT, "Identifier: %s\n", Identifier));
464
465 /* Set identifier */
466 FldrSetIdentifier(DiskKey, Identifier);
467 }
468
469 static ULONG
470 GetFloppyCount(VOID)
471 {
472 UCHAR Data;
473
474 WRITE_PORT_UCHAR((PUCHAR)0x70, 0x10);
475 Data = READ_PORT_UCHAR((PUCHAR)0x71);
476
477 return ((Data & 0xF0) ? 1 : 0) + ((Data & 0x0F) ? 1 : 0);
478 }
479
480
481 static UCHAR
482 GetFloppyType(UCHAR DriveNumber)
483 {
484 UCHAR Data;
485
486 WRITE_PORT_UCHAR((PUCHAR)0x70, 0x10);
487 Data = READ_PORT_UCHAR((PUCHAR)0x71);
488
489 if (DriveNumber == 0)
490 return Data >> 4;
491 else if (DriveNumber == 1)
492 return Data & 0x0F;
493
494 return 0;
495 }
496
497
498 static PVOID
499 GetInt1eTable(VOID)
500 {
501 PUSHORT SegPtr = (PUSHORT)0x7A;
502 PUSHORT OfsPtr = (PUSHORT)0x78;
503
504 return (PVOID)((ULONG_PTR)(((ULONG)(*SegPtr)) << 4) + (ULONG)(*OfsPtr));
505 }
506
507
508 static VOID
509 DetectBiosFloppyPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey)
510 {
511 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
512 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
513 PCM_FLOPPY_DEVICE_DATA FloppyData;
514 CHAR Identifier[20];
515 PCONFIGURATION_COMPONENT_DATA PeripheralKey;
516 ULONG Size;
517 ULONG FloppyNumber;
518 UCHAR FloppyType;
519 ULONG MaxDensity[6] = {0, 360, 1200, 720, 1440, 2880};
520 PUCHAR Ptr;
521
522 for (FloppyNumber = 0; FloppyNumber < 2; FloppyNumber++)
523 {
524 FloppyType = GetFloppyType(FloppyNumber);
525
526 if ((FloppyType > 5) || (FloppyType == 0))
527 continue;
528
529 DiskResetController(FloppyNumber);
530
531 Ptr = GetInt1eTable();
532
533 FldrCreateComponentKey(ControllerKey,
534 L"FloppyDiskPeripheral",
535 FloppyNumber,
536 PeripheralClass,
537 FloppyDiskPeripheral,
538 &PeripheralKey);
539
540 /* Set 'ComponentInformation' value */
541 FldrSetComponentInformation(PeripheralKey,
542 Input | Output,
543 FloppyNumber,
544 0xFFFFFFFF);
545
546 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) +
547 sizeof(CM_FLOPPY_DEVICE_DATA);
548 PartialResourceList = MmHeapAlloc(Size);
549 if (PartialResourceList == NULL)
550 {
551 DbgPrint((DPRINT_HWDETECT,
552 "Failed to allocate resource descriptor\n"));
553 return;
554 }
555
556 memset(PartialResourceList, 0, Size);
557 PartialResourceList->Version = 1;
558 PartialResourceList->Revision = 1;
559 PartialResourceList->Count = 1;
560
561 PartialDescriptor = &PartialResourceList->PartialDescriptors[0];
562 PartialDescriptor->Type = CmResourceTypeDeviceSpecific;
563 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
564 PartialDescriptor->u.DeviceSpecificData.DataSize = sizeof(CM_FLOPPY_DEVICE_DATA);
565
566 FloppyData = (PVOID)(((ULONG_PTR)PartialResourceList) + sizeof(CM_PARTIAL_RESOURCE_LIST));
567 FloppyData->Version = 2;
568 FloppyData->Revision = 0;
569 FloppyData->MaxDensity = MaxDensity[FloppyType];
570 FloppyData->MountDensity = 0;
571 RtlCopyMemory(&FloppyData->StepRateHeadUnloadTime,
572 Ptr,
573 11);
574 FloppyData->MaximumTrackValue = (FloppyType == 1) ? 39 : 79;
575 FloppyData->DataTransferRate = 0;
576
577 /* Set 'Configuration Data' value */
578 FldrSetConfigurationData(PeripheralKey, PartialResourceList, Size);
579 MmHeapFree(PartialResourceList);
580
581 /* Set 'Identifier' value */
582 sprintf(Identifier, "FLOPPY%ld", FloppyNumber + 1);
583 FldrSetIdentifier(PeripheralKey, Identifier);
584 }
585 }
586
587
588 static VOID
589 DetectBiosFloppyController(PCONFIGURATION_COMPONENT_DATA BusKey,
590 PCONFIGURATION_COMPONENT_DATA ControllerKey)
591 {
592 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
593 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
594 ULONG Size;
595 ULONG FloppyCount;
596
597 FloppyCount = GetFloppyCount();
598 DbgPrint((DPRINT_HWDETECT,
599 "Floppy count: %u\n",
600 FloppyCount));
601
602 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) +
603 2 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
604 PartialResourceList = MmHeapAlloc(Size);
605 if (PartialResourceList == NULL)
606 {
607 DbgPrint((DPRINT_HWDETECT,
608 "Failed to allocate resource descriptor\n"));
609 return;
610 }
611 memset(PartialResourceList, 0, Size);
612
613 /* Initialize resource descriptor */
614 PartialResourceList->Version = 1;
615 PartialResourceList->Revision = 1;
616 PartialResourceList->Count = 3;
617
618 /* Set IO Port */
619 PartialDescriptor = &PartialResourceList->PartialDescriptors[0];
620 PartialDescriptor->Type = CmResourceTypePort;
621 PartialDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
622 PartialDescriptor->Flags = CM_RESOURCE_PORT_IO;
623 PartialDescriptor->u.Port.Start.LowPart = 0x03F0;
624 PartialDescriptor->u.Port.Start.HighPart = 0x0;
625 PartialDescriptor->u.Port.Length = 8;
626
627 /* Set Interrupt */
628 PartialDescriptor = &PartialResourceList->PartialDescriptors[1];
629 PartialDescriptor->Type = CmResourceTypeInterrupt;
630 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
631 PartialDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
632 PartialDescriptor->u.Interrupt.Level = 6;
633 PartialDescriptor->u.Interrupt.Vector = 6;
634 PartialDescriptor->u.Interrupt.Affinity = 0xFFFFFFFF;
635
636 /* Set DMA channel */
637 PartialDescriptor = &PartialResourceList->PartialDescriptors[2];
638 PartialDescriptor->Type = CmResourceTypeDma;
639 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
640 PartialDescriptor->Flags = 0;
641 PartialDescriptor->u.Dma.Channel = 2;
642 PartialDescriptor->u.Dma.Port = 0;
643
644 /* Set 'Configuration Data' value */
645 FldrSetConfigurationData(ControllerKey, PartialResourceList, Size);
646 MmHeapFree(PartialResourceList);
647
648 if (FloppyCount) DetectBiosFloppyPeripheral(ControllerKey);
649 }
650
651 static VOID
652 DetectBiosDisks(PCONFIGURATION_COMPONENT_DATA SystemKey,
653 PCONFIGURATION_COMPONENT_DATA BusKey)
654 {
655 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
656 PCM_INT13_DRIVE_PARAMETER Int13Drives;
657 GEOMETRY Geometry;
658 PCONFIGURATION_COMPONENT_DATA DiskKey, ControllerKey;
659 ULONG DiskCount;
660 ULONG Size;
661 ULONG i;
662 BOOLEAN Changed;
663
664 /* Count the number of visible drives */
665 DiskReportError(FALSE);
666 DiskCount = 0;
667
668 /* There are some really broken BIOSes out there. There are even BIOSes
669 * that happily report success when you ask them to read from non-existent
670 * harddisks. So, we set the buffer to known contents first, then try to
671 * read. If the BIOS reports success but the buffer contents haven't
672 * changed then we fail anyway */
673 memset((PVOID) DISKREADBUFFER, 0xcd, 512);
674 while (MachDiskReadLogicalSectors(0x80 + DiskCount, 0ULL, 1, (PVOID)DISKREADBUFFER))
675 {
676 Changed = FALSE;
677 for (i = 0; ! Changed && i < 512; i++)
678 {
679 Changed = ((PUCHAR)DISKREADBUFFER)[i] != 0xcd;
680 }
681 if (! Changed)
682 {
683 DbgPrint((DPRINT_HWDETECT, "BIOS reports success for disk %d but data didn't change\n",
684 (int)DiskCount));
685 break;
686 }
687 DiskCount++;
688 memset((PVOID) DISKREADBUFFER, 0xcd, 512);
689 }
690 DiskReportError(TRUE);
691 DbgPrint((DPRINT_HWDETECT, "BIOS reports %d harddisk%s\n",
692 (int)DiskCount, (DiskCount == 1) ? "": "s"));
693
694 FldrCreateComponentKey(BusKey,
695 L"DiskController",
696 0,
697 ControllerClass,
698 DiskController,
699 &ControllerKey);
700 DbgPrint((DPRINT_HWDETECT, "Created key: DiskController\\0\n"));
701
702 /* Set 'ComponentInformation' value */
703 FldrSetComponentInformation(ControllerKey,
704 Output | Input | Removable,
705 0,
706 0xFFFFFFFF);
707
708 DetectBiosFloppyController(BusKey, ControllerKey);
709
710 /* Allocate resource descriptor */
711 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) +
712 sizeof(CM_INT13_DRIVE_PARAMETER) * DiskCount;
713 PartialResourceList = MmHeapAlloc(Size);
714 if (PartialResourceList == NULL)
715 {
716 DbgPrint((DPRINT_HWDETECT,
717 "Failed to allocate resource descriptor\n"));
718 return;
719 }
720
721 /* Initialize resource descriptor */
722 memset(PartialResourceList, 0, Size);
723 PartialResourceList->Version = 1;
724 PartialResourceList->Revision = 1;
725 PartialResourceList->Count = 1;
726 PartialResourceList->PartialDescriptors[0].Type = CmResourceTypeDeviceSpecific;
727 PartialResourceList->PartialDescriptors[0].ShareDisposition = 0;
728 PartialResourceList->PartialDescriptors[0].Flags = 0;
729 PartialResourceList->PartialDescriptors[0].u.DeviceSpecificData.DataSize =
730 sizeof(CM_INT13_DRIVE_PARAMETER) * DiskCount;
731
732 /* Get harddisk Int13 geometry data */
733 Int13Drives = (PVOID)(((ULONG_PTR)PartialResourceList) + sizeof(CM_PARTIAL_RESOURCE_LIST));
734 for (i = 0; i < DiskCount; i++)
735 {
736 if (MachDiskGetDriveGeometry(0x80 + i, &Geometry))
737 {
738 Int13Drives[i].DriveSelect = 0x80 + i;
739 Int13Drives[i].MaxCylinders = Geometry.Cylinders - 1;
740 Int13Drives[i].SectorsPerTrack = Geometry.Sectors;
741 Int13Drives[i].MaxHeads = Geometry.Heads - 1;
742 Int13Drives[i].NumberDrives = DiskCount;
743
744 DbgPrint((DPRINT_HWDETECT,
745 "Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n",
746 0x80 + i,
747 Geometry.Cylinders - 1,
748 Geometry.Heads -1,
749 Geometry.Sectors,
750 Geometry.BytesPerSector));
751 }
752 }
753
754 /* Set 'Configuration Data' value */
755 FldrSetConfigurationData(SystemKey, PartialResourceList, Size);
756 MmHeapFree(PartialResourceList);
757
758 /* Create and fill subkey for each harddisk */
759 for (i = 0; i < DiskCount; i++)
760 {
761 /* Create disk key */
762 FldrCreateComponentKey(ControllerKey,
763 L"DiskPeripheral",
764 i,
765 PeripheralClass,
766 DiskPeripheral,
767 &DiskKey);
768
769 /* Set 'ComponentInformation' value */
770 FldrSetComponentInformation(DiskKey,
771 Output | Input,
772 0,
773 0xFFFFFFFF);
774
775 /* Set disk values */
776 SetHarddiskConfigurationData(DiskKey, 0x80 + i);
777 SetHarddiskIdentifier(DiskKey, 0x80 + i);
778 }
779 }
780
781 static VOID
782 InitializeSerialPort(PUCHAR Port,
783 ULONG LineControl)
784 {
785 WRITE_PORT_UCHAR(Port + 3, 0x80); /* set DLAB on */
786 WRITE_PORT_UCHAR(Port, 0x60); /* speed LO byte */
787 WRITE_PORT_UCHAR(Port + 1, 0); /* speed HI byte */
788 WRITE_PORT_UCHAR(Port + 3, LineControl);
789 WRITE_PORT_UCHAR(Port + 1, 0); /* set comm and DLAB to 0 */
790 WRITE_PORT_UCHAR(Port + 4, 0x09); /* DR int enable */
791 READ_PORT_UCHAR(Port + 5); /* clear error bits */
792 }
793
794
795 static ULONG
796 DetectSerialMouse(PUCHAR Port)
797 {
798 CHAR Buffer[4];
799 ULONG i;
800 ULONG TimeOut;
801 UCHAR LineControl;
802
803 /* Shutdown mouse or something like that */
804 LineControl = READ_PORT_UCHAR(Port + 4);
805 WRITE_PORT_UCHAR(Port + 4, (LineControl & ~0x02) | 0x01);
806 StallExecutionProcessor(100000);
807
808 /*
809 * Clear buffer
810 * Maybe there is no serial port although BIOS reported one (this
811 * is the case on Apple hardware), or the serial port is misbehaving,
812 * therefore we must give up after some time.
813 */
814 TimeOut = 200;
815 while (READ_PORT_UCHAR(Port + 5) & 0x01)
816 {
817 if (--TimeOut == 0)
818 return MOUSE_TYPE_NONE;
819 READ_PORT_UCHAR(Port);
820 }
821
822 /*
823 * Send modem control with 'Data Terminal Ready', 'Request To Send' and
824 * 'Output Line 2' message. This enables mouse to identify.
825 */
826 WRITE_PORT_UCHAR(Port + 4, 0x0b);
827
828 /* Wait 10 milliseconds for the mouse getting ready */
829 StallExecutionProcessor(10000);
830
831 /* Read first four bytes, which contains Microsoft Mouse signs */
832 TimeOut = 200;
833 for (i = 0; i < 4; i++)
834 {
835 while (((READ_PORT_UCHAR(Port + 5) & 1) == 0) && (TimeOut > 0))
836 {
837 StallExecutionProcessor(1000);
838 --TimeOut;
839 if (TimeOut == 0)
840 return MOUSE_TYPE_NONE;
841 }
842 Buffer[i] = READ_PORT_UCHAR(Port);
843 }
844
845 DbgPrint((DPRINT_HWDETECT,
846 "Mouse data: %x %x %x %x\n",
847 Buffer[0],Buffer[1],Buffer[2],Buffer[3]));
848
849 /* Check that four bytes for signs */
850 for (i = 0; i < 4; ++i)
851 {
852 if (Buffer[i] == 'B')
853 {
854 /* Sign for Microsoft Ballpoint */
855 // DbgPrint("Microsoft Ballpoint device detected\n");
856 // DbgPrint("THIS DEVICE IS NOT SUPPORTED, YET\n");
857 return MOUSE_TYPE_NONE;
858 }
859 else if (Buffer[i] == 'M')
860 {
861 /* Sign for Microsoft Mouse protocol followed by button specifier */
862 if (i == 3)
863 {
864 /* Overflow Error */
865 return MOUSE_TYPE_NONE;
866 }
867
868 switch (Buffer[i + 1])
869 {
870 case '3':
871 DbgPrint((DPRINT_HWDETECT,
872 "Microsoft Mouse with 3-buttons detected\n"));
873 return MOUSE_TYPE_LOGITECH;
874
875 case 'Z':
876 DbgPrint((DPRINT_HWDETECT,
877 "Microsoft Wheel Mouse detected\n"));
878 return MOUSE_TYPE_WHEELZ;
879
880 /* case '2': */
881 default:
882 DbgPrint((DPRINT_HWDETECT,
883 "Microsoft Mouse with 2-buttons detected\n"));
884 return MOUSE_TYPE_MICROSOFT;
885 }
886 }
887 }
888
889 return MOUSE_TYPE_NONE;
890 }
891
892
893 static ULONG
894 GetSerialMousePnpId(PUCHAR Port, char *Buffer)
895 {
896 ULONG TimeOut;
897 ULONG i = 0;
898 char c;
899 char x;
900
901 WRITE_PORT_UCHAR(Port + 4, 0x09);
902
903 /* Wait 10 milliseconds for the mouse getting ready */
904 StallExecutionProcessor(10000);
905
906 WRITE_PORT_UCHAR(Port + 4, 0x0b);
907
908 StallExecutionProcessor(10000);
909
910 for (;;)
911 {
912 TimeOut = 200;
913 while (((READ_PORT_UCHAR(Port + 5) & 1) == 0) && (TimeOut > 0))
914 {
915 StallExecutionProcessor(1000);
916 --TimeOut;
917 if (TimeOut == 0)
918 {
919 return 0;
920 }
921 }
922
923 c = READ_PORT_UCHAR(Port);
924 if (c == 0x08 || c == 0x28)
925 break;
926 }
927
928 Buffer[i++] = c;
929 x = c + 1;
930
931 for (;;)
932 {
933 TimeOut = 200;
934 while (((READ_PORT_UCHAR(Port + 5) & 1) == 0) && (TimeOut > 0))
935 {
936 StallExecutionProcessor(1000);
937 --TimeOut;
938 if (TimeOut == 0)
939 return 0;
940 }
941 c = READ_PORT_UCHAR(Port);
942 Buffer[i++] = c;
943 if (c == x)
944 break;
945 if (i >= 256)
946 break;
947 }
948
949 return i;
950 }
951
952
953 static VOID
954 DetectSerialPointerPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey,
955 PUCHAR Base)
956 {
957 CM_PARTIAL_RESOURCE_LIST PartialResourceList;
958 char Buffer[256];
959 CHAR Identifier[256];
960 PCONFIGURATION_COMPONENT_DATA PeripheralKey;
961 ULONG MouseType;
962 ULONG Length;
963 ULONG i;
964 ULONG j;
965 ULONG k;
966
967 DbgPrint((DPRINT_HWDETECT,
968 "DetectSerialPointerPeripheral()\n"));
969
970 Identifier[0] = 0;
971
972 InitializeSerialPort(Base, 2);
973 MouseType = DetectSerialMouse(Base);
974
975 if (MouseType != MOUSE_TYPE_NONE)
976 {
977 Length = GetSerialMousePnpId(Base, Buffer);
978 DbgPrint((DPRINT_HWDETECT,
979 "PnP ID length: %u\n",
980 Length));
981
982 if (Length != 0)
983 {
984 /* Convert PnP sting to ASCII */
985 if (Buffer[0] == 0x08)
986 {
987 for (i = 0; i < Length; i++)
988 Buffer[i] += 0x20;
989 }
990 Buffer[Length] = 0;
991
992 DbgPrint((DPRINT_HWDETECT,
993 "PnP ID string: %s\n",
994 Buffer));
995
996 /* Copy PnpId string */
997 for (i = 0; i < 7; i++)
998 {
999 Identifier[i] = Buffer[3+i];
1000 }
1001 memcpy(&Identifier[7],
1002 L" - ",
1003 3 * sizeof(WCHAR));
1004
1005 /* Skip device serial number */
1006 i = 10;
1007 if (Buffer[i] == '\\')
1008 {
1009 for (j = ++i; i < Length; ++i)
1010 {
1011 if (Buffer[i] == '\\')
1012 break;
1013 }
1014 if (i >= Length)
1015 i -= 3;
1016 }
1017
1018 /* Skip PnP class */
1019 if (Buffer[i] == '\\')
1020 {
1021 for (j = ++i; i < Length; ++i)
1022 {
1023 if (Buffer[i] == '\\')
1024 break;
1025 }
1026
1027 if (i >= Length)
1028 i -= 3;
1029 }
1030
1031 /* Skip compatible PnP Id */
1032 if (Buffer[i] == '\\')
1033 {
1034 for (j = ++i; i < Length; ++i)
1035 {
1036 if (Buffer[i] == '\\')
1037 break;
1038 }
1039 if (Buffer[j] == '*')
1040 ++j;
1041 if (i >= Length)
1042 i -= 3;
1043 }
1044
1045 /* Get product description */
1046 if (Buffer[i] == '\\')
1047 {
1048 for (j = ++i; i < Length; ++i)
1049 {
1050 if (Buffer[i] == ';')
1051 break;
1052 }
1053 if (i >= Length)
1054 i -= 3;
1055 if (i > j + 1)
1056 {
1057 for (k = 0; k < i - j; k++)
1058 {
1059 Identifier[k + 10] = Buffer[k + j];
1060 }
1061 Identifier[10 + (i-j)] = 0;
1062 }
1063 }
1064
1065 DbgPrint((DPRINT_HWDETECT,
1066 "Identifier string: %s\n",
1067 Identifier));
1068 }
1069
1070 if (Length == 0 || strlen(Identifier) < 11)
1071 {
1072 switch (MouseType)
1073 {
1074 case MOUSE_TYPE_LOGITECH:
1075 strcpy (Identifier,
1076 "LOGITECH SERIAL MOUSE");
1077 break;
1078
1079 case MOUSE_TYPE_WHEELZ:
1080 strcpy (Identifier,
1081 "MICROSOFT SERIAL MOUSE WITH WHEEL");
1082 break;
1083
1084 case MOUSE_TYPE_MICROSOFT:
1085 default:
1086 strcpy (Identifier,
1087 "MICROSOFT SERIAL MOUSE");
1088 break;
1089 }
1090 }
1091
1092 /* Create 'PointerPeripheral' key */
1093 FldrCreateComponentKey(ControllerKey,
1094 L"PointerPeripheral",
1095 0,
1096 PeripheralClass,
1097 PointerPeripheral,
1098 &PeripheralKey);
1099 DbgPrint((DPRINT_HWDETECT,
1100 "Created key: PointerPeripheral\\0\n"));
1101
1102 /* Set 'ComponentInformation' value */
1103 FldrSetComponentInformation(PeripheralKey,
1104 Input,
1105 0,
1106 0xFFFFFFFF);
1107
1108 /* Set 'Configuration Data' value */
1109 memset(&PartialResourceList, 0, sizeof(CM_PARTIAL_RESOURCE_LIST));
1110 PartialResourceList.Version = 1;
1111 PartialResourceList.Revision = 1;
1112 PartialResourceList.Count = 0;
1113
1114 FldrSetConfigurationData(PeripheralKey,
1115 &PartialResourceList,
1116 sizeof(CM_PARTIAL_RESOURCE_LIST) -
1117 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
1118
1119 /* Set 'Identifier' value */
1120 FldrSetIdentifier(PeripheralKey, Identifier);
1121 }
1122 }
1123
1124
1125 static VOID
1126 DetectSerialPorts(PCONFIGURATION_COMPONENT_DATA BusKey)
1127 {
1128 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
1129 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
1130 PCM_SERIAL_DEVICE_DATA SerialDeviceData;
1131 ULONG Irq[4] = {4, 3, 4, 3};
1132 ULONG Base;
1133 CHAR Buffer[80];
1134 PUSHORT BasePtr;
1135 ULONG ControllerNumber = 0;
1136 PCONFIGURATION_COMPONENT_DATA ControllerKey;
1137 ULONG i;
1138 ULONG Size;
1139
1140 DbgPrint((DPRINT_HWDETECT, "DetectSerialPorts()\n"));
1141
1142 ControllerNumber = 0;
1143 BasePtr = (PUSHORT)0x400;
1144 for (i = 0; i < 4; i++, BasePtr++)
1145 {
1146 Base = (ULONG)*BasePtr;
1147 if (Base == 0)
1148 continue;
1149
1150 DbgPrint((DPRINT_HWDETECT,
1151 "Found COM%u port at 0x%x\n",
1152 i + 1,
1153 Base));
1154
1155 /* Create controller key */
1156 FldrCreateComponentKey(BusKey,
1157 L"SerialController",
1158 ControllerNumber,
1159 ControllerClass,
1160 SerialController,
1161 &ControllerKey);
1162
1163 /* Set 'ComponentInformation' value */
1164 FldrSetComponentInformation(ControllerKey,
1165 Output | Input | ConsoleIn | ConsoleOut,
1166 ControllerNumber,
1167 0xFFFFFFFF);
1168
1169 /* Build full device descriptor */
1170 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) +
1171 2 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) +
1172 sizeof(CM_SERIAL_DEVICE_DATA);
1173 PartialResourceList = MmHeapAlloc(Size);
1174 if (PartialResourceList == NULL)
1175 {
1176 DbgPrint((DPRINT_HWDETECT,
1177 "Failed to allocate resource descriptor\n"));
1178 continue;
1179 }
1180 memset(PartialResourceList, 0, Size);
1181
1182 /* Initialize resource descriptor */
1183 PartialResourceList->Version = 1;
1184 PartialResourceList->Revision = 1;
1185 PartialResourceList->Count = 3;
1186
1187 /* Set IO Port */
1188 PartialDescriptor = &PartialResourceList->PartialDescriptors[0];
1189 PartialDescriptor->Type = CmResourceTypePort;
1190 PartialDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1191 PartialDescriptor->Flags = CM_RESOURCE_PORT_IO;
1192 PartialDescriptor->u.Port.Start.LowPart = Base;
1193 PartialDescriptor->u.Port.Start.HighPart = 0x0;
1194 PartialDescriptor->u.Port.Length = 7;
1195
1196 /* Set Interrupt */
1197 PartialDescriptor = &PartialResourceList->PartialDescriptors[1];
1198 PartialDescriptor->Type = CmResourceTypeInterrupt;
1199 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
1200 PartialDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
1201 PartialDescriptor->u.Interrupt.Level = Irq[i];
1202 PartialDescriptor->u.Interrupt.Vector = 0;
1203 PartialDescriptor->u.Interrupt.Affinity = 0xFFFFFFFF;
1204
1205 /* Set serial data (device specific) */
1206 PartialDescriptor = &PartialResourceList->PartialDescriptors[2];
1207 PartialDescriptor->Type = CmResourceTypeDeviceSpecific;
1208 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
1209 PartialDescriptor->Flags = 0;
1210 PartialDescriptor->u.DeviceSpecificData.DataSize = sizeof(CM_SERIAL_DEVICE_DATA);
1211
1212 SerialDeviceData =
1213 (PCM_SERIAL_DEVICE_DATA)&PartialResourceList->PartialDescriptors[3];
1214 SerialDeviceData->BaudClock = 1843200; /* UART Clock frequency (Hertz) */
1215
1216 /* Set 'Configuration Data' value */
1217 FldrSetConfigurationData(ControllerKey, PartialResourceList, Size);
1218 MmHeapFree(PartialResourceList);
1219
1220 /* Set 'Identifier' value */
1221 sprintf(Buffer, "COM%ld", i + 1);
1222 FldrSetIdentifier(ControllerKey, Buffer);
1223 DbgPrint((DPRINT_HWDETECT,
1224 "Created value: Identifier %s\n",
1225 Buffer));
1226
1227 if (!Rs232PortInUse(Base))
1228 {
1229 /* Detect serial mouse */
1230 DetectSerialPointerPeripheral(ControllerKey, UlongToPtr(Base));
1231 }
1232
1233 ControllerNumber++;
1234 }
1235 }
1236
1237
1238 static VOID
1239 DetectParallelPorts(PCONFIGURATION_COMPONENT_DATA BusKey)
1240 {
1241 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
1242 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
1243 ULONG Irq[3] = {7, 5, (ULONG)-1};
1244 CHAR Buffer[80];
1245 PCONFIGURATION_COMPONENT_DATA ControllerKey;
1246 PUSHORT BasePtr;
1247 ULONG Base;
1248 ULONG ControllerNumber;
1249 ULONG i;
1250 ULONG Size;
1251
1252 DbgPrint((DPRINT_HWDETECT, "DetectParallelPorts() called\n"));
1253
1254 ControllerNumber = 0;
1255 BasePtr = (PUSHORT)0x408;
1256 for (i = 0; i < 3; i++, BasePtr++)
1257 {
1258 Base = (ULONG)*BasePtr;
1259 if (Base == 0)
1260 continue;
1261
1262 DbgPrint((DPRINT_HWDETECT,
1263 "Parallel port %u: %x\n",
1264 ControllerNumber,
1265 Base));
1266
1267 /* Create controller key */
1268 FldrCreateComponentKey(BusKey,
1269 L"ParallelController",
1270 ControllerNumber,
1271 ControllerClass,
1272 ParallelController,
1273 &ControllerKey);
1274
1275 /* Set 'ComponentInformation' value */
1276 FldrSetComponentInformation(ControllerKey,
1277 Output,
1278 ControllerNumber,
1279 0xFFFFFFFF);
1280
1281 /* Build full device descriptor */
1282 Size = sizeof(CM_PARTIAL_RESOURCE_LIST);
1283 if (Irq[i] != (ULONG)-1)
1284 Size += sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
1285
1286 PartialResourceList = MmHeapAlloc(Size);
1287 if (PartialResourceList == NULL)
1288 {
1289 DbgPrint((DPRINT_HWDETECT,
1290 "Failed to allocate resource descriptor\n"));
1291 continue;
1292 }
1293 memset(PartialResourceList, 0, Size);
1294
1295 /* Initialize resource descriptor */
1296 PartialResourceList->Version = 1;
1297 PartialResourceList->Revision = 1;
1298 PartialResourceList->Count = (Irq[i] != (ULONG)-1) ? 2 : 1;
1299
1300 /* Set IO Port */
1301 PartialDescriptor = &PartialResourceList->PartialDescriptors[0];
1302 PartialDescriptor->Type = CmResourceTypePort;
1303 PartialDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1304 PartialDescriptor->Flags = CM_RESOURCE_PORT_IO;
1305 PartialDescriptor->u.Port.Start.LowPart = Base;
1306 PartialDescriptor->u.Port.Start.HighPart = 0x0;
1307 PartialDescriptor->u.Port.Length = 3;
1308
1309 /* Set Interrupt */
1310 if (Irq[i] != (ULONG)-1)
1311 {
1312 PartialDescriptor = &PartialResourceList->PartialDescriptors[1];
1313 PartialDescriptor->Type = CmResourceTypeInterrupt;
1314 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
1315 PartialDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
1316 PartialDescriptor->u.Interrupt.Level = Irq[i];
1317 PartialDescriptor->u.Interrupt.Vector = 0;
1318 PartialDescriptor->u.Interrupt.Affinity = 0xFFFFFFFF;
1319 }
1320
1321 /* Set 'Configuration Data' value */
1322 FldrSetConfigurationData(ControllerKey, PartialResourceList, Size);
1323 MmHeapFree(PartialResourceList);
1324
1325 /* Set 'Identifier' value */
1326 sprintf(Buffer, "PARALLEL%ld", i + 1);
1327 FldrSetIdentifier(ControllerKey, Buffer);
1328 DbgPrint((DPRINT_HWDETECT,
1329 "Created value: Identifier %s\n",
1330 Buffer));
1331
1332 ControllerNumber++;
1333 }
1334
1335 DbgPrint((DPRINT_HWDETECT, "DetectParallelPorts() done\n"));
1336 }
1337
1338
1339 static BOOLEAN
1340 DetectKeyboardDevice(VOID)
1341 {
1342 UCHAR Status;
1343 UCHAR Scancode;
1344 ULONG Loops;
1345 BOOLEAN Result = TRUE;
1346
1347 /* Identify device */
1348 WRITE_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA,
1349 0xF2);
1350
1351 /* Wait for reply */
1352 for (Loops = 0; Loops < 100; Loops++)
1353 {
1354 StallExecutionProcessor(10000);
1355 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
1356 if ((Status & CONTROLLER_STATUS_OUTPUT_BUFFER_FULL) != 0)
1357 break;
1358 }
1359
1360 if ((Status & CONTROLLER_STATUS_OUTPUT_BUFFER_FULL) == 0)
1361 {
1362 /* PC/XT keyboard or no keyboard */
1363 Result = FALSE;
1364 }
1365
1366 Scancode = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA);
1367 if (Scancode != 0xFA)
1368 {
1369 /* No ACK received */
1370 Result = FALSE;
1371 }
1372
1373 StallExecutionProcessor(10000);
1374
1375 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
1376 if ((Status & CONTROLLER_STATUS_OUTPUT_BUFFER_FULL) == 0)
1377 {
1378 /* Found AT keyboard */
1379 return Result;
1380 }
1381
1382 Scancode = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA);
1383 if (Scancode != 0xAB)
1384 {
1385 /* No 0xAB received */
1386 Result = FALSE;
1387 }
1388
1389 StallExecutionProcessor(10000);
1390
1391 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
1392 if ((Status & CONTROLLER_STATUS_OUTPUT_BUFFER_FULL) == 0)
1393 {
1394 /* No byte in buffer */
1395 Result = FALSE;
1396 }
1397
1398 Scancode = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA);
1399 if (Scancode != 0x41)
1400 {
1401 /* No 0x41 received */
1402 Result = FALSE;
1403 }
1404
1405 /* Found MF-II keyboard */
1406 return Result;
1407 }
1408
1409
1410 static VOID
1411 DetectKeyboardPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey)
1412 {
1413 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
1414 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
1415 PCM_KEYBOARD_DEVICE_DATA KeyboardData;
1416 PCONFIGURATION_COMPONENT_DATA PeripheralKey;
1417 ULONG Size;
1418
1419 /* HACK: don't call DetectKeyboardDevice() as it fails in Qemu 0.8.2 */
1420 if (TRUE || DetectKeyboardDevice())
1421 {
1422 /* Create controller key */
1423 FldrCreateComponentKey(ControllerKey,
1424 L"KeyboardPeripheral",
1425 0,
1426 PeripheralClass,
1427 KeyboardPeripheral,
1428 &PeripheralKey);
1429 DbgPrint((DPRINT_HWDETECT, "Created key: KeyboardPeripheral\\0\n"));
1430
1431 /* Set 'ComponentInformation' value */
1432 FldrSetComponentInformation(PeripheralKey,
1433 Input | ConsoleIn,
1434 0,
1435 0xFFFFFFFF);
1436
1437 /* Set 'Configuration Data' value */
1438 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) +
1439 sizeof(CM_KEYBOARD_DEVICE_DATA);
1440 PartialResourceList = MmHeapAlloc(Size);
1441 if (PartialResourceList == NULL)
1442 {
1443 DbgPrint((DPRINT_HWDETECT,
1444 "Failed to allocate resource descriptor\n"));
1445 return;
1446 }
1447
1448 /* Initialize resource descriptor */
1449 memset(PartialResourceList, 0, Size);
1450 PartialResourceList->Version = 1;
1451 PartialResourceList->Revision = 1;
1452 PartialResourceList->Count = 1;
1453
1454 PartialDescriptor = &PartialResourceList->PartialDescriptors[0];
1455 PartialDescriptor->Type = CmResourceTypeDeviceSpecific;
1456 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
1457 PartialDescriptor->u.DeviceSpecificData.DataSize = sizeof(CM_KEYBOARD_DEVICE_DATA);
1458
1459 KeyboardData = (PCM_KEYBOARD_DEVICE_DATA)(PartialDescriptor + 1);
1460 KeyboardData->Version = 1;
1461 KeyboardData->Revision = 1;
1462 KeyboardData->Type = 4;
1463 KeyboardData->Subtype = 0;
1464 KeyboardData->KeyboardFlags = 0x20;
1465
1466 /* Set 'Configuration Data' value */
1467 FldrSetConfigurationData(PeripheralKey, PartialResourceList, Size);
1468 MmHeapFree(PartialResourceList);
1469
1470 /* Set 'Identifier' value */
1471 FldrSetIdentifier(PeripheralKey, "PCAT_ENHANCED");
1472 }
1473 }
1474
1475
1476 static VOID
1477 DetectKeyboardController(PCONFIGURATION_COMPONENT_DATA BusKey)
1478 {
1479 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
1480 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
1481 PCONFIGURATION_COMPONENT_DATA ControllerKey;
1482 ULONG Size;
1483
1484 /* Create controller key */
1485 FldrCreateComponentKey(BusKey,
1486 L"KeyboardController",
1487 0,
1488 ControllerClass,
1489 KeyboardController,
1490 &ControllerKey);
1491 DbgPrint((DPRINT_HWDETECT, "Created key: KeyboardController\\0\n"));
1492
1493 /* Set 'ComponentInformation' value */
1494 FldrSetComponentInformation(ControllerKey,
1495 Input | ConsoleIn,
1496 0,
1497 0xFFFFFFFF);
1498
1499 /* Set 'Configuration Data' value */
1500 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) +
1501 2 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
1502 PartialResourceList = MmHeapAlloc(Size);
1503 if (PartialResourceList == NULL)
1504 {
1505 DbgPrint((DPRINT_HWDETECT,
1506 "Failed to allocate resource descriptor\n"));
1507 return;
1508 }
1509
1510 /* Initialize resource descriptor */
1511 memset(PartialResourceList, 0, Size);
1512 PartialResourceList->Version = 1;
1513 PartialResourceList->Revision = 1;
1514 PartialResourceList->Count = 3;
1515
1516 /* Set Interrupt */
1517 PartialDescriptor = &PartialResourceList->PartialDescriptors[0];
1518 PartialDescriptor->Type = CmResourceTypeInterrupt;
1519 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
1520 PartialDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
1521 PartialDescriptor->u.Interrupt.Level = 1;
1522 PartialDescriptor->u.Interrupt.Vector = 0;
1523 PartialDescriptor->u.Interrupt.Affinity = 0xFFFFFFFF;
1524
1525 /* Set IO Port 0x60 */
1526 PartialDescriptor = &PartialResourceList->PartialDescriptors[1];
1527 PartialDescriptor->Type = CmResourceTypePort;
1528 PartialDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1529 PartialDescriptor->Flags = CM_RESOURCE_PORT_IO;
1530 PartialDescriptor->u.Port.Start.LowPart = 0x60;
1531 PartialDescriptor->u.Port.Start.HighPart = 0x0;
1532 PartialDescriptor->u.Port.Length = 1;
1533
1534 /* Set IO Port 0x64 */
1535 PartialDescriptor = &PartialResourceList->PartialDescriptors[2];
1536 PartialDescriptor->Type = CmResourceTypePort;
1537 PartialDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1538 PartialDescriptor->Flags = CM_RESOURCE_PORT_IO;
1539 PartialDescriptor->u.Port.Start.LowPart = 0x64;
1540 PartialDescriptor->u.Port.Start.HighPart = 0x0;
1541 PartialDescriptor->u.Port.Length = 1;
1542
1543 /* Set 'Configuration Data' value */
1544 FldrSetConfigurationData(ControllerKey, PartialResourceList, Size);
1545 MmHeapFree(PartialResourceList);
1546
1547 DetectKeyboardPeripheral(ControllerKey);
1548 }
1549
1550
1551 static VOID
1552 PS2ControllerWait(VOID)
1553 {
1554 ULONG Timeout;
1555 UCHAR Status;
1556
1557 for (Timeout = 0; Timeout < CONTROLLER_TIMEOUT; Timeout++)
1558 {
1559 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
1560 if ((Status & CONTROLLER_STATUS_INPUT_BUFFER_FULL) == 0)
1561 return;
1562
1563 /* Sleep for one millisecond */
1564 StallExecutionProcessor(1000);
1565 }
1566 }
1567
1568
1569 static BOOLEAN
1570 DetectPS2AuxPort(VOID)
1571 {
1572 #if 1
1573 /* Current detection is too unreliable. Just do as if
1574 * the PS/2 aux port is always present
1575 */
1576 return TRUE;
1577 #else
1578 ULONG Loops;
1579 UCHAR Status;
1580
1581 /* Put the value 0x5A in the output buffer using the
1582 * "WriteAuxiliary Device Output Buffer" command (0xD3).
1583 * Poll the Status Register for a while to see if the value really turns up
1584 * in the Data Register. If the KEYBOARD_STATUS_MOUSE_OBF bit is also set
1585 * to 1 in the Status Register, we assume this controller has an
1586 * Auxiliary Port (a.k.a. Mouse Port).
1587 */
1588 PS2ControllerWait();
1589 WRITE_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_CONTROL,
1590 CONTROLLER_COMMAND_WRITE_MOUSE_OUTPUT_BUFFER);
1591 PS2ControllerWait();
1592
1593 /* 0x5A is a random dummy value */
1594 WRITE_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA,
1595 0x5A);
1596
1597 for (Loops = 0; Loops < 10; Loops++)
1598 {
1599 StallExecutionProcessor(10000);
1600 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
1601 if ((Status & CONTROLLER_STATUS_OUTPUT_BUFFER_FULL) != 0)
1602 break;
1603 }
1604
1605 READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA);
1606
1607 return (Status & CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL);
1608 #endif
1609 }
1610
1611
1612 static BOOLEAN
1613 DetectPS2AuxDevice(VOID)
1614 {
1615 UCHAR Scancode;
1616 UCHAR Status;
1617 ULONG Loops;
1618 BOOLEAN Result = TRUE;
1619
1620 PS2ControllerWait();
1621 WRITE_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_CONTROL,
1622 CONTROLLER_COMMAND_WRITE_MOUSE);
1623 PS2ControllerWait();
1624
1625 /* Identify device */
1626 WRITE_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA,
1627 0xF2);
1628
1629 /* Wait for reply */
1630 for (Loops = 0; Loops < 100; Loops++)
1631 {
1632 StallExecutionProcessor(10000);
1633 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
1634 if ((Status & CONTROLLER_STATUS_OUTPUT_BUFFER_FULL) != 0)
1635 break;
1636 }
1637
1638 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
1639 if ((Status & CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL) == 0)
1640 Result = FALSE;
1641
1642 Scancode = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA);
1643 if (Scancode != 0xFA)
1644 Result = FALSE;
1645
1646 StallExecutionProcessor(10000);
1647
1648 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
1649 if ((Status & CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL) == 0)
1650 Result = FALSE;
1651
1652 Scancode = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA);
1653 if (Scancode != 0x00)
1654 Result = FALSE;
1655
1656 return Result;
1657 }
1658
1659
1660 static VOID
1661 DetectPS2Mouse(PCONFIGURATION_COMPONENT_DATA BusKey)
1662 {
1663 CM_PARTIAL_RESOURCE_LIST PartialResourceList;
1664 PCONFIGURATION_COMPONENT_DATA ControllerKey;
1665 PCONFIGURATION_COMPONENT_DATA PeripheralKey;
1666
1667 if (DetectPS2AuxPort())
1668 {
1669 DbgPrint((DPRINT_HWDETECT, "Detected PS2 port\n"));
1670
1671 /* Create controller key */
1672 FldrCreateComponentKey(BusKey,
1673 L"PointerController",
1674 0,
1675 ControllerClass,
1676 PointerController,
1677 &ControllerKey);
1678 DbgPrint((DPRINT_HWDETECT, "Created key: PointerController\\0\n"));
1679
1680 /* Set 'ComponentInformation' value */
1681 FldrSetComponentInformation(ControllerKey,
1682 Input,
1683 0,
1684 0xFFFFFFFF);
1685
1686 memset(&PartialResourceList, 0, sizeof(CM_PARTIAL_RESOURCE_LIST));
1687
1688 /* Initialize resource descriptor */
1689 PartialResourceList.Version = 1;
1690 PartialResourceList.Revision = 1;
1691 PartialResourceList.Count = 1;
1692
1693 /* Set Interrupt */
1694 PartialResourceList.PartialDescriptors[0].Type = CmResourceTypeInterrupt;
1695 PartialResourceList.PartialDescriptors[0].ShareDisposition = CmResourceShareUndetermined;
1696 PartialResourceList.PartialDescriptors[0].Flags = CM_RESOURCE_INTERRUPT_LATCHED;
1697 PartialResourceList.PartialDescriptors[0].u.Interrupt.Level = 12;
1698 PartialResourceList.PartialDescriptors[0].u.Interrupt.Vector = 0;
1699 PartialResourceList.PartialDescriptors[0].u.Interrupt.Affinity = 0xFFFFFFFF;
1700
1701 /* Set 'Configuration Data' value */
1702 FldrSetConfigurationData(ControllerKey,
1703 &PartialResourceList,
1704 sizeof(CM_PARTIAL_RESOURCE_LIST));
1705
1706 if (DetectPS2AuxDevice())
1707 {
1708 DbgPrint((DPRINT_HWDETECT, "Detected PS2 mouse\n"));
1709
1710 /* Create peripheral key */
1711 FldrCreateComponentKey(ControllerKey,
1712 L"PointerPeripheral",
1713 0,
1714 ControllerClass,
1715 PointerPeripheral,
1716 &PeripheralKey);
1717 DbgPrint((DPRINT_HWDETECT, "Created key: PointerPeripheral\\0\n"));
1718
1719 /* Set 'ComponentInformation' value */
1720 FldrSetComponentInformation(PeripheralKey,
1721 Input,
1722 0,
1723 0xFFFFFFFF);
1724
1725 /* Initialize resource descriptor */
1726 memset(&PartialResourceList, 0, sizeof(CM_PARTIAL_RESOURCE_LIST));
1727 PartialResourceList.Version = 1;
1728 PartialResourceList.Revision = 1;
1729 PartialResourceList.Count = 0;
1730
1731 /* Set 'Configuration Data' value */
1732 FldrSetConfigurationData(PeripheralKey,
1733 &PartialResourceList,
1734 sizeof(CM_PARTIAL_RESOURCE_LIST) -
1735 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
1736
1737 /* Set 'Identifier' value */
1738 FldrSetIdentifier(PeripheralKey, "MICROSOFT PS2 MOUSE");
1739 }
1740 }
1741 }
1742
1743
1744 static VOID
1745 DetectDisplayController(PCONFIGURATION_COMPONENT_DATA BusKey)
1746 {
1747 CHAR Buffer[80];
1748 PCONFIGURATION_COMPONENT_DATA ControllerKey;
1749 USHORT VesaVersion;
1750
1751 FldrCreateComponentKey(BusKey,
1752 L"DisplayController",
1753 0,
1754 ControllerClass,
1755 DisplayController,
1756 &ControllerKey);
1757 DbgPrint((DPRINT_HWDETECT, "Created key: DisplayController\\0\n"));
1758
1759 /* Set 'ComponentInformation' value */
1760 FldrSetComponentInformation(ControllerKey,
1761 0x00,
1762 0,
1763 0xFFFFFFFF);
1764
1765 /* FIXME: Set 'ComponentInformation' value */
1766
1767 VesaVersion = BiosIsVesaSupported();
1768 if (VesaVersion != 0)
1769 {
1770 DbgPrint((DPRINT_HWDETECT,
1771 "VESA version %c.%c\n",
1772 (VesaVersion >> 8) + '0',
1773 (VesaVersion & 0xFF) + '0'));
1774 }
1775 else
1776 {
1777 DbgPrint((DPRINT_HWDETECT,
1778 "VESA not supported\n"));
1779 }
1780
1781 if (VesaVersion >= 0x0200)
1782 {
1783 strcpy(Buffer,
1784 "VBE Display");
1785 }
1786 else
1787 {
1788 strcpy(Buffer,
1789 "VGA Display");
1790 }
1791
1792 /* Set 'Identifier' value */
1793 FldrSetIdentifier(ControllerKey, Buffer);
1794
1795 /* FIXME: Add display peripheral (monitor) data */
1796 }
1797
1798
1799 static VOID
1800 DetectIsaBios(PCONFIGURATION_COMPONENT_DATA SystemKey, ULONG *BusNumber)
1801 {
1802 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
1803 PCONFIGURATION_COMPONENT_DATA BusKey;
1804 ULONG Size;
1805
1806 /* Create new bus key */
1807 FldrCreateComponentKey(SystemKey,
1808 L"MultifunctionAdapter",
1809 *BusNumber,
1810 AdapterClass,
1811 MultiFunctionAdapter,
1812 &BusKey);
1813
1814 /* Set 'Component Information' value similar to my NT4 box */
1815 FldrSetComponentInformation(BusKey,
1816 0x0,
1817 0x0,
1818 0xFFFFFFFF);
1819
1820 /* Increment bus number */
1821 (*BusNumber)++;
1822
1823 /* Set 'Identifier' value */
1824 FldrSetIdentifier(BusKey, "ISA");
1825
1826 /* Set 'Configuration Data' value */
1827 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) -
1828 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
1829 PartialResourceList = MmHeapAlloc(Size);
1830 if (PartialResourceList == NULL)
1831 {
1832 DbgPrint((DPRINT_HWDETECT,
1833 "Failed to allocate resource descriptor\n"));
1834 return;
1835 }
1836
1837 /* Initialize resource descriptor */
1838 memset(PartialResourceList, 0, Size);
1839 PartialResourceList->Version = 1;
1840 PartialResourceList->Revision = 1;
1841 PartialResourceList->Count = 0;
1842
1843 /* Set 'Configuration Data' value */
1844 FldrSetConfigurationData(BusKey, PartialResourceList, Size);
1845 MmHeapFree(PartialResourceList);
1846
1847 /* Detect ISA/BIOS devices */
1848 DetectBiosDisks(SystemKey, BusKey);
1849
1850 DetectSerialPorts(BusKey);
1851
1852 DetectParallelPorts(BusKey);
1853
1854 DetectKeyboardController(BusKey);
1855
1856 DetectPS2Mouse(BusKey);
1857
1858 DetectDisplayController(BusKey);
1859
1860 /* FIXME: Detect more ISA devices */
1861 }
1862
1863
1864 PCONFIGURATION_COMPONENT_DATA
1865 PcHwDetect(VOID)
1866 {
1867 PCONFIGURATION_COMPONENT_DATA SystemKey;
1868 ULONG BusNumber = 0;
1869
1870 DbgPrint((DPRINT_HWDETECT, "DetectHardware()\n"));
1871
1872 /* Create the 'System' key */
1873 FldrCreateSystemKey(&SystemKey);
1874
1875 /* Set empty component information */
1876 FldrSetComponentInformation(SystemKey,
1877 0x0,
1878 0x0,
1879 0xFFFFFFFF);
1880
1881 /* Detect buses */
1882 DetectPciBios(SystemKey, &BusNumber);
1883 DetectApmBios(SystemKey, &BusNumber);
1884 DetectPnpBios(SystemKey, &BusNumber);
1885 DetectIsaBios(SystemKey, &BusNumber);
1886 DetectAcpiBios(SystemKey, &BusNumber);
1887
1888 DbgPrint((DPRINT_HWDETECT, "DetectHardware() Done\n"));
1889
1890 return SystemKey;
1891 }
1892
1893 /* EOF */