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