Detect display controller. Distinguish VGA and VBE display devices.
[reactos.git] / 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 #include <arch.h>
23 #include <rtl.h>
24 #include <debug.h>
25 #include <disk.h>
26 #include <mm.h>
27 #include <portio.h>
28 #include <video.h>
29
30 #include "../../reactos/registry.h"
31 #include "hardware.h"
32
33
34 #define MILLISEC (10)
35 #define PRECISION (8)
36
37 #define HZ (100)
38 #define CLOCK_TICK_RATE (1193182)
39 #define LATCH (CLOCK_TICK_RATE / HZ)
40
41
42 /* No Mouse */
43 #define MOUSE_TYPE_NONE 0
44 /* Microsoft Mouse with 2 buttons */
45 #define MOUSE_TYPE_MICROSOFT 1
46 /* Logitech Mouse with 3 buttons */
47 #define MOUSE_TYPE_LOGITECH 2
48 /* Microsoft Wheel Mouse (aka Z Mouse) */
49 #define MOUSE_TYPE_WHEELZ 3
50 /* Mouse Systems Mouse */
51 #define MOUSE_TYPE_MOUSESYSTEMS 4
52
53
54 /* PS2 stuff */
55
56 /* Controller registers. */
57 #define CONTROLLER_REGISTER_STATUS 0x64
58 #define CONTROLLER_REGISTER_CONTROL 0x64
59 #define CONTROLLER_REGISTER_DATA 0x60
60
61 /* Controller commands. */
62 #define CONTROLLER_COMMAND_READ_MODE 0x20
63 #define CONTROLLER_COMMAND_WRITE_MODE 0x60
64 #define CONTROLLER_COMMAND_GET_VERSION 0xA1
65 #define CONTROLLER_COMMAND_MOUSE_DISABLE 0xA7
66 #define CONTROLLER_COMMAND_MOUSE_ENABLE 0xA8
67 #define CONTROLLER_COMMAND_TEST_MOUSE 0xA9
68 #define CONTROLLER_COMMAND_SELF_TEST 0xAA
69 #define CONTROLLER_COMMAND_KEYBOARD_TEST 0xAB
70 #define CONTROLLER_COMMAND_KEYBOARD_DISABLE 0xAD
71 #define CONTROLLER_COMMAND_KEYBOARD_ENABLE 0xAE
72 #define CONTROLLER_COMMAND_WRITE_MOUSE_OUTPUT_BUFFER 0xD3
73 #define CONTROLLER_COMMAND_WRITE_MOUSE 0xD4
74
75 /* Controller status */
76 #define CONTROLLER_STATUS_OUTPUT_BUFFER_FULL 0x01
77 #define CONTROLLER_STATUS_INPUT_BUFFER_FULL 0x02
78 #define CONTROLLER_STATUS_SELF_TEST 0x04
79 #define CONTROLLER_STATUS_COMMAND 0x08
80 #define CONTROLLER_STATUS_UNLOCKED 0x10
81 #define CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL 0x20
82 #define CONTROLLER_STATUS_GENERAL_TIMEOUT 0x40
83 #define CONTROLLER_STATUS_PARITY_ERROR 0x80
84 #define AUX_STATUS_OUTPUT_BUFFER_FULL (CONTROLLER_STATUS_OUTPUT_BUFFER_FULL | \
85 CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL)
86
87 /* Timeout in ms for sending to keyboard controller. */
88 #define CONTROLLER_TIMEOUT 250
89
90
91 typedef struct _CM_INT13_DRIVE_PARAMETER
92 {
93 U16 DriveSelect;
94 U32 MaxCylinders;
95 U16 SectorsPerTrack;
96 U16 MaxHeads;
97 U16 NumberDrives;
98 } CM_INT13_DRIVE_PARAMETER, *PCM_INT13_DRIVE_PARAMETER;
99
100
101 typedef struct _CM_DISK_GEOMETRY_DEVICE_DATA
102 {
103 U32 BytesPerSector;
104 U32 NumberOfCylinders;
105 U32 SectorsPerTrack;
106 U32 NumberOfHeads;
107 } CM_DISK_GEOMETRY_DEVICE_DATA, *PCM_DISK_GEOMETRY_DEVICE_DATA;
108
109
110 typedef struct _CM_PNP_BIOS_DEVICE_NODE
111 {
112 U16 Size;
113 U8 Node;
114 U32 ProductId;
115 U8 DeviceType[3];
116 U16 DeviceAttributes;
117 } __attribute__((packed)) CM_PNP_BIOS_DEVICE_NODE, *PCM_PNP_BIOS_DEVICE_NODE;
118
119
120 typedef struct _CM_PNP_BIOS_INSTALLATION_CHECK
121 {
122 U8 Signature[4];
123 U8 Revision;
124 U8 Length;
125 U16 ControlField;
126 U8 Checksum;
127 U32 EventFlagAddress;
128 U16 RealModeEntryOffset;
129 U16 RealModeEntrySegment;
130 U16 ProtectedModeEntryOffset;
131 U32 ProtectedModeCodeBaseAddress;
132 U32 OemDeviceId;
133 U16 RealModeDataBaseAddress;
134 U32 ProtectedModeDataBaseAddress;
135 } __attribute__((packed)) CM_PNP_BIOS_INSTALLATION_CHECK, *PCM_PNP_BIOS_INSTALLATION_CHECK;
136
137
138 typedef struct _CM_SERIAL_DEVICE_DATA
139 {
140 U16 Version;
141 U16 Revision;
142 U32 BaudClock;
143 } __attribute__((packed)) CM_SERIAL_DEVICE_DATA, *PCM_SERIAL_DEVICE_DATA;
144
145
146 typedef struct _CM_FLOPPY_DEVICE_DATA
147 {
148 U16 Version;
149 U16 Revision;
150 CHAR Size[8];
151 U32 MaxDensity;
152 U32 MountDensity;
153
154 /* Version 2.0 data */
155 U8 StepRateHeadUnloadTime;
156 U8 HeadLoadTime;
157 U8 MotorOffTime;
158 U8 SectorLengthCode;
159 U8 SectorPerTrack;
160 U8 ReadWriteGapLength;
161 U8 DataTransferLength;
162 U8 FormatGapLength;
163 U8 FormatFillCharacter;
164 U8 HeadSettleTime;
165 U8 MotorSettleTime;
166 U8 MaximumTrackValue;
167 U8 DataTransferRate;
168 } __attribute__((packed)) CM_FLOPPY_DEVICE_DATA, *PCM_FLOPPY_DEVICE_DATA;
169
170
171 typedef struct _CM_KEYBOARD_DEVICE_DATA
172 {
173 U16 Version;
174 U16 Revision;
175 U8 Type;
176 U8 Subtype;
177 U16 KeyboardFlags;
178 } __attribute__((packed)) CM_KEYBOARD_DEVICE_DATA, *PCM_KEYBOARD_DEVICE_DATA;
179
180
181 static char Hex[] = "0123456789ABCDEF";
182 static unsigned int delay_count = 1;
183
184
185 /* FUNCTIONS ****************************************************************/
186
187
188 static VOID
189 __KeStallExecutionProcessor(U32 Loops)
190 {
191 register unsigned int i;
192 for (i = 0; i < Loops; i++);
193 }
194
195 VOID KeStallExecutionProcessor(U32 Microseconds)
196 {
197 U64 LoopCount = ((U64)delay_count * (U64)Microseconds) / 1000ULL;
198 __KeStallExecutionProcessor((U32)LoopCount);
199 }
200
201
202 static U32
203 Read8254Timer(VOID)
204 {
205 U32 Count;
206
207 WRITE_PORT_UCHAR((PU8)0x43, 0x00);
208 Count = READ_PORT_UCHAR((PU8)0x40);
209 Count |= READ_PORT_UCHAR((PU8)0x40) << 8;
210
211 return Count;
212 }
213
214
215 static VOID
216 WaitFor8254Wraparound(VOID)
217 {
218 U32 CurCount;
219 U32 PrevCount = ~0;
220 S32 Delta;
221
222 CurCount = Read8254Timer();
223
224 do
225 {
226 PrevCount = CurCount;
227 CurCount = Read8254Timer();
228 Delta = CurCount - PrevCount;
229
230 /*
231 * This limit for delta seems arbitrary, but it isn't, it's
232 * slightly above the level of error a buggy Mercury/Neptune
233 * chipset timer can cause.
234 */
235 }
236 while (Delta < 300);
237 }
238
239
240 VOID
241 HalpCalibrateStallExecution(VOID)
242 {
243 U32 i;
244 U32 calib_bit;
245 U32 CurCount;
246
247 /* Initialise timer interrupt with MILLISECOND ms interval */
248 WRITE_PORT_UCHAR((PU8)0x43, 0x34); /* binary, mode 2, LSB/MSB, ch 0 */
249 WRITE_PORT_UCHAR((PU8)0x40, LATCH & 0xff); /* LSB */
250 WRITE_PORT_UCHAR((PU8)0x40, LATCH >> 8); /* MSB */
251
252 /* Stage 1: Coarse calibration */
253
254 WaitFor8254Wraparound();
255
256 delay_count = 1;
257
258 do {
259 delay_count <<= 1; /* Next delay count to try */
260
261 WaitFor8254Wraparound();
262
263 __KeStallExecutionProcessor(delay_count); /* Do the delay */
264
265 CurCount = Read8254Timer();
266 } while (CurCount > LATCH / 2);
267
268 delay_count >>= 1; /* Get bottom value for delay */
269
270 /* Stage 2: Fine calibration */
271
272 calib_bit = delay_count; /* Which bit are we going to test */
273
274 for(i=0;i<PRECISION;i++) {
275 calib_bit >>= 1; /* Next bit to calibrate */
276 if(!calib_bit) break; /* If we have done all bits, stop */
277
278 delay_count |= calib_bit; /* Set the bit in delay_count */
279
280 WaitFor8254Wraparound();
281
282 __KeStallExecutionProcessor(delay_count); /* Do the delay */
283
284 CurCount = Read8254Timer();
285 if (CurCount <= LATCH / 2) /* If a tick has passed, turn the */
286 delay_count &= ~calib_bit; /* calibrated bit back off */
287 }
288
289 /* We're finished: Do the finishing touches */
290 delay_count /= (MILLISEC / 2); /* Calculate delay_count for 1ms */
291 }
292
293
294 VOID
295 SetComponentInformation(HKEY ComponentKey,
296 U32 Flags,
297 U32 Key,
298 U32 Affinity)
299 {
300 CM_COMPONENT_INFORMATION CompInfo;
301 S32 Error;
302
303 CompInfo.Flags = Flags;
304 CompInfo.Version = 0;
305 CompInfo.Key = Key;
306 CompInfo.Affinity = Affinity;
307
308 /* Set 'Component Information' value */
309 Error = RegSetValue(ComponentKey,
310 "Component Information",
311 REG_BINARY,
312 (PU8)&CompInfo,
313 sizeof(CM_COMPONENT_INFORMATION));
314 if (Error != ERROR_SUCCESS)
315 {
316 DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error));
317 }
318 }
319
320
321 static VOID
322 DetectPnpBios(HKEY SystemKey, U32 *BusNumber)
323 {
324 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
325 PCM_PNP_BIOS_DEVICE_NODE DeviceNode;
326 PCM_PNP_BIOS_INSTALLATION_CHECK InstData;
327 char Buffer[80];
328 HKEY BusKey;
329 U32 x;
330 U32 NodeSize = 0;
331 U32 NodeCount = 0;
332 U8 NodeNumber;
333 U32 FoundNodeCount;
334 int i;
335 U32 PnpBufferSize;
336 U32 Size;
337 char *Ptr;
338 S32 Error;
339
340 InstData = (PCM_PNP_BIOS_INSTALLATION_CHECK)PnpBiosSupported();
341 if (InstData == NULL || strncmp(InstData->Signature, "$PnP", 4))
342 {
343 DbgPrint((DPRINT_HWDETECT, "PnP-BIOS not supported\n"));
344 return;
345 }
346 DbgPrint((DPRINT_HWDETECT, "Signature '%c%c%c%c'\n",
347 InstData->Signature[0], InstData->Signature[1],
348 InstData->Signature[2], InstData->Signature[3]));
349
350
351 x = PnpBiosGetDeviceNodeCount(&NodeSize, &NodeCount);
352 if (x != 0 || NodeSize == 0 || NodeCount == 0)
353 {
354 DbgPrint((DPRINT_HWDETECT, "PnP-BIOS failed to enumerate device nodes\n"));
355 return;
356 }
357 DbgPrint((DPRINT_HWDETECT, "PnP-BIOS supported\n"));
358 DbgPrint((DPRINT_HWDETECT, "MaxNodeSize %u NodeCount %u\n", NodeSize, NodeCount));
359 DbgPrint((DPRINT_HWDETECT, "Estimated buffer size %u\n", NodeSize * NodeCount));
360
361 /* Create new bus key */
362 sprintf(Buffer,
363 "MultifunctionAdapter\\%u", *BusNumber);
364 Error = RegCreateKey(SystemKey,
365 Buffer,
366 &BusKey);
367 if (Error != ERROR_SUCCESS)
368 {
369 DbgPrint((DPRINT_HWDETECT, "RegCreateKey() failed (Error %u)\n", (int)Error));
370 return;
371 }
372
373 /* Increment bus number */
374 (*BusNumber)++;
375
376 /* Set 'Identifier' value */
377 Error = RegSetValue(BusKey,
378 "Identifier",
379 REG_SZ,
380 (PU8)"PNP BIOS",
381 9);
382 if (Error != ERROR_SUCCESS)
383 {
384 DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error));
385 return;
386 }
387
388 /* Set 'Configuration Data' value */
389 Size = sizeof(CM_FULL_RESOURCE_DESCRIPTOR) + (NodeSize * NodeCount);
390 FullResourceDescriptor = MmAllocateMemory(Size);
391 if (FullResourceDescriptor == NULL)
392 {
393 DbgPrint((DPRINT_HWDETECT,
394 "Failed to allocate resource descriptor\n"));
395 return;
396 }
397 memset(FullResourceDescriptor, 0, Size);
398
399 /* Initialize resource descriptor */
400 FullResourceDescriptor->InterfaceType = Internal;
401 FullResourceDescriptor->BusNumber = 0;
402 FullResourceDescriptor->PartialResourceList.Count = 1;
403 FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].Type =
404 CmResourceTypeDeviceSpecific;
405 FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].ShareDisposition =
406 CmResourceShareUndetermined;
407 // FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].Flags =
408
409 Ptr = (char *)(((PVOID)&FullResourceDescriptor->PartialResourceList.PartialDescriptors[0]) +
410 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
411
412 /* Set instalation check data */
413 memcpy (Ptr, InstData, sizeof(CM_PNP_BIOS_INSTALLATION_CHECK));
414 Ptr += sizeof(CM_PNP_BIOS_INSTALLATION_CHECK);
415
416 /* Copy device nodes */
417 FoundNodeCount = 0;
418 PnpBufferSize = sizeof(CM_PNP_BIOS_INSTALLATION_CHECK);
419 for (i = 0; i < 0xFF; i++)
420 {
421 NodeNumber = (U8)i;
422
423 x = PnpBiosGetDeviceNode(&NodeNumber, (PVOID)DISKREADBUFFER);
424 if (x == 0)
425 {
426 DeviceNode = (PCM_PNP_BIOS_DEVICE_NODE)DISKREADBUFFER;
427
428 DbgPrint((DPRINT_HWDETECT,
429 "Node: %u Size %u (0x%x)\n",
430 DeviceNode->Node,
431 DeviceNode->Size,
432 DeviceNode->Size));
433 // printf("Node: %u Size %u (0x%x)\n",
434 // DeviceNode->Node,
435 // DeviceNode->Size,
436 // DeviceNode->Size);
437
438 memcpy (Ptr,
439 DeviceNode,
440 DeviceNode->Size);
441
442 Ptr += DeviceNode->Size;
443 PnpBufferSize += DeviceNode->Size;
444
445 FoundNodeCount++;
446 if (FoundNodeCount >= NodeCount)
447 break;
448 }
449 }
450
451 /* Set real data size */
452 FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].u.DeviceSpecificData.DataSize =
453 PnpBufferSize;
454 Size = sizeof(CM_FULL_RESOURCE_DESCRIPTOR) + PnpBufferSize;
455
456 DbgPrint((DPRINT_HWDETECT, "Real buffer size: %u\n", PnpBufferSize));
457 DbgPrint((DPRINT_HWDETECT, "Resource size: %u\n", Size));
458
459 /* Set 'Configuration Data' value */
460 Error = RegSetValue(BusKey,
461 "Configuration Data",
462 REG_FULL_RESOURCE_DESCRIPTOR,
463 (PU8) FullResourceDescriptor,
464 Size);
465 MmFreeMemory(FullResourceDescriptor);
466 if (Error != ERROR_SUCCESS)
467 {
468 DbgPrint((DPRINT_HWDETECT,
469 "RegSetValue(Configuration Data) failed (Error %u)\n",
470 (int)Error));
471 }
472 }
473
474
475
476 static VOID
477 SetHarddiskConfigurationData(HKEY DiskKey,
478 U32 DriveNumber)
479 {
480 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
481 PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry;
482 EXTENDED_GEOMETRY ExtGeometry;
483 GEOMETRY Geometry;
484 U32 Size;
485 S32 Error;
486
487 /* Set 'Configuration Data' value */
488 Size = sizeof(CM_FULL_RESOURCE_DESCRIPTOR) +
489 sizeof(CM_DISK_GEOMETRY_DEVICE_DATA);
490 FullResourceDescriptor = MmAllocateMemory(Size);
491 if (FullResourceDescriptor == NULL)
492 {
493 DbgPrint((DPRINT_HWDETECT,
494 "Failed to allocate a full resource descriptor\n"));
495 return;
496 }
497
498 memset(FullResourceDescriptor, 0, Size);
499 FullResourceDescriptor->InterfaceType = InterfaceTypeUndefined;
500 FullResourceDescriptor->BusNumber = 0;
501 FullResourceDescriptor->PartialResourceList.Count = 1;
502 FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].Type =
503 CmResourceTypeDeviceSpecific;
504 // FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].ShareDisposition =
505 // FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].Flags =
506 FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].u.DeviceSpecificData.DataSize =
507 sizeof(CM_DISK_GEOMETRY_DEVICE_DATA);
508
509 /* Get pointer to geometry data */
510 DiskGeometry = ((PVOID)FullResourceDescriptor) + sizeof(CM_FULL_RESOURCE_DESCRIPTOR);
511
512 /* Get the disk geometry */
513 ExtGeometry.Size = sizeof(EXTENDED_GEOMETRY);
514 if (DiskGetExtendedDriveParameters(DriveNumber, &ExtGeometry, ExtGeometry.Size))
515 {
516 DiskGeometry->BytesPerSector = ExtGeometry.BytesPerSector;
517 DiskGeometry->NumberOfCylinders = ExtGeometry.Cylinders;
518 DiskGeometry->SectorsPerTrack = ExtGeometry.SectorsPerTrack;
519 DiskGeometry->NumberOfHeads = ExtGeometry.Heads;
520 }
521 else if(DiskGetDriveParameters(DriveNumber, &Geometry))
522 {
523 DiskGeometry->BytesPerSector = Geometry.BytesPerSector;
524 DiskGeometry->NumberOfCylinders = Geometry.Cylinders;
525 DiskGeometry->SectorsPerTrack = Geometry.Sectors;
526 DiskGeometry->NumberOfHeads = Geometry.Heads;
527 }
528 else
529 {
530 DbgPrint((DPRINT_HWDETECT, "Reading disk geometry failed\n"));
531 MmFreeMemory(FullResourceDescriptor);
532 return;
533 }
534 DbgPrint((DPRINT_HWDETECT,
535 "Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n",
536 DriveNumber,
537 DiskGeometry->NumberOfCylinders,
538 DiskGeometry->NumberOfHeads,
539 DiskGeometry->SectorsPerTrack,
540 DiskGeometry->BytesPerSector));
541
542 Error = RegSetValue(DiskKey,
543 "Configuration Data",
544 REG_FULL_RESOURCE_DESCRIPTOR,
545 (PU8) FullResourceDescriptor,
546 Size);
547 MmFreeMemory(FullResourceDescriptor);
548 if (Error != ERROR_SUCCESS)
549 {
550 DbgPrint((DPRINT_HWDETECT,
551 "RegSetValue(Configuration Data) failed (Error %u)\n",
552 (int)Error));
553 }
554 }
555
556
557 static VOID
558 SetHarddiskIdentifier(HKEY DiskKey,
559 U32 DriveNumber)
560 {
561 PMASTER_BOOT_RECORD Mbr;
562 U32 *Buffer;
563 U32 i;
564 U32 Checksum;
565 U32 Signature;
566 char Identifier[20];
567 S32 Error;
568
569 /* Read the MBR */
570 if (!DiskReadLogicalSectors(DriveNumber, 0ULL, 1, (PVOID)DISKREADBUFFER))
571 {
572 DbgPrint((DPRINT_HWDETECT, "Reading MBR failed\n"));
573 return;
574 }
575
576 Buffer = (U32*)DISKREADBUFFER;
577 Mbr = (PMASTER_BOOT_RECORD)DISKREADBUFFER;
578
579 Signature = Mbr->Signature;
580 DbgPrint((DPRINT_HWDETECT, "Signature: %x\n", Signature));
581
582 /* Calculate the MBR checksum */
583 Checksum = 0;
584 for (i = 0; i < 128; i++)
585 {
586 Checksum += Buffer[i];
587 }
588 Checksum = ~Checksum + 1;
589 DbgPrint((DPRINT_HWDETECT, "Checksum: %x\n", Checksum));
590
591 /* Convert checksum and signature to identifier string */
592 Identifier[0] = Hex[(Checksum >> 28) & 0x0F];
593 Identifier[1] = Hex[(Checksum >> 24) & 0x0F];
594 Identifier[2] = Hex[(Checksum >> 20) & 0x0F];
595 Identifier[3] = Hex[(Checksum >> 16) & 0x0F];
596 Identifier[4] = Hex[(Checksum >> 12) & 0x0F];
597 Identifier[5] = Hex[(Checksum >> 8) & 0x0F];
598 Identifier[6] = Hex[(Checksum >> 4) & 0x0F];
599 Identifier[7] = Hex[Checksum & 0x0F];
600 Identifier[8] = '-';
601 Identifier[9] = Hex[(Signature >> 28) & 0x0F];
602 Identifier[10] = Hex[(Signature >> 24) & 0x0F];
603 Identifier[11] = Hex[(Signature >> 20) & 0x0F];
604 Identifier[12] = Hex[(Signature >> 16) & 0x0F];
605 Identifier[13] = Hex[(Signature >> 12) & 0x0F];
606 Identifier[14] = Hex[(Signature >> 8) & 0x0F];
607 Identifier[15] = Hex[(Signature >> 4) & 0x0F];
608 Identifier[16] = Hex[Signature & 0x0F];
609 Identifier[17] = '-';
610 Identifier[18] = 'A';
611 Identifier[19] = 0;
612 DbgPrint((DPRINT_HWDETECT, "Identifier: %xsn", Identifier));
613
614 /* Set identifier */
615 Error = RegSetValue(DiskKey,
616 "Identifier",
617 REG_SZ,
618 (PU8) Identifier,
619 20);
620 if (Error != ERROR_SUCCESS)
621 {
622 DbgPrint((DPRINT_HWDETECT,
623 "RegSetValue(Identifier) failed (Error %u)\n",
624 (int)Error));
625 }
626 }
627
628
629 static VOID
630 DetectBiosDisks(HKEY SystemKey,
631 HKEY BusKey)
632 {
633 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
634 PCM_INT13_DRIVE_PARAMETER Int13Drives;
635 GEOMETRY Geometry;
636 CHAR Buffer[80];
637 HKEY DiskKey;
638 U32 DiskCount;
639 U32 Size;
640 U32 i;
641 S32 Error;
642
643 /* Count the number of visible drives */
644 DiskReportError(FALSE);
645 DiskCount = 0;
646 while (DiskReadLogicalSectors(0x80 + DiskCount, 0ULL, 1, (PVOID)DISKREADBUFFER))
647 {
648 DiskCount++;
649 }
650 DiskReportError(TRUE);
651 DbgPrint((DPRINT_HWDETECT, "BIOS reports %d harddisk%s\n",
652 (int)DiskCount, (DiskCount == 1) ? "": "s"));
653
654 /* Allocate resource descriptor */
655 Size = sizeof(CM_FULL_RESOURCE_DESCRIPTOR) +
656 sizeof(CM_INT13_DRIVE_PARAMETER) * DiskCount;
657 FullResourceDescriptor = MmAllocateMemory(Size);
658 if (FullResourceDescriptor == NULL)
659 {
660 DbgPrint((DPRINT_HWDETECT,
661 "Failed to allocate resource descriptor\n"));
662 return;
663 }
664
665 /* Initialize resource descriptor */
666 memset(FullResourceDescriptor, 0, Size);
667 FullResourceDescriptor->InterfaceType = InterfaceTypeUndefined;
668 FullResourceDescriptor->BusNumber = -1;
669 FullResourceDescriptor->PartialResourceList.Count = 1;
670 FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].Type =
671 CmResourceTypeDeviceSpecific;
672 // FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].ShareDisposition =
673 // FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].Flags =
674 FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].u.DeviceSpecificData.DataSize =
675 sizeof(CM_INT13_DRIVE_PARAMETER) * DiskCount;
676
677 /* Get harddisk Int13 geometry data */
678 Int13Drives = ((PVOID)FullResourceDescriptor) + sizeof(CM_FULL_RESOURCE_DESCRIPTOR);
679 for (i = 0; i < DiskCount; i++)
680 {
681 if (DiskGetDriveParameters(0x80 + i, &Geometry))
682 {
683 Int13Drives[i].DriveSelect = 0x80 + i;
684 Int13Drives[i].MaxCylinders = Geometry.Cylinders - 1;
685 Int13Drives[i].SectorsPerTrack = Geometry.Sectors;
686 Int13Drives[i].MaxHeads = Geometry.Heads - 1;
687 Int13Drives[i].NumberDrives = DiskCount;
688
689 DbgPrint((DPRINT_HWDETECT,
690 "Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n",
691 0x80 + i,
692 Geometry.Cylinders - 1,
693 Geometry.Heads -1,
694 Geometry.Sectors,
695 Geometry.BytesPerSector));
696 }
697 }
698
699 /* Set 'Configuration Data' value */
700 Error = RegSetValue(SystemKey,
701 "Configuration Data",
702 REG_FULL_RESOURCE_DESCRIPTOR,
703 (PU8) FullResourceDescriptor,
704 Size);
705 MmFreeMemory(FullResourceDescriptor);
706 if (Error != ERROR_SUCCESS)
707 {
708 DbgPrint((DPRINT_HWDETECT,
709 "RegSetValue(Configuration Data) failed (Error %u)\n",
710 (int)Error));
711 return;
712 }
713
714 /* Create and fill subkey for each harddisk */
715 for (i = 0; i < DiskCount; i++)
716 {
717 /* Create disk key */
718 sprintf (Buffer,
719 "DiskController\\0\\DiskPeripheral\\%u",
720 i);
721
722 Error = RegCreateKey(BusKey,
723 Buffer,
724 &DiskKey);
725 if (Error != ERROR_SUCCESS)
726 {
727 DbgPrint((DPRINT_HWDETECT, "Failed to create drive key\n"));
728 continue;
729 }
730 DbgPrint((DPRINT_HWDETECT, "Created key: %s\n", Buffer));
731
732 /* Set disk values */
733 SetHarddiskConfigurationData(DiskKey, 0x80 + i);
734 SetHarddiskIdentifier(DiskKey, 0x80 + i);
735 }
736 }
737
738
739 static U32
740 GetFloppyCount(VOID)
741 {
742 U8 Data;
743
744 WRITE_PORT_UCHAR((PUCHAR)0x70, 0x10);
745 Data = READ_PORT_UCHAR((PUCHAR)0x71);
746
747 return ((Data & 0xF0) ? 1 : 0) + ((Data & 0x0F) ? 1 : 0);
748 }
749
750
751 static U8
752 GetFloppyType(U8 DriveNumber)
753 {
754 U8 Data;
755
756 WRITE_PORT_UCHAR((PUCHAR)0x70, 0x10);
757 Data = READ_PORT_UCHAR((PUCHAR)0x71);
758
759 if (DriveNumber == 0)
760 return Data >> 4;
761 else if (DriveNumber == 1)
762 return Data & 0x0F;
763
764 return 0;
765 }
766
767
768 static PVOID
769 GetInt1eTable(VOID)
770 {
771 PU16 SegPtr = (PU16)0x7A;
772 PU16 OfsPtr = (PU16)0x78;
773
774 return (PVOID)(((U32)(*SegPtr)) << 4) + (U32)(*OfsPtr);
775 }
776
777
778 static VOID
779 DetectBiosFloppyPeripheral(HKEY ControllerKey)
780 {
781 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
782 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
783 PCM_FLOPPY_DEVICE_DATA FloppyData;
784 char KeyName[32];
785 char Identifier[20];
786 HKEY PeripheralKey;
787 U32 Size;
788 S32 Error;
789 U32 FloppyNumber;
790 U8 FloppyType;
791 U32 MaxDensity[6] = {0, 360, 1200, 720, 1440, 2880};
792 PU8 Ptr;
793
794 for (FloppyNumber = 0; FloppyNumber < 2; FloppyNumber++)
795 {
796 FloppyType = GetFloppyType(FloppyNumber);
797
798 if ((FloppyType > 5) || (FloppyType == 0))
799 continue;
800
801 DiskResetController(FloppyNumber);
802
803 Ptr = GetInt1eTable();
804
805 sprintf(KeyName, "FloppyDiskPeripheral\\%u", FloppyNumber);
806
807 Error = RegCreateKey(ControllerKey,
808 "FloppyDiskPeripheral\\0",
809 &PeripheralKey);
810 if (Error != ERROR_SUCCESS)
811 {
812 DbgPrint((DPRINT_HWDETECT, "Failed to create peripheral key\n"));
813 return;
814 }
815
816 DbgPrint((DPRINT_HWDETECT, "Created key: %s\n", KeyName));
817
818 /* Set 'ComponentInformation' value */
819 SetComponentInformation(PeripheralKey,
820 0x0,
821 FloppyNumber,
822 0xFFFFFFFF);
823
824 Size = sizeof(CM_FULL_RESOURCE_DESCRIPTOR) +
825 sizeof(CM_FLOPPY_DEVICE_DATA);
826 FullResourceDescriptor = MmAllocateMemory(Size);
827 if (FullResourceDescriptor == NULL)
828 {
829 DbgPrint((DPRINT_HWDETECT,
830 "Failed to allocate resource descriptor\n"));
831 return;
832 }
833
834 memset(FullResourceDescriptor, 0, Size);
835 FullResourceDescriptor->InterfaceType = Isa;
836 FullResourceDescriptor->BusNumber = 0;
837 FullResourceDescriptor->PartialResourceList.Count = 1;
838
839 PartialDescriptor = &FullResourceDescriptor->PartialResourceList.PartialDescriptors[0];
840 PartialDescriptor->Type = CmResourceTypeDeviceSpecific;
841 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
842 PartialDescriptor->u.DeviceSpecificData.DataSize = sizeof(CM_FLOPPY_DEVICE_DATA);
843
844 FloppyData = ((PVOID)FullResourceDescriptor) + sizeof(CM_FULL_RESOURCE_DESCRIPTOR);
845 FloppyData->Version = 2;
846 FloppyData->Revision = 0;
847 FloppyData->MaxDensity = MaxDensity[FloppyType];
848 FloppyData->MountDensity = 0;
849 RtlCopyMemory(&FloppyData->StepRateHeadUnloadTime,
850 Ptr,
851 11);
852 FloppyData->MaximumTrackValue = (FloppyType == 1) ? 39 : 79;
853 FloppyData->DataTransferRate = 0;
854
855 /* Set 'Configuration Data' value */
856 Error = RegSetValue(PeripheralKey,
857 "Configuration Data",
858 REG_FULL_RESOURCE_DESCRIPTOR,
859 (PU8) FullResourceDescriptor,
860 Size);
861 MmFreeMemory(FullResourceDescriptor);
862 if (Error != ERROR_SUCCESS)
863 {
864 DbgPrint((DPRINT_HWDETECT,
865 "RegSetValue(Configuration Data) failed (Error %u)\n",
866 (int)Error));
867 return;
868 }
869
870 /* Set 'Identifier' value */
871 sprintf(Identifier, "FLOPPY%u", FloppyNumber + 1);
872 Error = RegSetValue(PeripheralKey,
873 "Identifier",
874 REG_SZ,
875 (PU8)Identifier,
876 strlen(Identifier) + 1);
877 if (Error != ERROR_SUCCESS)
878 {
879 DbgPrint((DPRINT_HWDETECT,
880 "RegSetValue() failed (Error %u)\n",
881 (int)Error));
882 }
883 }
884 }
885
886
887 static VOID
888 DetectBiosFloppyController(HKEY SystemKey,
889 HKEY BusKey)
890 {
891 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
892 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
893 HKEY ControllerKey;
894 U32 Size;
895 S32 Error;
896 U32 FloppyCount;
897
898 FloppyCount = GetFloppyCount();
899 DbgPrint((DPRINT_HWDETECT,
900 "Floppy count: %u\n",
901 FloppyCount));
902
903 if (FloppyCount == 0)
904 return;
905
906 Error = RegCreateKey(BusKey,
907 "DiskController\\0",
908 &ControllerKey);
909 if (Error != ERROR_SUCCESS)
910 {
911 DbgPrint((DPRINT_HWDETECT, "Failed to create controller key\n"));
912 return;
913 }
914
915 DbgPrint((DPRINT_HWDETECT, "Created key: DiskController\\0\n"));
916
917 /* Set 'ComponentInformation' value */
918 SetComponentInformation(ControllerKey,
919 0x64,
920 0,
921 0xFFFFFFFF);
922
923 Size = sizeof(CM_FULL_RESOURCE_DESCRIPTOR) +
924 2 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
925 FullResourceDescriptor = MmAllocateMemory(Size);
926 if (FullResourceDescriptor == NULL)
927 {
928 DbgPrint((DPRINT_HWDETECT,
929 "Failed to allocate resource descriptor\n"));
930 return;
931 }
932 memset(FullResourceDescriptor, 0, Size);
933
934 /* Initialize resource descriptor */
935 FullResourceDescriptor->InterfaceType = Isa;
936 FullResourceDescriptor->BusNumber = 0;
937 FullResourceDescriptor->PartialResourceList.Count = 3;
938
939 /* Set IO Port */
940 PartialDescriptor = &FullResourceDescriptor->PartialResourceList.PartialDescriptors[0];
941 PartialDescriptor->Type = CmResourceTypePort;
942 PartialDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
943 PartialDescriptor->Flags = CM_RESOURCE_PORT_IO;
944 PartialDescriptor->u.Port.Start = (U64)0x03F0;
945 PartialDescriptor->u.Port.Length = 8;
946
947 /* Set Interrupt */
948 PartialDescriptor = &FullResourceDescriptor->PartialResourceList.PartialDescriptors[1];
949 PartialDescriptor->Type = CmResourceTypeInterrupt;
950 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
951 PartialDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
952 PartialDescriptor->u.Interrupt.Level = 6;
953 PartialDescriptor->u.Interrupt.Vector = 6;
954 PartialDescriptor->u.Interrupt.Affinity = 0xFFFFFFFF;
955
956 /* Set DMA channel */
957 PartialDescriptor = &FullResourceDescriptor->PartialResourceList.PartialDescriptors[2];
958 PartialDescriptor->Type = CmResourceTypeDma;
959 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
960 PartialDescriptor->Flags = 0;
961 PartialDescriptor->u.Dma.Channel = 2;
962 PartialDescriptor->u.Dma.Port = 0;
963
964 /* Set 'Configuration Data' value */
965 Error = RegSetValue(ControllerKey,
966 "Configuration Data",
967 REG_FULL_RESOURCE_DESCRIPTOR,
968 (PU8) FullResourceDescriptor,
969 Size);
970 MmFreeMemory(FullResourceDescriptor);
971 if (Error != ERROR_SUCCESS)
972 {
973 DbgPrint((DPRINT_HWDETECT,
974 "RegSetValue(Configuration Data) failed (Error %u)\n",
975 (int)Error));
976 return;
977 }
978
979 DetectBiosFloppyPeripheral(ControllerKey);
980 }
981
982
983 static VOID
984 InitializeSerialPort(U32 Port,
985 U32 LineControl)
986 {
987 WRITE_PORT_UCHAR((PUCHAR)Port + 3, 0x80); /* set DLAB on */
988 WRITE_PORT_UCHAR((PUCHAR)Port, 0x60); /* speed LO byte */
989 WRITE_PORT_UCHAR((PUCHAR)Port + 1, 0); /* speed HI byte */
990 WRITE_PORT_UCHAR((PUCHAR)Port + 3, LineControl);
991 WRITE_PORT_UCHAR((PUCHAR)Port + 1, 0); /* set comm and DLAB to 0 */
992 WRITE_PORT_UCHAR((PUCHAR)Port + 4, 0x09); /* DR int enable */
993 READ_PORT_UCHAR((PUCHAR)Port + 5); /* clear error bits */
994 }
995
996
997 static U32
998 DetectSerialMouse(U32 Port)
999 {
1000 CHAR Buffer[4];
1001 U32 i;
1002 U32 TimeOut = 200;
1003 U8 LineControl;
1004
1005 /* Shutdown mouse or something like that */
1006 LineControl = READ_PORT_UCHAR((PUCHAR)Port + 4);
1007 WRITE_PORT_UCHAR((PUCHAR)Port + 4, (LineControl & ~0x02) | 0x01);
1008 KeStallExecutionProcessor(100000);
1009
1010 /* Clear buffer */
1011 while (READ_PORT_UCHAR((PUCHAR)Port + 5) & 0x01)
1012 READ_PORT_UCHAR((PUCHAR)Port);
1013
1014 /*
1015 * Send modem control with 'Data Terminal Ready', 'Request To Send' and
1016 * 'Output Line 2' message. This enables mouse to identify.
1017 */
1018 WRITE_PORT_UCHAR((PUCHAR)Port + 4, 0x0b);
1019
1020 /* Wait 10 milliseconds for the mouse getting ready */
1021 KeStallExecutionProcessor(10000);
1022
1023 /* Read first four bytes, which contains Microsoft Mouse signs */
1024 for (i = 0; i < 4; i++)
1025 {
1026 while (((READ_PORT_UCHAR((PUCHAR)Port + 5) & 1) == 0) && (TimeOut > 0))
1027 {
1028 KeStallExecutionProcessor(1000);
1029 --TimeOut;
1030 if (TimeOut == 0)
1031 return MOUSE_TYPE_NONE;
1032 }
1033 Buffer[i] = READ_PORT_UCHAR((PUCHAR)Port);
1034 }
1035
1036 DbgPrint((DPRINT_HWDETECT,
1037 "Mouse data: %x %x %x %x\n",
1038 Buffer[0],Buffer[1],Buffer[2],Buffer[3]));
1039
1040 /* Check that four bytes for signs */
1041 for (i = 0; i < 4; ++i)
1042 {
1043 if (Buffer[i] == 'B')
1044 {
1045 /* Sign for Microsoft Ballpoint */
1046 // DbgPrint("Microsoft Ballpoint device detected\n");
1047 // DbgPrint("THIS DEVICE IS NOT SUPPORTED, YET\n");
1048 return MOUSE_TYPE_NONE;
1049 }
1050 else if (Buffer[i] == 'M')
1051 {
1052 /* Sign for Microsoft Mouse protocol followed by button specifier */
1053 if (i == 3)
1054 {
1055 /* Overflow Error */
1056 return MOUSE_TYPE_NONE;
1057 }
1058
1059 switch (Buffer[i + 1])
1060 {
1061 case '3':
1062 DbgPrint((DPRINT_HWDETECT,
1063 "Microsoft Mouse with 3-buttons detected\n"));
1064 return MOUSE_TYPE_LOGITECH;
1065
1066 case 'Z':
1067 DbgPrint((DPRINT_HWDETECT,
1068 "Microsoft Wheel Mouse detected\n"));
1069 return MOUSE_TYPE_WHEELZ;
1070
1071 /* case '2': */
1072 default:
1073 DbgPrint((DPRINT_HWDETECT,
1074 "Microsoft Mouse with 2-buttons detected\n"));
1075 return MOUSE_TYPE_MICROSOFT;
1076 }
1077 }
1078 }
1079
1080 return MOUSE_TYPE_NONE;
1081 }
1082
1083
1084 static U32
1085 GetSerialMousePnpId(U32 Port, char *Buffer)
1086 {
1087 U32 TimeOut;
1088 U32 i = 0;
1089 char c;
1090 char x;
1091
1092 WRITE_PORT_UCHAR((PUCHAR)Port + 4, 0x09);
1093
1094 /* Wait 10 milliseconds for the mouse getting ready */
1095 KeStallExecutionProcessor(10000);
1096
1097 WRITE_PORT_UCHAR((PUCHAR)Port + 4, 0x0b);
1098
1099 KeStallExecutionProcessor(10000);
1100
1101 for (;;)
1102 {
1103 TimeOut = 200;
1104 while (((READ_PORT_UCHAR((PUCHAR)Port + 5) & 1) == 0) && (TimeOut > 0))
1105 {
1106 KeStallExecutionProcessor(1000);
1107 --TimeOut;
1108 if (TimeOut == 0)
1109 {
1110 return 0;
1111 }
1112 }
1113
1114 c = READ_PORT_UCHAR((PUCHAR)Port);
1115 if (c == 0x08 || c == 0x28)
1116 break;
1117 }
1118
1119 Buffer[i++] = c;
1120 x = c + 1;
1121
1122 for (;;)
1123 {
1124 TimeOut = 200;
1125 while (((READ_PORT_UCHAR((PUCHAR)Port + 5) & 1) == 0) && (TimeOut > 0))
1126 {
1127 KeStallExecutionProcessor(1000);
1128 --TimeOut;
1129 if (TimeOut == 0)
1130 return 0;
1131 }
1132 c = READ_PORT_UCHAR((PUCHAR)Port);
1133 Buffer[i++] = c;
1134 if (c == x)
1135 break;
1136 if (i >= 256)
1137 break;
1138 }
1139
1140 return i;
1141 }
1142
1143
1144 static VOID
1145 DetectSerialPointerPeripheral(HKEY ControllerKey,
1146 U32 Base)
1147 {
1148 CM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
1149 char Buffer[256];
1150 char Identifier[256];
1151 HKEY PeripheralKey;
1152 U32 MouseType;
1153 U32 Length;
1154 U32 i;
1155 U32 j;
1156 S32 Error;
1157
1158 DbgPrint((DPRINT_HWDETECT,
1159 "DetectSerialPointerPeripheral()\n"));
1160
1161 Identifier[0] = 0;
1162
1163 InitializeSerialPort(Base, 2);
1164 MouseType = DetectSerialMouse(Base);
1165
1166 if (MouseType != MOUSE_TYPE_NONE)
1167 {
1168 Length = GetSerialMousePnpId(Base, Buffer);
1169 DbgPrint((DPRINT_HWDETECT,
1170 "PnP ID length: %u\n",
1171 Length));
1172
1173 if (Length != 0)
1174 {
1175 /* Convert PnP sting to ASCII */
1176 if (Buffer[0] == 0x08)
1177 {
1178 for (i = 0; i < Length; i++)
1179 Buffer[i] += 0x20;
1180 }
1181 Buffer[Length] = 0;
1182
1183 DbgPrint((DPRINT_HWDETECT,
1184 "PnP ID string: %s\n",
1185 Buffer));
1186
1187 /* Copy PnpId string */
1188 memcpy(&Identifier[0],
1189 &Buffer[3],
1190 7);
1191 memcpy(&Identifier[7],
1192 " - ",
1193 4);
1194
1195 /* Skip device serial number */
1196 i = 10;
1197 if (Buffer[i] == '\\')
1198 {
1199 for (j = ++i; i < Length; ++i)
1200 {
1201 if (Buffer[i] == '\\')
1202 break;
1203 }
1204 if (i >= Length)
1205 i -= 3;
1206 }
1207
1208 /* Skip PnP class */
1209 if (Buffer[i] == '\\')
1210 {
1211 for (j = ++i; i < Length; ++i)
1212 {
1213 if (Buffer[i] == '\\')
1214 break;
1215 }
1216
1217 if (i >= Length)
1218 i -= 3;
1219 }
1220
1221 /* Skip compatible PnP Id */
1222 if (Buffer[i] == '\\')
1223 {
1224 for (j = ++i; i < Length; ++i)
1225 {
1226 if (Buffer[i] == '\\')
1227 break;
1228 }
1229 if (Buffer[j] == '*')
1230 ++j;
1231 if (i >= Length)
1232 i -= 3;
1233 }
1234
1235 /* Get product description */
1236 if (Buffer[i] == '\\')
1237 {
1238 for (j = ++i; i < Length; ++i)
1239 {
1240 if (Buffer[i] == ';')
1241 break;
1242 }
1243 if (i >= Length)
1244 i -= 3;
1245 if (i > j + 1)
1246 {
1247 memcpy(&Identifier[10],
1248 &Buffer[j],
1249 i - j);
1250 Identifier[10 + (i-j)] = 0;
1251 }
1252 }
1253
1254 DbgPrint((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 /* Create 'PointerPeripheral' key */
1282 Error = RegCreateKey(ControllerKey,
1283 "PointerPeripheral\\0",
1284 &PeripheralKey);
1285 if (Error != ERROR_SUCCESS)
1286 {
1287 DbgPrint((DPRINT_HWDETECT,
1288 "Failed to create peripheral key\n"));
1289 return;
1290 }
1291 DbgPrint((DPRINT_HWDETECT,
1292 "Created key: PointerPeripheral\\0\n"));
1293
1294 /* Set 'ComponentInformation' value */
1295 SetComponentInformation(PeripheralKey,
1296 0x20,
1297 0,
1298 0xFFFFFFFF);
1299
1300 /* Set 'Configuration Data' value */
1301 memset(&FullResourceDescriptor, 0, sizeof(CM_FULL_RESOURCE_DESCRIPTOR));
1302 FullResourceDescriptor.InterfaceType = Isa;
1303 FullResourceDescriptor.BusNumber = 0;
1304 FullResourceDescriptor.PartialResourceList.Count = 0;
1305
1306 Error = RegSetValue(PeripheralKey,
1307 "Configuration Data",
1308 REG_FULL_RESOURCE_DESCRIPTOR,
1309 (PU8)&FullResourceDescriptor,
1310 sizeof(CM_FULL_RESOURCE_DESCRIPTOR) -
1311 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
1312 if (Error != ERROR_SUCCESS)
1313 {
1314 DbgPrint((DPRINT_HWDETECT,
1315 "RegSetValue(Configuration Data) failed (Error %u)\n",
1316 (int)Error));
1317 }
1318
1319 /* Set 'Identifier' value */
1320 Error = RegSetValue(PeripheralKey,
1321 "Identifier",
1322 REG_SZ,
1323 (PU8)Identifier,
1324 strlen(Identifier) + 1);
1325 if (Error != ERROR_SUCCESS)
1326 {
1327 DbgPrint((DPRINT_HWDETECT,
1328 "RegSetValue() failed (Error %u)\n",
1329 (int)Error));
1330 }
1331 }
1332 }
1333
1334
1335 static VOID
1336 DetectSerialPorts(HKEY BusKey)
1337 {
1338 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
1339 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
1340 PCM_SERIAL_DEVICE_DATA SerialDeviceData;
1341 U32 Base[4] = {0x3F8, 0x2F8, 0x3E8, 0x2E8};
1342 U32 Irq[4] = {4, 3, 4, 3};
1343 char Buffer[80];
1344 U32 ControllerNumber = 0;
1345 HKEY ControllerKey;
1346 U32 i;
1347 S32 Error;
1348 U32 Size;
1349
1350 DbgPrint((DPRINT_HWDETECT, "DetectSerialPorts()\n"));
1351
1352 for (i = 0; i < 4; i++)
1353 {
1354 WRITE_PORT_UCHAR ((PUCHAR)(Base[i] + 4), 0x10);
1355 if (!(READ_PORT_UCHAR((PUCHAR)Base[i] + 6) & 0xf0))
1356 {
1357 DbgPrint((DPRINT_HWDETECT,
1358 "Found COM%u port at 0x%x\n",
1359 i + 1,
1360 Base[i]));
1361
1362 /* Create controller key */
1363 sprintf(Buffer,
1364 "SerialController\\%u",
1365 ControllerNumber);
1366
1367 Error = RegCreateKey(BusKey,
1368 Buffer,
1369 &ControllerKey);
1370 if (Error != ERROR_SUCCESS)
1371 {
1372 DbgPrint((DPRINT_HWDETECT, "Failed to create controller key\n"));
1373 continue;
1374 }
1375 DbgPrint((DPRINT_HWDETECT, "Created key: %s\n", Buffer));
1376
1377 /* Set 'ComponentInformation' value */
1378 SetComponentInformation(ControllerKey,
1379 0x78,
1380 ControllerNumber,
1381 0xFFFFFFFF);
1382
1383 /* Build full device descriptor */
1384 Size = sizeof(CM_FULL_RESOURCE_DESCRIPTOR) +
1385 2 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) +
1386 sizeof(CM_SERIAL_DEVICE_DATA);
1387 FullResourceDescriptor = MmAllocateMemory(Size);
1388 if (FullResourceDescriptor == NULL)
1389 {
1390 DbgPrint((DPRINT_HWDETECT,
1391 "Failed to allocate resource descriptor\n"));
1392 continue;
1393 }
1394 memset(FullResourceDescriptor, 0, Size);
1395
1396 /* Initialize resource descriptor */
1397 FullResourceDescriptor->InterfaceType = Isa;
1398 FullResourceDescriptor->BusNumber = 0;
1399 FullResourceDescriptor->PartialResourceList.Count = 3;
1400
1401 /* Set IO Port */
1402 PartialDescriptor = &FullResourceDescriptor->PartialResourceList.PartialDescriptors[0];
1403 PartialDescriptor->Type = CmResourceTypePort;
1404 PartialDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1405 PartialDescriptor->Flags = CM_RESOURCE_PORT_IO;
1406 PartialDescriptor->u.Port.Start = (U64)Base[i];
1407 PartialDescriptor->u.Port.Length = 7;
1408
1409 /* Set Interrupt */
1410 PartialDescriptor = &FullResourceDescriptor->PartialResourceList.PartialDescriptors[1];
1411 PartialDescriptor->Type = CmResourceTypeInterrupt;
1412 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
1413 PartialDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
1414 PartialDescriptor->u.Interrupt.Level = Irq[i];
1415 PartialDescriptor->u.Interrupt.Vector = Irq[i];
1416 PartialDescriptor->u.Interrupt.Affinity = 0xFFFFFFFF;
1417
1418 /* Set serial data (device specific) */
1419 PartialDescriptor = &FullResourceDescriptor->PartialResourceList.PartialDescriptors[2];
1420 PartialDescriptor->Type = CmResourceTypeDeviceSpecific;
1421 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
1422 PartialDescriptor->Flags = 0;
1423 PartialDescriptor->u.DeviceSpecificData.DataSize = sizeof(CM_SERIAL_DEVICE_DATA);
1424
1425 SerialDeviceData =
1426 (PCM_SERIAL_DEVICE_DATA)&FullResourceDescriptor->PartialResourceList.PartialDescriptors[3];
1427 SerialDeviceData->BaudClock = 1843200; /* UART Clock frequency (Hertz) */
1428
1429 /* Set 'Configuration Data' value */
1430 Error = RegSetValue(ControllerKey,
1431 "Configuration Data",
1432 REG_FULL_RESOURCE_DESCRIPTOR,
1433 (PU8) FullResourceDescriptor,
1434 Size);
1435 MmFreeMemory(FullResourceDescriptor);
1436 if (Error != ERROR_SUCCESS)
1437 {
1438 DbgPrint((DPRINT_HWDETECT,
1439 "RegSetValue(Configuration Data) failed (Error %u)\n",
1440 (int)Error));
1441 }
1442
1443 /* Set 'Identifier' value */
1444 sprintf(Buffer,
1445 "COM%u",
1446 i + 1);
1447 Error = RegSetValue(ControllerKey,
1448 "Identifier",
1449 REG_SZ,
1450 (PU8)Buffer,
1451 5);
1452 if (Error != ERROR_SUCCESS)
1453 {
1454 DbgPrint((DPRINT_HWDETECT,
1455 "RegSetValue() failed (Error %u)\n",
1456 (int)Error));
1457 continue;
1458 }
1459 DbgPrint((DPRINT_HWDETECT,
1460 "Created value: Identifier %s\n",
1461 Buffer));
1462
1463 /* Detect serial mouse */
1464 DetectSerialPointerPeripheral(ControllerKey, Base[i]);
1465
1466 ControllerNumber++;
1467 }
1468 }
1469 }
1470
1471
1472 static BOOLEAN
1473 DetectKeyboardDevice(VOID)
1474 {
1475 UCHAR Status;
1476 UCHAR Scancode;
1477
1478 WRITE_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA,
1479 0xF2);
1480
1481 KeStallExecutionProcessor(10000);
1482
1483 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
1484 if ((Status & 0x01) != 0x01)
1485 {
1486 /* PC/XT keyboard or no keyboard */
1487 return FALSE;
1488 }
1489
1490 Scancode = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA);
1491 if (Scancode != 0xFA)
1492 {
1493 /* No ACK received */
1494 return FALSE;
1495 }
1496
1497 KeStallExecutionProcessor(10000);
1498 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
1499 if ((Status & 0x01) != 0x01)
1500 {
1501 /* Found AT keyboard */
1502 return TRUE;
1503 }
1504
1505 Scancode = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA);
1506 if (Scancode != 0xAB)
1507 {
1508 /* No 0xAB received */
1509 return FALSE;
1510 }
1511
1512 KeStallExecutionProcessor(10000);
1513 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
1514 if ((Status & 0x01) != 0x01)
1515 {
1516 /* No byte in buffer */
1517 return FALSE;
1518 }
1519
1520 Scancode = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA);
1521 if (Scancode != 0x41)
1522 {
1523 /* No 0x41 received */
1524 return FALSE;
1525 }
1526
1527 /* Found MF-II keyboard */
1528 return TRUE;
1529 }
1530
1531
1532 static VOID
1533 DetectKeyboardPeripheral(HKEY ControllerKey)
1534 {
1535 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
1536 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
1537 PCM_KEYBOARD_DEVICE_DATA KeyboardData;
1538 HKEY PeripheralKey;
1539 char Buffer[80];
1540 U32 Size;
1541 S32 Error;
1542
1543 if (DetectKeyboardDevice())
1544 {
1545 /* Create controller key */
1546 Error = RegCreateKey(ControllerKey,
1547 "KeyboardPeripheral\\0",
1548 &PeripheralKey);
1549 if (Error != ERROR_SUCCESS)
1550 {
1551 DbgPrint((DPRINT_HWDETECT, "Failed to create peripheral key\n"));
1552 return;
1553 }
1554 DbgPrint((DPRINT_HWDETECT, "Created key: KeyboardPeripheral\\0\n"));
1555
1556 /* Set 'ComponentInformation' value */
1557 SetComponentInformation(ControllerKey,
1558 0x28,
1559 0,
1560 0xFFFFFFFF);
1561
1562 /* Set 'Configuration Data' value */
1563 Size = sizeof(CM_FULL_RESOURCE_DESCRIPTOR) +
1564 sizeof(CM_KEYBOARD_DEVICE_DATA);
1565 FullResourceDescriptor = MmAllocateMemory(Size);
1566 if (FullResourceDescriptor == NULL)
1567 {
1568 DbgPrint((DPRINT_HWDETECT,
1569 "Failed to allocate resource descriptor\n"));
1570 return;
1571 }
1572
1573 /* Initialize resource descriptor */
1574 memset(FullResourceDescriptor, 0, Size);
1575 FullResourceDescriptor->InterfaceType = Isa;
1576 FullResourceDescriptor->BusNumber = 0;
1577 FullResourceDescriptor->PartialResourceList.Count = 1;
1578
1579 PartialDescriptor = &FullResourceDescriptor->PartialResourceList.PartialDescriptors[0];
1580 PartialDescriptor->Type = CmResourceTypeDeviceSpecific;
1581 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
1582 PartialDescriptor->u.DeviceSpecificData.DataSize = sizeof(CM_KEYBOARD_DEVICE_DATA);
1583
1584 KeyboardData = ((PVOID)FullResourceDescriptor) + sizeof(CM_FULL_RESOURCE_DESCRIPTOR);
1585 KeyboardData->Version = 0;
1586 KeyboardData->Revision = 0;
1587 KeyboardData->Type = 4;
1588 KeyboardData->Subtype = 0;
1589 KeyboardData->KeyboardFlags = 0x20;
1590
1591 /* Set 'Configuration Data' value */
1592 Error = RegSetValue(PeripheralKey,
1593 "Configuration Data",
1594 REG_FULL_RESOURCE_DESCRIPTOR,
1595 (PU8)FullResourceDescriptor,
1596 Size);
1597 MmFreeMemory(FullResourceDescriptor);
1598 if (Error != ERROR_SUCCESS)
1599 {
1600 DbgPrint((DPRINT_HWDETECT,
1601 "RegSetValue(Configuration Data) failed (Error %u)\n",
1602 (int)Error));
1603 }
1604
1605 /* Set 'Identifier' value */
1606 strcpy(Buffer,
1607 "PCAT_ENHANCED");
1608 Error = RegSetValue(ControllerKey,
1609 "Identifier",
1610 REG_SZ,
1611 (PU8)Buffer,
1612 strlen(Buffer) + 1);
1613 if (Error != ERROR_SUCCESS)
1614 {
1615 DbgPrint((DPRINT_HWDETECT,
1616 "RegSetValue() failed (Error %u)\n",
1617 (int)Error));
1618 }
1619 }
1620 }
1621
1622
1623 static VOID
1624 DetectKeyboardController(HKEY BusKey)
1625 {
1626 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
1627 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
1628 HKEY ControllerKey;
1629 U32 Size;
1630 S32 Error;
1631
1632 /* Create controller key */
1633 Error = RegCreateKey(BusKey,
1634 "KeyboardController\\0",
1635 &ControllerKey);
1636 if (Error != ERROR_SUCCESS)
1637 {
1638 DbgPrint((DPRINT_HWDETECT, "Failed to create controller key\n"));
1639 return;
1640 }
1641 DbgPrint((DPRINT_HWDETECT, "Created key: KeyboardController\\0\n"));
1642
1643 /* Set 'ComponentInformation' value */
1644 SetComponentInformation(ControllerKey,
1645 0x28,
1646 0,
1647 0xFFFFFFFF);
1648
1649 /* Set 'Configuration Data' value */
1650 Size = sizeof(CM_FULL_RESOURCE_DESCRIPTOR) +
1651 2 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
1652 FullResourceDescriptor = MmAllocateMemory(Size);
1653 if (FullResourceDescriptor == NULL)
1654 {
1655 DbgPrint((DPRINT_HWDETECT,
1656 "Failed to allocate resource descriptor\n"));
1657 return;
1658 }
1659
1660 /* Initialize resource descriptor */
1661 memset(FullResourceDescriptor, 0, Size);
1662 FullResourceDescriptor->InterfaceType = Isa;
1663 FullResourceDescriptor->BusNumber = 0;
1664 FullResourceDescriptor->PartialResourceList.Count = 3;
1665
1666 /* Set Interrupt */
1667 PartialDescriptor = &FullResourceDescriptor->PartialResourceList.PartialDescriptors[0];
1668 PartialDescriptor->Type = CmResourceTypeInterrupt;
1669 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
1670 PartialDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
1671 PartialDescriptor->u.Interrupt.Level = 1;
1672 PartialDescriptor->u.Interrupt.Vector = 1;
1673 PartialDescriptor->u.Interrupt.Affinity = 0xFFFFFFFF;
1674
1675 /* Set IO Port 0x60 */
1676 PartialDescriptor = &FullResourceDescriptor->PartialResourceList.PartialDescriptors[1];
1677 PartialDescriptor->Type = CmResourceTypePort;
1678 PartialDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1679 PartialDescriptor->Flags = CM_RESOURCE_PORT_IO;
1680 PartialDescriptor->u.Port.Start = (U64)0x60;
1681 PartialDescriptor->u.Port.Length = 1;
1682
1683 /* Set IO Port 0x64 */
1684 PartialDescriptor = &FullResourceDescriptor->PartialResourceList.PartialDescriptors[2];
1685 PartialDescriptor->Type = CmResourceTypePort;
1686 PartialDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1687 PartialDescriptor->Flags = CM_RESOURCE_PORT_IO;
1688 PartialDescriptor->u.Port.Start = (U64)0x64;
1689 PartialDescriptor->u.Port.Length = 1;
1690
1691 /* Set 'Configuration Data' value */
1692 Error = RegSetValue(ControllerKey,
1693 "Configuration Data",
1694 REG_FULL_RESOURCE_DESCRIPTOR,
1695 (PU8)FullResourceDescriptor,
1696 Size);
1697 MmFreeMemory(FullResourceDescriptor);
1698 if (Error != ERROR_SUCCESS)
1699 {
1700 DbgPrint((DPRINT_HWDETECT,
1701 "RegSetValue(Configuration Data) failed (Error %u)\n",
1702 (int)Error));
1703 return;
1704 }
1705
1706 DetectKeyboardPeripheral(ControllerKey);
1707 }
1708
1709
1710 static VOID
1711 PS2ControllerWait(VOID)
1712 {
1713 U32 Timeout;
1714 U8 Status;
1715
1716 for (Timeout = 0; Timeout < CONTROLLER_TIMEOUT; Timeout++)
1717 {
1718 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
1719 if ((Status & CONTROLLER_STATUS_INPUT_BUFFER_FULL) == 0)
1720 return;
1721
1722 /* Sleep for one millisecond */
1723 KeStallExecutionProcessor(1000);
1724 }
1725 }
1726
1727
1728 static BOOLEAN
1729 DetectPS2AuxPort(VOID)
1730 {
1731 U32 Loops;
1732 U8 Scancode;
1733 U8 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 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
1754
1755 if ((Status & CONTROLLER_STATUS_OUTPUT_BUFFER_FULL) != 0)
1756 {
1757 Scancode = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA);
1758 if ((Status & CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL) != 0)
1759 {
1760 return TRUE;
1761 }
1762 break;
1763 }
1764
1765 KeStallExecutionProcessor(10000);
1766 }
1767
1768 return FALSE;
1769 }
1770
1771
1772 static BOOLEAN
1773 DetectPS2AuxDevice(VOID)
1774 {
1775 U8 Scancode;
1776 U8 Status;
1777
1778 PS2ControllerWait();
1779 WRITE_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_CONTROL,
1780 CONTROLLER_COMMAND_WRITE_MOUSE);
1781 PS2ControllerWait();
1782
1783 /* Identify device */
1784 WRITE_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA,
1785 0xF2);
1786
1787 KeStallExecutionProcessor(10000);
1788
1789 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
1790 if ((Status & CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL) == 0)
1791 {
1792 return FALSE;
1793 }
1794
1795 Scancode = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA);
1796 if (Scancode != 0xFA)
1797 return FALSE;
1798
1799 KeStallExecutionProcessor(10000);
1800
1801 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
1802 if ((Status & CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL) == 0)
1803 {
1804 return FALSE;
1805 }
1806
1807 Scancode = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA);
1808 if (Scancode != 0x00)
1809 return FALSE;
1810
1811 return TRUE;
1812 }
1813
1814
1815 static VOID
1816 DetectPS2Mouse(HKEY BusKey)
1817 {
1818 CM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
1819 HKEY ControllerKey;
1820 HKEY PeripheralKey;
1821 S32 Error;
1822
1823 if (DetectPS2AuxPort())
1824 {
1825 DbgPrint((DPRINT_HWDETECT, "Detected PS2 port\n"));
1826
1827 /* Create controller key */
1828 Error = RegCreateKey(BusKey,
1829 "PointerController\\0",
1830 &ControllerKey);
1831 if (Error != ERROR_SUCCESS)
1832 {
1833 DbgPrint((DPRINT_HWDETECT, "Failed to create controller key\n"));
1834 return;
1835 }
1836 DbgPrint((DPRINT_HWDETECT, "Created key: PointerController\\0\n"));
1837
1838 /* Set 'ComponentInformation' value */
1839 SetComponentInformation(ControllerKey,
1840 0x20,
1841 0,
1842 0xFFFFFFFF);
1843
1844 memset(&FullResourceDescriptor, 0, sizeof(CM_FULL_RESOURCE_DESCRIPTOR));
1845
1846 /* Initialize resource descriptor */
1847 FullResourceDescriptor.InterfaceType = Isa;
1848 FullResourceDescriptor.BusNumber = 0;
1849 FullResourceDescriptor.PartialResourceList.Count = 1;
1850
1851 /* Set Interrupt */
1852 FullResourceDescriptor.PartialResourceList.PartialDescriptors[0].Type = CmResourceTypeInterrupt;
1853 FullResourceDescriptor.PartialResourceList.PartialDescriptors[0].ShareDisposition = CmResourceShareUndetermined;
1854 FullResourceDescriptor.PartialResourceList.PartialDescriptors[0].Flags = CM_RESOURCE_INTERRUPT_LATCHED;
1855 FullResourceDescriptor.PartialResourceList.PartialDescriptors[0].u.Interrupt.Level = 12;
1856 FullResourceDescriptor.PartialResourceList.PartialDescriptors[0].u.Interrupt.Vector = 12;
1857 FullResourceDescriptor.PartialResourceList.PartialDescriptors[0].u.Interrupt.Affinity = 0xFFFFFFFF;
1858
1859 /* Set 'Configuration Data' value */
1860 Error = RegSetValue(ControllerKey,
1861 "Configuration Data",
1862 REG_FULL_RESOURCE_DESCRIPTOR,
1863 (PU8)&FullResourceDescriptor,
1864 sizeof(CM_FULL_RESOURCE_DESCRIPTOR));
1865 if (Error != ERROR_SUCCESS)
1866 {
1867 DbgPrint((DPRINT_HWDETECT,
1868 "RegSetValue(Configuration Data) failed (Error %u)\n",
1869 (int)Error));
1870 return;
1871 }
1872
1873
1874 if (DetectPS2AuxDevice())
1875 {
1876 DbgPrint((DPRINT_HWDETECT, "Detected PS2 mouse\n"));
1877
1878 /* Create peripheral key */
1879 Error = RegCreateKey(ControllerKey,
1880 "PointerPeripheral\\0",
1881 &PeripheralKey);
1882 if (Error != ERROR_SUCCESS)
1883 {
1884 DbgPrint((DPRINT_HWDETECT, "Failed to create peripheral key\n"));
1885 return;
1886 }
1887 DbgPrint((DPRINT_HWDETECT, "Created key: PointerPeripheral\\0\n"));
1888
1889 /* Set 'ComponentInformation' value */
1890 SetComponentInformation(PeripheralKey,
1891 0x20,
1892 0,
1893 0xFFFFFFFF);
1894
1895 /* Initialize resource descriptor */
1896 memset(&FullResourceDescriptor, 0, sizeof(CM_FULL_RESOURCE_DESCRIPTOR));
1897 FullResourceDescriptor.InterfaceType = Isa;
1898 FullResourceDescriptor.BusNumber = 0;
1899 FullResourceDescriptor.PartialResourceList.Count = 0;
1900
1901 /* Set 'Configuration Data' value */
1902 Error = RegSetValue(PeripheralKey,
1903 "Configuration Data",
1904 REG_FULL_RESOURCE_DESCRIPTOR,
1905 (PU8)&FullResourceDescriptor,
1906 sizeof(CM_FULL_RESOURCE_DESCRIPTOR) -
1907 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
1908 if (Error != ERROR_SUCCESS)
1909 {
1910 DbgPrint((DPRINT_HWDETECT,
1911 "RegSetValue(Configuration Data) failed (Error %u)\n",
1912 (int)Error));
1913 return;
1914 }
1915
1916 /* Set 'Identifier' value */
1917 Error = RegSetValue(PeripheralKey,
1918 "Identifier",
1919 REG_SZ,
1920 (PU8)"MICROSOFT PS2 MOUSE",
1921 20);
1922 if (Error != ERROR_SUCCESS)
1923 {
1924 DbgPrint((DPRINT_HWDETECT,
1925 "RegSetValue() failed (Error %u)\n",
1926 (int)Error));
1927 return;
1928 }
1929 }
1930 }
1931 }
1932
1933
1934 static VOID
1935 DetectDisplayController(HKEY BusKey)
1936 {
1937 CHAR Buffer[80];
1938 HKEY ControllerKey;
1939 U16 VesaVersion;
1940 S32 Error;
1941
1942 Error = RegCreateKey(BusKey,
1943 "DisplayController\\0",
1944 &ControllerKey);
1945 if (Error != ERROR_SUCCESS)
1946 {
1947 DbgPrint((DPRINT_HWDETECT, "Failed to create controller key\n"));
1948 return;
1949 }
1950 DbgPrint((DPRINT_HWDETECT, "Created key: PointerController\\0\n"));
1951
1952 /* Set 'ComponentInformation' value */
1953 SetComponentInformation(ControllerKey,
1954 0x00,
1955 0,
1956 0xFFFFFFFF);
1957
1958 /* FIXME: Set 'ComponentInformation' value */
1959
1960 VesaVersion = BiosIsVesaSupported();
1961 if (VesaVersion != 0)
1962 {
1963 DbgPrint((DPRINT_HWDETECT,
1964 "VESA version %c.%c\n",
1965 (VesaVersion >> 8) + '0',
1966 (VesaVersion & 0xFF) + '0'));
1967 }
1968 else
1969 {
1970 DbgPrint((DPRINT_HWDETECT,
1971 "VESA not supported\n"));
1972 }
1973
1974 if (VesaVersion >= 0x0200)
1975 {
1976 strcpy(Buffer,
1977 "VBE Display");
1978 }
1979 else
1980 {
1981 strcpy(Buffer,
1982 "VGA Display");
1983 }
1984
1985 /* Set 'Identifier' value */
1986 Error = RegSetValue(ControllerKey,
1987 "Identifier",
1988 REG_SZ,
1989 (PU8)Buffer,
1990 strlen(Buffer) + 1);
1991 if (Error != ERROR_SUCCESS)
1992 {
1993 DbgPrint((DPRINT_HWDETECT,
1994 "RegSetValue() failed (Error %u)\n",
1995 (int)Error));
1996 return;
1997 }
1998
1999 /* FIXME: Add display peripheral (monitor) data */
2000 }
2001
2002
2003 static VOID
2004 DetectIsaBios(HKEY SystemKey, U32 *BusNumber)
2005 {
2006 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
2007 char Buffer[80];
2008 HKEY BusKey;
2009 U32 Size;
2010 S32 Error;
2011
2012 /* Create new bus key */
2013 sprintf(Buffer,
2014 "MultifunctionAdapter\\%u", *BusNumber);
2015 Error = RegCreateKey(SystemKey,
2016 Buffer,
2017 &BusKey);
2018 if (Error != ERROR_SUCCESS)
2019 {
2020 DbgPrint((DPRINT_HWDETECT, "RegCreateKey() failed (Error %u)\n", (int)Error));
2021 return;
2022 }
2023
2024 /* Set 'Component Information' value similar to my NT4 box */
2025 SetComponentInformation(BusKey,
2026 0x0,
2027 0x0,
2028 0xFFFFFFFF);
2029
2030 /* Increment bus number */
2031 (*BusNumber)++;
2032
2033 /* Set 'Identifier' value */
2034 Error = RegSetValue(BusKey,
2035 "Identifier",
2036 REG_SZ,
2037 (PU8)"ISA",
2038 4);
2039 if (Error != ERROR_SUCCESS)
2040 {
2041 DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error));
2042 return;
2043 }
2044
2045 /* Set 'Configuration Data' value */
2046 Size = sizeof(CM_FULL_RESOURCE_DESCRIPTOR) -
2047 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
2048 FullResourceDescriptor = MmAllocateMemory(Size);
2049 if (FullResourceDescriptor == NULL)
2050 {
2051 DbgPrint((DPRINT_HWDETECT,
2052 "Failed to allocate resource descriptor\n"));
2053 return;
2054 }
2055
2056 /* Initialize resource descriptor */
2057 memset(FullResourceDescriptor, 0, Size);
2058 FullResourceDescriptor->InterfaceType = Isa;
2059 FullResourceDescriptor->BusNumber = 0;
2060 FullResourceDescriptor->PartialResourceList.Count = 0;
2061
2062 /* Set 'Configuration Data' value */
2063 Error = RegSetValue(BusKey,
2064 "Configuration Data",
2065 REG_FULL_RESOURCE_DESCRIPTOR,
2066 (PU8) FullResourceDescriptor,
2067 Size);
2068 MmFreeMemory(FullResourceDescriptor);
2069 if (Error != ERROR_SUCCESS)
2070 {
2071 DbgPrint((DPRINT_HWDETECT,
2072 "RegSetValue(Configuration Data) failed (Error %u)\n",
2073 (int)Error));
2074 return;
2075 }
2076
2077 /* Detect ISA/BIOS devices */
2078 DetectBiosDisks(SystemKey, BusKey);
2079
2080 DetectBiosFloppyController(SystemKey, BusKey);
2081
2082 DetectSerialPorts(BusKey);
2083
2084 #if 0
2085 DetectParallelPorts(BusKey);
2086 #endif
2087
2088 DetectKeyboardController(BusKey);
2089
2090 DetectPS2Mouse(BusKey);
2091
2092 DetectDisplayController(BusKey);
2093
2094 /* FIXME: Detect more ISA devices */
2095 }
2096
2097
2098 VOID
2099 DetectHardware(VOID)
2100 {
2101 HKEY SystemKey;
2102 U32 BusNumber = 0;
2103 S32 Error;
2104
2105 DbgPrint((DPRINT_HWDETECT, "DetectHardware()\n"));
2106
2107 HalpCalibrateStallExecution ();
2108
2109 /* Create the 'System' key */
2110 Error = RegCreateKey(NULL,
2111 "\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System",
2112 &SystemKey);
2113 if (Error != ERROR_SUCCESS)
2114 {
2115 DbgPrint((DPRINT_HWDETECT, "RegCreateKey() failed (Error %u)\n", (int)Error));
2116 return;
2117 }
2118
2119 #if 0
2120 DetectSystemData();
2121 #endif
2122 DetectCPUs(SystemKey);
2123
2124 /* Detect buses */
2125 #if 0
2126 DetectPciBios(&BusNumber);
2127 DetectApmBios(&BusNumber);
2128 #endif
2129 DetectPnpBios(SystemKey, &BusNumber);
2130 DetectIsaBios(SystemKey, &BusNumber);
2131 #if 0
2132 DetectAcpiBios(&BusNumber);
2133 #endif
2134
2135
2136 DbgPrint((DPRINT_HWDETECT, "DetectHardware() Done\n"));
2137
2138 #if 0
2139 printf("*** System stopped ***\n");
2140 for (;;);
2141 #endif
2142 }
2143
2144 /* EOF */