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