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