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