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