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