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