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