Sync trunk head (r41026)
[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 /* Add partitions */
540 i = 0;
541 DiskReportError(FALSE);
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 DiskReportError(TRUE);
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, BootDriveReported = FALSE;
774 CHAR BootPath[512];
775
776 /* Count the number of visible drives */
777 DiskReportError(FALSE);
778 DiskCount = 0;
779
780 /* There are some really broken BIOSes out there. There are even BIOSes
781 * that happily report success when you ask them to read from non-existent
782 * harddisks. So, we set the buffer to known contents first, then try to
783 * read. If the BIOS reports success but the buffer contents haven't
784 * changed then we fail anyway */
785 memset((PVOID) DISKREADBUFFER, 0xcd, 512);
786 while (MachDiskReadLogicalSectors(0x80 + DiskCount, 0ULL, 1, (PVOID)DISKREADBUFFER))
787 {
788 Changed = FALSE;
789 for (i = 0; ! Changed && i < 512; i++)
790 {
791 Changed = ((PUCHAR)DISKREADBUFFER)[i] != 0xcd;
792 }
793 if (! Changed)
794 {
795 DPRINTM(DPRINT_HWDETECT, "BIOS reports success for disk %d but data didn't change\n",
796 (int)DiskCount);
797 break;
798 }
799 DiskCount++;
800 memset((PVOID) DISKREADBUFFER, 0xcd, 512);
801 }
802 DiskReportError(TRUE);
803 DPRINTM(DPRINT_HWDETECT, "BIOS reports %d harddisk%s\n",
804 (int)DiskCount, (DiskCount == 1) ? "": "s");
805
806 FldrCreateComponentKey(BusKey,
807 L"DiskController",
808 0,
809 ControllerClass,
810 DiskController,
811 &ControllerKey);
812 DPRINTM(DPRINT_HWDETECT, "Created key: DiskController\\0\n");
813
814 /* Set 'ComponentInformation' value */
815 FldrSetComponentInformation(ControllerKey,
816 Output | Input | Removable,
817 0,
818 0xFFFFFFFF);
819
820 DetectBiosFloppyController(BusKey, ControllerKey);
821
822 /* Allocate resource descriptor */
823 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) +
824 sizeof(CM_INT13_DRIVE_PARAMETER) * DiskCount;
825 PartialResourceList = MmHeapAlloc(Size);
826 if (PartialResourceList == NULL)
827 {
828 DPRINTM(DPRINT_HWDETECT,
829 "Failed to allocate resource descriptor\n");
830 return;
831 }
832
833 /* Initialize resource descriptor */
834 memset(PartialResourceList, 0, Size);
835 PartialResourceList->Version = 1;
836 PartialResourceList->Revision = 1;
837 PartialResourceList->Count = 1;
838 PartialResourceList->PartialDescriptors[0].Type = CmResourceTypeDeviceSpecific;
839 PartialResourceList->PartialDescriptors[0].ShareDisposition = 0;
840 PartialResourceList->PartialDescriptors[0].Flags = 0;
841 PartialResourceList->PartialDescriptors[0].u.DeviceSpecificData.DataSize =
842 sizeof(CM_INT13_DRIVE_PARAMETER) * DiskCount;
843
844 /* Get harddisk Int13 geometry data */
845 Int13Drives = (PVOID)(((ULONG_PTR)PartialResourceList) + sizeof(CM_PARTIAL_RESOURCE_LIST));
846 for (i = 0; i < DiskCount; i++)
847 {
848 if (BootDrive == 0x80 + i)
849 BootDriveReported = TRUE;
850
851 if (MachDiskGetDriveGeometry(0x80 + i, &Geometry))
852 {
853 Int13Drives[i].DriveSelect = 0x80 + i;
854 Int13Drives[i].MaxCylinders = Geometry.Cylinders - 1;
855 Int13Drives[i].SectorsPerTrack = Geometry.Sectors;
856 Int13Drives[i].MaxHeads = Geometry.Heads - 1;
857 Int13Drives[i].NumberDrives = DiskCount;
858
859 DPRINTM(DPRINT_HWDETECT,
860 "Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n",
861 0x80 + i,
862 Geometry.Cylinders - 1,
863 Geometry.Heads -1,
864 Geometry.Sectors,
865 Geometry.BytesPerSector);
866 }
867 }
868
869 /* Set 'Configuration Data' value */
870 FldrSetConfigurationData(SystemKey, PartialResourceList, Size);
871 MmHeapFree(PartialResourceList);
872
873 /* Create and fill subkey for each harddisk */
874 for (i = 0; i < DiskCount; i++)
875 {
876 /* Create disk key */
877 FldrCreateComponentKey(ControllerKey,
878 L"DiskPeripheral",
879 i,
880 PeripheralClass,
881 DiskPeripheral,
882 &DiskKey);
883
884 /* Set 'ComponentInformation' value */
885 FldrSetComponentInformation(DiskKey,
886 Output | Input,
887 0,
888 0xFFFFFFFF);
889
890 /* Set disk values */
891 SetHarddiskConfigurationData(DiskKey, 0x80 + i);
892 SetHarddiskIdentifier(DiskKey, 0x80 + i);
893 }
894
895 /* Get the drive we're booting from */
896 MachDiskGetBootPath(BootPath, sizeof(BootPath));
897
898 /* Add it, if it's a floppy or cdrom */
899 if ((BootDrive >= 0x80 && !BootDriveReported) ||
900 DiskIsDriveRemovable(BootDrive))
901 {
902 /* TODO: Check if it's really a cdrom drive */
903 FsRegisterDevice(BootPath, &DiskVtbl);
904 }
905 }
906
907 static VOID
908 InitializeSerialPort(PUCHAR Port,
909 ULONG LineControl)
910 {
911 WRITE_PORT_UCHAR(Port + 3, 0x80); /* set DLAB on */
912 WRITE_PORT_UCHAR(Port, 0x60); /* speed LO byte */
913 WRITE_PORT_UCHAR(Port + 1, 0); /* speed HI byte */
914 WRITE_PORT_UCHAR(Port + 3, LineControl);
915 WRITE_PORT_UCHAR(Port + 1, 0); /* set comm and DLAB to 0 */
916 WRITE_PORT_UCHAR(Port + 4, 0x09); /* DR int enable */
917 READ_PORT_UCHAR(Port + 5); /* clear error bits */
918 }
919
920
921 static ULONG
922 DetectSerialMouse(PUCHAR Port)
923 {
924 CHAR Buffer[4];
925 ULONG i;
926 ULONG TimeOut;
927 UCHAR LineControl;
928
929 /* Shutdown mouse or something like that */
930 LineControl = READ_PORT_UCHAR(Port + 4);
931 WRITE_PORT_UCHAR(Port + 4, (LineControl & ~0x02) | 0x01);
932 StallExecutionProcessor(100000);
933
934 /*
935 * Clear buffer
936 * Maybe there is no serial port although BIOS reported one (this
937 * is the case on Apple hardware), or the serial port is misbehaving,
938 * therefore we must give up after some time.
939 */
940 TimeOut = 200;
941 while (READ_PORT_UCHAR(Port + 5) & 0x01)
942 {
943 if (--TimeOut == 0)
944 return MOUSE_TYPE_NONE;
945 READ_PORT_UCHAR(Port);
946 }
947
948 /*
949 * Send modem control with 'Data Terminal Ready', 'Request To Send' and
950 * 'Output Line 2' message. This enables mouse to identify.
951 */
952 WRITE_PORT_UCHAR(Port + 4, 0x0b);
953
954 /* Wait 10 milliseconds for the mouse getting ready */
955 StallExecutionProcessor(10000);
956
957 /* Read first four bytes, which contains Microsoft Mouse signs */
958 TimeOut = 200;
959 for (i = 0; i < 4; i++)
960 {
961 while (((READ_PORT_UCHAR(Port + 5) & 1) == 0) && (TimeOut > 0))
962 {
963 StallExecutionProcessor(1000);
964 --TimeOut;
965 if (TimeOut == 0)
966 return MOUSE_TYPE_NONE;
967 }
968 Buffer[i] = READ_PORT_UCHAR(Port);
969 }
970
971 DPRINTM(DPRINT_HWDETECT,
972 "Mouse data: %x %x %x %x\n",
973 Buffer[0],Buffer[1],Buffer[2],Buffer[3]);
974
975 /* Check that four bytes for signs */
976 for (i = 0; i < 4; ++i)
977 {
978 if (Buffer[i] == 'B')
979 {
980 /* Sign for Microsoft Ballpoint */
981 // DbgPrint("Microsoft Ballpoint device detected\n");
982 // DbgPrint("THIS DEVICE IS NOT SUPPORTED, YET\n");
983 return MOUSE_TYPE_NONE;
984 }
985 else if (Buffer[i] == 'M')
986 {
987 /* Sign for Microsoft Mouse protocol followed by button specifier */
988 if (i == 3)
989 {
990 /* Overflow Error */
991 return MOUSE_TYPE_NONE;
992 }
993
994 switch (Buffer[i + 1])
995 {
996 case '3':
997 DPRINTM(DPRINT_HWDETECT,
998 "Microsoft Mouse with 3-buttons detected\n");
999 return MOUSE_TYPE_LOGITECH;
1000
1001 case 'Z':
1002 DPRINTM(DPRINT_HWDETECT,
1003 "Microsoft Wheel Mouse detected\n");
1004 return MOUSE_TYPE_WHEELZ;
1005
1006 /* case '2': */
1007 default:
1008 DPRINTM(DPRINT_HWDETECT,
1009 "Microsoft Mouse with 2-buttons detected\n");
1010 return MOUSE_TYPE_MICROSOFT;
1011 }
1012 }
1013 }
1014
1015 return MOUSE_TYPE_NONE;
1016 }
1017
1018
1019 static ULONG
1020 GetSerialMousePnpId(PUCHAR Port, char *Buffer)
1021 {
1022 ULONG TimeOut;
1023 ULONG i = 0;
1024 char c;
1025 char x;
1026
1027 WRITE_PORT_UCHAR(Port + 4, 0x09);
1028
1029 /* Wait 10 milliseconds for the mouse getting ready */
1030 StallExecutionProcessor(10000);
1031
1032 WRITE_PORT_UCHAR(Port + 4, 0x0b);
1033
1034 StallExecutionProcessor(10000);
1035
1036 for (;;)
1037 {
1038 TimeOut = 200;
1039 while (((READ_PORT_UCHAR(Port + 5) & 1) == 0) && (TimeOut > 0))
1040 {
1041 StallExecutionProcessor(1000);
1042 --TimeOut;
1043 if (TimeOut == 0)
1044 {
1045 return 0;
1046 }
1047 }
1048
1049 c = READ_PORT_UCHAR(Port);
1050 if (c == 0x08 || c == 0x28)
1051 break;
1052 }
1053
1054 Buffer[i++] = c;
1055 x = c + 1;
1056
1057 for (;;)
1058 {
1059 TimeOut = 200;
1060 while (((READ_PORT_UCHAR(Port + 5) & 1) == 0) && (TimeOut > 0))
1061 {
1062 StallExecutionProcessor(1000);
1063 --TimeOut;
1064 if (TimeOut == 0)
1065 return 0;
1066 }
1067 c = READ_PORT_UCHAR(Port);
1068 Buffer[i++] = c;
1069 if (c == x)
1070 break;
1071 if (i >= 256)
1072 break;
1073 }
1074
1075 return i;
1076 }
1077
1078
1079 static VOID
1080 DetectSerialPointerPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey,
1081 PUCHAR Base)
1082 {
1083 CM_PARTIAL_RESOURCE_LIST PartialResourceList;
1084 char Buffer[256];
1085 CHAR Identifier[256];
1086 PCONFIGURATION_COMPONENT_DATA PeripheralKey;
1087 ULONG MouseType;
1088 ULONG Length;
1089 ULONG i;
1090 ULONG j;
1091 ULONG k;
1092
1093 DPRINTM(DPRINT_HWDETECT,
1094 "DetectSerialPointerPeripheral()\n");
1095
1096 Identifier[0] = 0;
1097
1098 InitializeSerialPort(Base, 2);
1099 MouseType = DetectSerialMouse(Base);
1100
1101 if (MouseType != MOUSE_TYPE_NONE)
1102 {
1103 Length = GetSerialMousePnpId(Base, Buffer);
1104 DPRINTM(DPRINT_HWDETECT,
1105 "PnP ID length: %u\n",
1106 Length);
1107
1108 if (Length != 0)
1109 {
1110 /* Convert PnP sting to ASCII */
1111 if (Buffer[0] == 0x08)
1112 {
1113 for (i = 0; i < Length; i++)
1114 Buffer[i] += 0x20;
1115 }
1116 Buffer[Length] = 0;
1117
1118 DPRINTM(DPRINT_HWDETECT,
1119 "PnP ID string: %s\n",
1120 Buffer);
1121
1122 /* Copy PnpId string */
1123 for (i = 0; i < 7; i++)
1124 {
1125 Identifier[i] = Buffer[3+i];
1126 }
1127 memcpy(&Identifier[7],
1128 L" - ",
1129 3 * sizeof(WCHAR));
1130
1131 /* Skip device serial number */
1132 i = 10;
1133 if (Buffer[i] == '\\')
1134 {
1135 for (j = ++i; i < Length; ++i)
1136 {
1137 if (Buffer[i] == '\\')
1138 break;
1139 }
1140 if (i >= Length)
1141 i -= 3;
1142 }
1143
1144 /* Skip PnP class */
1145 if (Buffer[i] == '\\')
1146 {
1147 for (j = ++i; i < Length; ++i)
1148 {
1149 if (Buffer[i] == '\\')
1150 break;
1151 }
1152
1153 if (i >= Length)
1154 i -= 3;
1155 }
1156
1157 /* Skip compatible PnP Id */
1158 if (Buffer[i] == '\\')
1159 {
1160 for (j = ++i; i < Length; ++i)
1161 {
1162 if (Buffer[i] == '\\')
1163 break;
1164 }
1165 if (Buffer[j] == '*')
1166 ++j;
1167 if (i >= Length)
1168 i -= 3;
1169 }
1170
1171 /* Get product description */
1172 if (Buffer[i] == '\\')
1173 {
1174 for (j = ++i; i < Length; ++i)
1175 {
1176 if (Buffer[i] == ';')
1177 break;
1178 }
1179 if (i >= Length)
1180 i -= 3;
1181 if (i > j + 1)
1182 {
1183 for (k = 0; k < i - j; k++)
1184 {
1185 Identifier[k + 10] = Buffer[k + j];
1186 }
1187 Identifier[10 + (i-j)] = 0;
1188 }
1189 }
1190
1191 DPRINTM(DPRINT_HWDETECT,
1192 "Identifier string: %s\n",
1193 Identifier);
1194 }
1195
1196 if (Length == 0 || strlen(Identifier) < 11)
1197 {
1198 switch (MouseType)
1199 {
1200 case MOUSE_TYPE_LOGITECH:
1201 strcpy (Identifier,
1202 "LOGITECH SERIAL MOUSE");
1203 break;
1204
1205 case MOUSE_TYPE_WHEELZ:
1206 strcpy (Identifier,
1207 "MICROSOFT SERIAL MOUSE WITH WHEEL");
1208 break;
1209
1210 case MOUSE_TYPE_MICROSOFT:
1211 default:
1212 strcpy (Identifier,
1213 "MICROSOFT SERIAL MOUSE");
1214 break;
1215 }
1216 }
1217
1218 /* Create 'PointerPeripheral' key */
1219 FldrCreateComponentKey(ControllerKey,
1220 L"PointerPeripheral",
1221 0,
1222 PeripheralClass,
1223 PointerPeripheral,
1224 &PeripheralKey);
1225 DPRINTM(DPRINT_HWDETECT,
1226 "Created key: PointerPeripheral\\0\n");
1227
1228 /* Set 'ComponentInformation' value */
1229 FldrSetComponentInformation(PeripheralKey,
1230 Input,
1231 0,
1232 0xFFFFFFFF);
1233
1234 /* Set 'Configuration Data' value */
1235 memset(&PartialResourceList, 0, sizeof(CM_PARTIAL_RESOURCE_LIST));
1236 PartialResourceList.Version = 1;
1237 PartialResourceList.Revision = 1;
1238 PartialResourceList.Count = 0;
1239
1240 FldrSetConfigurationData(PeripheralKey,
1241 &PartialResourceList,
1242 sizeof(CM_PARTIAL_RESOURCE_LIST) -
1243 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
1244
1245 /* Set 'Identifier' value */
1246 FldrSetIdentifier(PeripheralKey, Identifier);
1247 }
1248 }
1249
1250
1251 static VOID
1252 DetectSerialPorts(PCONFIGURATION_COMPONENT_DATA BusKey)
1253 {
1254 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
1255 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
1256 PCM_SERIAL_DEVICE_DATA SerialDeviceData;
1257 ULONG Irq[4] = {4, 3, 4, 3};
1258 ULONG Base;
1259 CHAR Buffer[80];
1260 PUSHORT BasePtr;
1261 ULONG ControllerNumber = 0;
1262 PCONFIGURATION_COMPONENT_DATA ControllerKey;
1263 ULONG i;
1264 ULONG Size;
1265
1266 DPRINTM(DPRINT_HWDETECT, "DetectSerialPorts()\n");
1267
1268 ControllerNumber = 0;
1269 BasePtr = (PUSHORT)0x400;
1270 for (i = 0; i < 4; i++, BasePtr++)
1271 {
1272 Base = (ULONG)*BasePtr;
1273 if (Base == 0)
1274 continue;
1275
1276 DPRINTM(DPRINT_HWDETECT,
1277 "Found COM%u port at 0x%x\n",
1278 i + 1,
1279 Base);
1280
1281 /* Create controller key */
1282 FldrCreateComponentKey(BusKey,
1283 L"SerialController",
1284 ControllerNumber,
1285 ControllerClass,
1286 SerialController,
1287 &ControllerKey);
1288
1289 /* Set 'ComponentInformation' value */
1290 FldrSetComponentInformation(ControllerKey,
1291 Output | Input | ConsoleIn | ConsoleOut,
1292 ControllerNumber,
1293 0xFFFFFFFF);
1294
1295 /* Build full device descriptor */
1296 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) +
1297 2 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) +
1298 sizeof(CM_SERIAL_DEVICE_DATA);
1299 PartialResourceList = MmHeapAlloc(Size);
1300 if (PartialResourceList == NULL)
1301 {
1302 DPRINTM(DPRINT_HWDETECT,
1303 "Failed to allocate resource descriptor\n");
1304 continue;
1305 }
1306 memset(PartialResourceList, 0, Size);
1307
1308 /* Initialize resource descriptor */
1309 PartialResourceList->Version = 1;
1310 PartialResourceList->Revision = 1;
1311 PartialResourceList->Count = 3;
1312
1313 /* Set IO Port */
1314 PartialDescriptor = &PartialResourceList->PartialDescriptors[0];
1315 PartialDescriptor->Type = CmResourceTypePort;
1316 PartialDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1317 PartialDescriptor->Flags = CM_RESOURCE_PORT_IO;
1318 PartialDescriptor->u.Port.Start.LowPart = Base;
1319 PartialDescriptor->u.Port.Start.HighPart = 0x0;
1320 PartialDescriptor->u.Port.Length = 7;
1321
1322 /* Set Interrupt */
1323 PartialDescriptor = &PartialResourceList->PartialDescriptors[1];
1324 PartialDescriptor->Type = CmResourceTypeInterrupt;
1325 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
1326 PartialDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
1327 PartialDescriptor->u.Interrupt.Level = Irq[i];
1328 PartialDescriptor->u.Interrupt.Vector = 0;
1329 PartialDescriptor->u.Interrupt.Affinity = 0xFFFFFFFF;
1330
1331 /* Set serial data (device specific) */
1332 PartialDescriptor = &PartialResourceList->PartialDescriptors[2];
1333 PartialDescriptor->Type = CmResourceTypeDeviceSpecific;
1334 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
1335 PartialDescriptor->Flags = 0;
1336 PartialDescriptor->u.DeviceSpecificData.DataSize = sizeof(CM_SERIAL_DEVICE_DATA);
1337
1338 SerialDeviceData =
1339 (PCM_SERIAL_DEVICE_DATA)&PartialResourceList->PartialDescriptors[3];
1340 SerialDeviceData->BaudClock = 1843200; /* UART Clock frequency (Hertz) */
1341
1342 /* Set 'Configuration Data' value */
1343 FldrSetConfigurationData(ControllerKey, PartialResourceList, Size);
1344 MmHeapFree(PartialResourceList);
1345
1346 /* Set 'Identifier' value */
1347 sprintf(Buffer, "COM%ld", i + 1);
1348 FldrSetIdentifier(ControllerKey, Buffer);
1349 DPRINTM(DPRINT_HWDETECT,
1350 "Created value: Identifier %s\n",
1351 Buffer);
1352
1353 if (!Rs232PortInUse(Base))
1354 {
1355 /* Detect serial mouse */
1356 DetectSerialPointerPeripheral(ControllerKey, UlongToPtr(Base));
1357 }
1358
1359 ControllerNumber++;
1360 }
1361 }
1362
1363
1364 static VOID
1365 DetectParallelPorts(PCONFIGURATION_COMPONENT_DATA BusKey)
1366 {
1367 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
1368 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
1369 ULONG Irq[3] = {7, 5, (ULONG)-1};
1370 CHAR Buffer[80];
1371 PCONFIGURATION_COMPONENT_DATA ControllerKey;
1372 PUSHORT BasePtr;
1373 ULONG Base;
1374 ULONG ControllerNumber;
1375 ULONG i;
1376 ULONG Size;
1377
1378 DPRINTM(DPRINT_HWDETECT, "DetectParallelPorts() called\n");
1379
1380 ControllerNumber = 0;
1381 BasePtr = (PUSHORT)0x408;
1382 for (i = 0; i < 3; i++, BasePtr++)
1383 {
1384 Base = (ULONG)*BasePtr;
1385 if (Base == 0)
1386 continue;
1387
1388 DPRINTM(DPRINT_HWDETECT,
1389 "Parallel port %u: %x\n",
1390 ControllerNumber,
1391 Base);
1392
1393 /* Create controller key */
1394 FldrCreateComponentKey(BusKey,
1395 L"ParallelController",
1396 ControllerNumber,
1397 ControllerClass,
1398 ParallelController,
1399 &ControllerKey);
1400
1401 /* Set 'ComponentInformation' value */
1402 FldrSetComponentInformation(ControllerKey,
1403 Output,
1404 ControllerNumber,
1405 0xFFFFFFFF);
1406
1407 /* Build full device descriptor */
1408 Size = sizeof(CM_PARTIAL_RESOURCE_LIST);
1409 if (Irq[i] != (ULONG)-1)
1410 Size += sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
1411
1412 PartialResourceList = MmHeapAlloc(Size);
1413 if (PartialResourceList == NULL)
1414 {
1415 DPRINTM(DPRINT_HWDETECT,
1416 "Failed to allocate resource descriptor\n");
1417 continue;
1418 }
1419 memset(PartialResourceList, 0, Size);
1420
1421 /* Initialize resource descriptor */
1422 PartialResourceList->Version = 1;
1423 PartialResourceList->Revision = 1;
1424 PartialResourceList->Count = (Irq[i] != (ULONG)-1) ? 2 : 1;
1425
1426 /* Set IO Port */
1427 PartialDescriptor = &PartialResourceList->PartialDescriptors[0];
1428 PartialDescriptor->Type = CmResourceTypePort;
1429 PartialDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1430 PartialDescriptor->Flags = CM_RESOURCE_PORT_IO;
1431 PartialDescriptor->u.Port.Start.LowPart = Base;
1432 PartialDescriptor->u.Port.Start.HighPart = 0x0;
1433 PartialDescriptor->u.Port.Length = 3;
1434
1435 /* Set Interrupt */
1436 if (Irq[i] != (ULONG)-1)
1437 {
1438 PartialDescriptor = &PartialResourceList->PartialDescriptors[1];
1439 PartialDescriptor->Type = CmResourceTypeInterrupt;
1440 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
1441 PartialDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
1442 PartialDescriptor->u.Interrupt.Level = Irq[i];
1443 PartialDescriptor->u.Interrupt.Vector = 0;
1444 PartialDescriptor->u.Interrupt.Affinity = 0xFFFFFFFF;
1445 }
1446
1447 /* Set 'Configuration Data' value */
1448 FldrSetConfigurationData(ControllerKey, PartialResourceList, Size);
1449 MmHeapFree(PartialResourceList);
1450
1451 /* Set 'Identifier' value */
1452 sprintf(Buffer, "PARALLEL%ld", i + 1);
1453 FldrSetIdentifier(ControllerKey, Buffer);
1454 DPRINTM(DPRINT_HWDETECT,
1455 "Created value: Identifier %s\n",
1456 Buffer);
1457
1458 ControllerNumber++;
1459 }
1460
1461 DPRINTM(DPRINT_HWDETECT, "DetectParallelPorts() done\n");
1462 }
1463
1464
1465 static BOOLEAN
1466 DetectKeyboardDevice(VOID)
1467 {
1468 UCHAR Status;
1469 UCHAR Scancode;
1470 ULONG Loops;
1471 BOOLEAN Result = TRUE;
1472
1473 /* Identify device */
1474 WRITE_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA,
1475 0xF2);
1476
1477 /* Wait for reply */
1478 for (Loops = 0; Loops < 100; Loops++)
1479 {
1480 StallExecutionProcessor(10000);
1481 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
1482 if ((Status & CONTROLLER_STATUS_OUTPUT_BUFFER_FULL) != 0)
1483 break;
1484 }
1485
1486 if ((Status & CONTROLLER_STATUS_OUTPUT_BUFFER_FULL) == 0)
1487 {
1488 /* PC/XT keyboard or no keyboard */
1489 Result = FALSE;
1490 }
1491
1492 Scancode = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA);
1493 if (Scancode != 0xFA)
1494 {
1495 /* No ACK received */
1496 Result = FALSE;
1497 }
1498
1499 StallExecutionProcessor(10000);
1500
1501 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
1502 if ((Status & CONTROLLER_STATUS_OUTPUT_BUFFER_FULL) == 0)
1503 {
1504 /* Found AT keyboard */
1505 return Result;
1506 }
1507
1508 Scancode = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA);
1509 if (Scancode != 0xAB)
1510 {
1511 /* No 0xAB received */
1512 Result = FALSE;
1513 }
1514
1515 StallExecutionProcessor(10000);
1516
1517 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
1518 if ((Status & CONTROLLER_STATUS_OUTPUT_BUFFER_FULL) == 0)
1519 {
1520 /* No byte in buffer */
1521 Result = FALSE;
1522 }
1523
1524 Scancode = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA);
1525 if (Scancode != 0x41)
1526 {
1527 /* No 0x41 received */
1528 Result = FALSE;
1529 }
1530
1531 /* Found MF-II keyboard */
1532 return Result;
1533 }
1534
1535
1536 static VOID
1537 DetectKeyboardPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey)
1538 {
1539 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
1540 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
1541 PCM_KEYBOARD_DEVICE_DATA KeyboardData;
1542 PCONFIGURATION_COMPONENT_DATA PeripheralKey;
1543 ULONG Size;
1544
1545 /* HACK: don't call DetectKeyboardDevice() as it fails in Qemu 0.8.2 */
1546 if (TRUE || DetectKeyboardDevice())
1547 {
1548 /* Create controller key */
1549 FldrCreateComponentKey(ControllerKey,
1550 L"KeyboardPeripheral",
1551 0,
1552 PeripheralClass,
1553 KeyboardPeripheral,
1554 &PeripheralKey);
1555 DPRINTM(DPRINT_HWDETECT, "Created key: KeyboardPeripheral\\0\n");
1556
1557 /* Set 'ComponentInformation' value */
1558 FldrSetComponentInformation(PeripheralKey,
1559 Input | ConsoleIn,
1560 0,
1561 0xFFFFFFFF);
1562
1563 /* Set 'Configuration Data' value */
1564 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) +
1565 sizeof(CM_KEYBOARD_DEVICE_DATA);
1566 PartialResourceList = MmHeapAlloc(Size);
1567 if (PartialResourceList == NULL)
1568 {
1569 DPRINTM(DPRINT_HWDETECT,
1570 "Failed to allocate resource descriptor\n");
1571 return;
1572 }
1573
1574 /* Initialize resource descriptor */
1575 memset(PartialResourceList, 0, Size);
1576 PartialResourceList->Version = 1;
1577 PartialResourceList->Revision = 1;
1578 PartialResourceList->Count = 1;
1579
1580 PartialDescriptor = &PartialResourceList->PartialDescriptors[0];
1581 PartialDescriptor->Type = CmResourceTypeDeviceSpecific;
1582 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
1583 PartialDescriptor->u.DeviceSpecificData.DataSize = sizeof(CM_KEYBOARD_DEVICE_DATA);
1584
1585 KeyboardData = (PCM_KEYBOARD_DEVICE_DATA)(PartialDescriptor + 1);
1586 KeyboardData->Version = 1;
1587 KeyboardData->Revision = 1;
1588 KeyboardData->Type = 4;
1589 KeyboardData->Subtype = 0;
1590 KeyboardData->KeyboardFlags = 0x20;
1591
1592 /* Set 'Configuration Data' value */
1593 FldrSetConfigurationData(PeripheralKey, PartialResourceList, Size);
1594 MmHeapFree(PartialResourceList);
1595
1596 /* Set 'Identifier' value */
1597 FldrSetIdentifier(PeripheralKey, "PCAT_ENHANCED");
1598 }
1599 }
1600
1601
1602 static VOID
1603 DetectKeyboardController(PCONFIGURATION_COMPONENT_DATA BusKey)
1604 {
1605 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
1606 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
1607 PCONFIGURATION_COMPONENT_DATA ControllerKey;
1608 ULONG Size;
1609
1610 /* Create controller key */
1611 FldrCreateComponentKey(BusKey,
1612 L"KeyboardController",
1613 0,
1614 ControllerClass,
1615 KeyboardController,
1616 &ControllerKey);
1617 DPRINTM(DPRINT_HWDETECT, "Created key: KeyboardController\\0\n");
1618
1619 /* Set 'ComponentInformation' value */
1620 FldrSetComponentInformation(ControllerKey,
1621 Input | ConsoleIn,
1622 0,
1623 0xFFFFFFFF);
1624
1625 /* Set 'Configuration Data' value */
1626 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) +
1627 2 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
1628 PartialResourceList = MmHeapAlloc(Size);
1629 if (PartialResourceList == NULL)
1630 {
1631 DPRINTM(DPRINT_HWDETECT,
1632 "Failed to allocate resource descriptor\n");
1633 return;
1634 }
1635
1636 /* Initialize resource descriptor */
1637 memset(PartialResourceList, 0, Size);
1638 PartialResourceList->Version = 1;
1639 PartialResourceList->Revision = 1;
1640 PartialResourceList->Count = 3;
1641
1642 /* Set Interrupt */
1643 PartialDescriptor = &PartialResourceList->PartialDescriptors[0];
1644 PartialDescriptor->Type = CmResourceTypeInterrupt;
1645 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
1646 PartialDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
1647 PartialDescriptor->u.Interrupt.Level = 1;
1648 PartialDescriptor->u.Interrupt.Vector = 0;
1649 PartialDescriptor->u.Interrupt.Affinity = 0xFFFFFFFF;
1650
1651 /* Set IO Port 0x60 */
1652 PartialDescriptor = &PartialResourceList->PartialDescriptors[1];
1653 PartialDescriptor->Type = CmResourceTypePort;
1654 PartialDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1655 PartialDescriptor->Flags = CM_RESOURCE_PORT_IO;
1656 PartialDescriptor->u.Port.Start.LowPart = 0x60;
1657 PartialDescriptor->u.Port.Start.HighPart = 0x0;
1658 PartialDescriptor->u.Port.Length = 1;
1659
1660 /* Set IO Port 0x64 */
1661 PartialDescriptor = &PartialResourceList->PartialDescriptors[2];
1662 PartialDescriptor->Type = CmResourceTypePort;
1663 PartialDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1664 PartialDescriptor->Flags = CM_RESOURCE_PORT_IO;
1665 PartialDescriptor->u.Port.Start.LowPart = 0x64;
1666 PartialDescriptor->u.Port.Start.HighPart = 0x0;
1667 PartialDescriptor->u.Port.Length = 1;
1668
1669 /* Set 'Configuration Data' value */
1670 FldrSetConfigurationData(ControllerKey, PartialResourceList, Size);
1671 MmHeapFree(PartialResourceList);
1672
1673 DetectKeyboardPeripheral(ControllerKey);
1674 }
1675
1676
1677 static VOID
1678 PS2ControllerWait(VOID)
1679 {
1680 ULONG Timeout;
1681 UCHAR Status;
1682
1683 for (Timeout = 0; Timeout < CONTROLLER_TIMEOUT; Timeout++)
1684 {
1685 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
1686 if ((Status & CONTROLLER_STATUS_INPUT_BUFFER_FULL) == 0)
1687 return;
1688
1689 /* Sleep for one millisecond */
1690 StallExecutionProcessor(1000);
1691 }
1692 }
1693
1694
1695 static BOOLEAN
1696 DetectPS2AuxPort(VOID)
1697 {
1698 #if 1
1699 /* Current detection is too unreliable. Just do as if
1700 * the PS/2 aux port is always present
1701 */
1702 return TRUE;
1703 #else
1704 ULONG Loops;
1705 UCHAR Status;
1706
1707 /* Put the value 0x5A in the output buffer using the
1708 * "WriteAuxiliary Device Output Buffer" command (0xD3).
1709 * Poll the Status Register for a while to see if the value really turns up
1710 * in the Data Register. If the KEYBOARD_STATUS_MOUSE_OBF bit is also set
1711 * to 1 in the Status Register, we assume this controller has an
1712 * Auxiliary Port (a.k.a. Mouse Port).
1713 */
1714 PS2ControllerWait();
1715 WRITE_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_CONTROL,
1716 CONTROLLER_COMMAND_WRITE_MOUSE_OUTPUT_BUFFER);
1717 PS2ControllerWait();
1718
1719 /* 0x5A is a random dummy value */
1720 WRITE_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA,
1721 0x5A);
1722
1723 for (Loops = 0; Loops < 10; Loops++)
1724 {
1725 StallExecutionProcessor(10000);
1726 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
1727 if ((Status & CONTROLLER_STATUS_OUTPUT_BUFFER_FULL) != 0)
1728 break;
1729 }
1730
1731 READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA);
1732
1733 return (Status & CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL);
1734 #endif
1735 }
1736
1737
1738 static BOOLEAN
1739 DetectPS2AuxDevice(VOID)
1740 {
1741 UCHAR Scancode;
1742 UCHAR Status;
1743 ULONG Loops;
1744 BOOLEAN Result = TRUE;
1745
1746 PS2ControllerWait();
1747 WRITE_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_CONTROL,
1748 CONTROLLER_COMMAND_WRITE_MOUSE);
1749 PS2ControllerWait();
1750
1751 /* Identify device */
1752 WRITE_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA,
1753 0xF2);
1754
1755 /* Wait for reply */
1756 for (Loops = 0; Loops < 100; Loops++)
1757 {
1758 StallExecutionProcessor(10000);
1759 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
1760 if ((Status & CONTROLLER_STATUS_OUTPUT_BUFFER_FULL) != 0)
1761 break;
1762 }
1763
1764 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
1765 if ((Status & CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL) == 0)
1766 Result = FALSE;
1767
1768 Scancode = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA);
1769 if (Scancode != 0xFA)
1770 Result = FALSE;
1771
1772 StallExecutionProcessor(10000);
1773
1774 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
1775 if ((Status & CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL) == 0)
1776 Result = FALSE;
1777
1778 Scancode = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA);
1779 if (Scancode != 0x00)
1780 Result = FALSE;
1781
1782 return Result;
1783 }
1784
1785
1786 static VOID
1787 DetectPS2Mouse(PCONFIGURATION_COMPONENT_DATA BusKey)
1788 {
1789 CM_PARTIAL_RESOURCE_LIST PartialResourceList;
1790 PCONFIGURATION_COMPONENT_DATA ControllerKey;
1791 PCONFIGURATION_COMPONENT_DATA PeripheralKey;
1792
1793 if (DetectPS2AuxPort())
1794 {
1795 DPRINTM(DPRINT_HWDETECT, "Detected PS2 port\n");
1796
1797 /* Create controller key */
1798 FldrCreateComponentKey(BusKey,
1799 L"PointerController",
1800 0,
1801 ControllerClass,
1802 PointerController,
1803 &ControllerKey);
1804 DPRINTM(DPRINT_HWDETECT, "Created key: PointerController\\0\n");
1805
1806 /* Set 'ComponentInformation' value */
1807 FldrSetComponentInformation(ControllerKey,
1808 Input,
1809 0,
1810 0xFFFFFFFF);
1811
1812 memset(&PartialResourceList, 0, sizeof(CM_PARTIAL_RESOURCE_LIST));
1813
1814 /* Initialize resource descriptor */
1815 PartialResourceList.Version = 1;
1816 PartialResourceList.Revision = 1;
1817 PartialResourceList.Count = 1;
1818
1819 /* Set Interrupt */
1820 PartialResourceList.PartialDescriptors[0].Type = CmResourceTypeInterrupt;
1821 PartialResourceList.PartialDescriptors[0].ShareDisposition = CmResourceShareUndetermined;
1822 PartialResourceList.PartialDescriptors[0].Flags = CM_RESOURCE_INTERRUPT_LATCHED;
1823 PartialResourceList.PartialDescriptors[0].u.Interrupt.Level = 12;
1824 PartialResourceList.PartialDescriptors[0].u.Interrupt.Vector = 0;
1825 PartialResourceList.PartialDescriptors[0].u.Interrupt.Affinity = 0xFFFFFFFF;
1826
1827 /* Set 'Configuration Data' value */
1828 FldrSetConfigurationData(ControllerKey,
1829 &PartialResourceList,
1830 sizeof(CM_PARTIAL_RESOURCE_LIST));
1831
1832 if (DetectPS2AuxDevice())
1833 {
1834 DPRINTM(DPRINT_HWDETECT, "Detected PS2 mouse\n");
1835
1836 /* Create peripheral key */
1837 FldrCreateComponentKey(ControllerKey,
1838 L"PointerPeripheral",
1839 0,
1840 ControllerClass,
1841 PointerPeripheral,
1842 &PeripheralKey);
1843 DPRINTM(DPRINT_HWDETECT, "Created key: PointerPeripheral\\0\n");
1844
1845 /* Set 'ComponentInformation' value */
1846 FldrSetComponentInformation(PeripheralKey,
1847 Input,
1848 0,
1849 0xFFFFFFFF);
1850
1851 /* Initialize resource descriptor */
1852 memset(&PartialResourceList, 0, sizeof(CM_PARTIAL_RESOURCE_LIST));
1853 PartialResourceList.Version = 1;
1854 PartialResourceList.Revision = 1;
1855 PartialResourceList.Count = 0;
1856
1857 /* Set 'Configuration Data' value */
1858 FldrSetConfigurationData(PeripheralKey,
1859 &PartialResourceList,
1860 sizeof(CM_PARTIAL_RESOURCE_LIST) -
1861 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
1862
1863 /* Set 'Identifier' value */
1864 FldrSetIdentifier(PeripheralKey, "MICROSOFT PS2 MOUSE");
1865 }
1866 }
1867 }
1868
1869
1870 static VOID
1871 DetectDisplayController(PCONFIGURATION_COMPONENT_DATA BusKey)
1872 {
1873 CHAR Buffer[80];
1874 PCONFIGURATION_COMPONENT_DATA ControllerKey;
1875 USHORT VesaVersion;
1876
1877 FldrCreateComponentKey(BusKey,
1878 L"DisplayController",
1879 0,
1880 ControllerClass,
1881 DisplayController,
1882 &ControllerKey);
1883 DPRINTM(DPRINT_HWDETECT, "Created key: DisplayController\\0\n");
1884
1885 /* Set 'ComponentInformation' value */
1886 FldrSetComponentInformation(ControllerKey,
1887 0x00,
1888 0,
1889 0xFFFFFFFF);
1890
1891 /* FIXME: Set 'ComponentInformation' value */
1892
1893 VesaVersion = BiosIsVesaSupported();
1894 if (VesaVersion != 0)
1895 {
1896 DPRINTM(DPRINT_HWDETECT,
1897 "VESA version %c.%c\n",
1898 (VesaVersion >> 8) + '0',
1899 (VesaVersion & 0xFF) + '0');
1900 }
1901 else
1902 {
1903 DPRINTM(DPRINT_HWDETECT,
1904 "VESA not supported\n");
1905 }
1906
1907 if (VesaVersion >= 0x0200)
1908 {
1909 strcpy(Buffer,
1910 "VBE Display");
1911 }
1912 else
1913 {
1914 strcpy(Buffer,
1915 "VGA Display");
1916 }
1917
1918 /* Set 'Identifier' value */
1919 FldrSetIdentifier(ControllerKey, Buffer);
1920
1921 /* FIXME: Add display peripheral (monitor) data */
1922 }
1923
1924
1925 static VOID
1926 DetectIsaBios(PCONFIGURATION_COMPONENT_DATA SystemKey, ULONG *BusNumber)
1927 {
1928 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
1929 PCONFIGURATION_COMPONENT_DATA BusKey;
1930 ULONG Size;
1931
1932 /* Create new bus key */
1933 FldrCreateComponentKey(SystemKey,
1934 L"MultifunctionAdapter",
1935 *BusNumber,
1936 AdapterClass,
1937 MultiFunctionAdapter,
1938 &BusKey);
1939
1940 /* Set 'Component Information' value similar to my NT4 box */
1941 FldrSetComponentInformation(BusKey,
1942 0x0,
1943 0x0,
1944 0xFFFFFFFF);
1945
1946 /* Increment bus number */
1947 (*BusNumber)++;
1948
1949 /* Set 'Identifier' value */
1950 FldrSetIdentifier(BusKey, "ISA");
1951
1952 /* Set 'Configuration Data' value */
1953 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) -
1954 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
1955 PartialResourceList = MmHeapAlloc(Size);
1956 if (PartialResourceList == NULL)
1957 {
1958 DPRINTM(DPRINT_HWDETECT,
1959 "Failed to allocate resource descriptor\n");
1960 return;
1961 }
1962
1963 /* Initialize resource descriptor */
1964 memset(PartialResourceList, 0, Size);
1965 PartialResourceList->Version = 1;
1966 PartialResourceList->Revision = 1;
1967 PartialResourceList->Count = 0;
1968
1969 /* Set 'Configuration Data' value */
1970 FldrSetConfigurationData(BusKey, PartialResourceList, Size);
1971 MmHeapFree(PartialResourceList);
1972
1973 /* Detect ISA/BIOS devices */
1974 DetectBiosDisks(SystemKey, BusKey);
1975
1976 DetectSerialPorts(BusKey);
1977
1978 DetectParallelPorts(BusKey);
1979
1980 DetectKeyboardController(BusKey);
1981
1982 DetectPS2Mouse(BusKey);
1983
1984 DetectDisplayController(BusKey);
1985
1986 /* FIXME: Detect more ISA devices */
1987 }
1988
1989
1990 PCONFIGURATION_COMPONENT_DATA
1991 PcHwDetect(VOID)
1992 {
1993 PCONFIGURATION_COMPONENT_DATA SystemKey;
1994 ULONG BusNumber = 0;
1995
1996 DPRINTM(DPRINT_HWDETECT, "DetectHardware()\n");
1997
1998 /* Create the 'System' key */
1999 FldrCreateSystemKey(&SystemKey);
2000
2001 /* Set empty component information */
2002 FldrSetComponentInformation(SystemKey,
2003 0x0,
2004 0x0,
2005 0xFFFFFFFF);
2006
2007 /* Detect buses */
2008 DetectPciBios(SystemKey, &BusNumber);
2009 DetectApmBios(SystemKey, &BusNumber);
2010 DetectPnpBios(SystemKey, &BusNumber);
2011 DetectIsaBios(SystemKey, &BusNumber);
2012 DetectAcpiBios(SystemKey, &BusNumber);
2013
2014 DPRINTM(DPRINT_HWDETECT, "DetectHardware() Done\n");
2015
2016 return SystemKey;
2017 }
2018
2019 /* EOF */