Don't stop after hardware detection.
[reactos.git] / freeldr / freeldr / arch / i386 / hardware.c
1 /*
2 * FreeLoader
3 *
4 * Copyright (C) 2003 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
29 #include "../../reactos/registry.h"
30 #include "hardware.h"
31
32
33 #define MILLISEC (10)
34 #define PRECISION (8)
35
36 #define HZ (100)
37 #define CLOCK_TICK_RATE (1193182)
38 #define LATCH (CLOCK_TICK_RATE / HZ)
39
40
41 /* No Mouse */
42 #define MOUSE_TYPE_NONE 0
43 /* Microsoft Mouse with 2 buttons */
44 #define MOUSE_TYPE_MICROSOFT 1
45 /* Logitech Mouse with 3 buttons */
46 #define MOUSE_TYPE_LOGITECH 2
47 /* Microsoft Wheel Mouse (aka Z Mouse) */
48 #define MOUSE_TYPE_WHEELZ 3
49 /* Mouse Systems Mouse */
50 #define MOUSE_TYPE_MOUSESYSTEMS 4
51
52
53 /* PS2 stuff */
54
55 /* Controller registers. */
56 #define CONTROLLER_REGISTER_STATUS 0x64
57 #define CONTROLLER_REGISTER_CONTROL 0x64
58 #define CONTROLLER_REGISTER_DATA 0x60
59
60 /* Controller commands. */
61 #define CONTROLLER_COMMAND_READ_MODE 0x20
62 #define CONTROLLER_COMMAND_WRITE_MODE 0x60
63 #define CONTROLLER_COMMAND_GET_VERSION 0xA1
64 #define CONTROLLER_COMMAND_MOUSE_DISABLE 0xA7
65 #define CONTROLLER_COMMAND_MOUSE_ENABLE 0xA8
66 #define CONTROLLER_COMMAND_TEST_MOUSE 0xA9
67 #define CONTROLLER_COMMAND_SELF_TEST 0xAA
68 #define CONTROLLER_COMMAND_KEYBOARD_TEST 0xAB
69 #define CONTROLLER_COMMAND_KEYBOARD_DISABLE 0xAD
70 #define CONTROLLER_COMMAND_KEYBOARD_ENABLE 0xAE
71 #define CONTROLLER_COMMAND_WRITE_MOUSE_OUTPUT_BUFFER 0xD3
72 #define CONTROLLER_COMMAND_WRITE_MOUSE 0xD4
73
74 /* Controller status */
75 #define CONTROLLER_STATUS_OUTPUT_BUFFER_FULL 0x01
76 #define CONTROLLER_STATUS_INPUT_BUFFER_FULL 0x02
77 #define CONTROLLER_STATUS_SELF_TEST 0x04
78 #define CONTROLLER_STATUS_COMMAND 0x08
79 #define CONTROLLER_STATUS_UNLOCKED 0x10
80 #define CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL 0x20
81 #define CONTROLLER_STATUS_GENERAL_TIMEOUT 0x40
82 #define CONTROLLER_STATUS_PARITY_ERROR 0x80
83 #define AUX_STATUS_OUTPUT_BUFFER_FULL (CONTROLLER_STATUS_OUTPUT_BUFFER_FULL | \
84 CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL)
85
86 /* Timeout in ms for sending to keyboard controller. */
87 #define CONTROLLER_TIMEOUT 250
88
89
90 typedef struct _CM_INT13_DRIVE_PARAMETER
91 {
92 U16 DriveSelect;
93 U32 MaxCylinders;
94 U16 SectorsPerTrack;
95 U16 MaxHeads;
96 U16 NumberDrives;
97 } CM_INT13_DRIVE_PARAMETER, *PCM_INT13_DRIVE_PARAMETER;
98
99
100 typedef struct _CM_DISK_GEOMETRY_DEVICE_DATA
101 {
102 U32 BytesPerSector;
103 U32 NumberOfCylinders;
104 U32 SectorsPerTrack;
105 U32 NumberOfHeads;
106 } CM_DISK_GEOMETRY_DEVICE_DATA, *PCM_DISK_GEOMETRY_DEVICE_DATA;
107
108
109 typedef struct _CM_PNP_BIOS_DEVICE_NODE
110 {
111 U16 Size;
112 U8 Node;
113 U32 ProductId;
114 U8 DeviceType[3];
115 U16 DeviceAttributes;
116 } __attribute__((packed)) CM_PNP_BIOS_DEVICE_NODE, *PCM_PNP_BIOS_DEVICE_NODE;
117
118
119 typedef struct _CM_PNP_BIOS_INSTALLATION_CHECK
120 {
121 U8 Signature[4];
122 U8 Revision;
123 U8 Length;
124 U16 ControlField;
125 U8 Checksum;
126 U32 EventFlagAddress;
127 U16 RealModeEntryOffset;
128 U16 RealModeEntrySegment;
129 U16 ProtectedModeEntryOffset;
130 U32 ProtectedModeCodeBaseAddress;
131 U32 OemDeviceId;
132 U16 RealModeDataBaseAddress;
133 U32 ProtectedModeDataBaseAddress;
134 } __attribute__((packed)) CM_PNP_BIOS_INSTALLATION_CHECK, *PCM_PNP_BIOS_INSTALLATION_CHECK;
135
136
137 typedef struct _CM_SERIAL_DEVICE_DATA
138 {
139 U16 Version;
140 U16 Revision;
141 U32 BaudClock;
142 } CM_SERIAL_DEVICE_DATA, *PCM_SERIAL_DEVICE_DATA;
143
144
145 static char Hex[] = "0123456789ABCDEF";
146 static unsigned int delay_count = 1;
147
148
149 /* FUNCTIONS ****************************************************************/
150
151
152 static VOID
153 __KeStallExecutionProcessor(U32 Loops)
154 {
155 register unsigned int i;
156 for (i = 0; i < Loops; i++);
157 }
158
159 VOID KeStallExecutionProcessor(U32 Microseconds)
160 {
161 U64 LoopCount = ((U64)delay_count * (U64)Microseconds) / 1000ULL;
162 __KeStallExecutionProcessor((U32)LoopCount);
163 }
164
165
166 static U32
167 Read8254Timer(VOID)
168 {
169 U32 Count;
170
171 WRITE_PORT_UCHAR((PU8)0x43, 0x00);
172 Count = READ_PORT_UCHAR((PU8)0x40);
173 Count |= READ_PORT_UCHAR((PU8)0x40) << 8;
174
175 return Count;
176 }
177
178
179 static VOID
180 WaitFor8254Wraparound(VOID)
181 {
182 U32 CurCount;
183 U32 PrevCount = ~0;
184 S32 Delta;
185
186 CurCount = Read8254Timer();
187
188 do
189 {
190 PrevCount = CurCount;
191 CurCount = Read8254Timer();
192 Delta = CurCount - PrevCount;
193
194 /*
195 * This limit for delta seems arbitrary, but it isn't, it's
196 * slightly above the level of error a buggy Mercury/Neptune
197 * chipset timer can cause.
198 */
199 }
200 while (Delta < 300);
201 }
202
203
204 VOID
205 HalpCalibrateStallExecution(VOID)
206 {
207 U32 i;
208 U32 calib_bit;
209 U32 CurCount;
210
211 /* Initialise timer interrupt with MILLISECOND ms interval */
212 WRITE_PORT_UCHAR((PU8)0x43, 0x34); /* binary, mode 2, LSB/MSB, ch 0 */
213 WRITE_PORT_UCHAR((PU8)0x40, LATCH & 0xff); /* LSB */
214 WRITE_PORT_UCHAR((PU8)0x40, LATCH >> 8); /* MSB */
215
216 /* Stage 1: Coarse calibration */
217
218 WaitFor8254Wraparound();
219
220 delay_count = 1;
221
222 do {
223 delay_count <<= 1; /* Next delay count to try */
224
225 WaitFor8254Wraparound();
226
227 __KeStallExecutionProcessor(delay_count); /* Do the delay */
228
229 CurCount = Read8254Timer();
230 } while (CurCount > LATCH / 2);
231
232 delay_count >>= 1; /* Get bottom value for delay */
233
234 /* Stage 2: Fine calibration */
235
236 calib_bit = delay_count; /* Which bit are we going to test */
237
238 for(i=0;i<PRECISION;i++) {
239 calib_bit >>= 1; /* Next bit to calibrate */
240 if(!calib_bit) break; /* If we have done all bits, stop */
241
242 delay_count |= calib_bit; /* Set the bit in delay_count */
243
244 WaitFor8254Wraparound();
245
246 __KeStallExecutionProcessor(delay_count); /* Do the delay */
247
248 CurCount = Read8254Timer();
249 if (CurCount <= LATCH / 2) /* If a tick has passed, turn the */
250 delay_count &= ~calib_bit; /* calibrated bit back off */
251 }
252
253 /* We're finished: Do the finishing touches */
254 delay_count /= (MILLISEC / 2); /* Calculate delay_count for 1ms */
255 }
256
257
258 VOID
259 SetComponentInformation(HKEY ComponentKey,
260 U32 Flags,
261 U32 Key,
262 U32 Affinity)
263 {
264 CM_COMPONENT_INFORMATION CompInfo;
265 S32 Error;
266
267 CompInfo.Flags = Flags;
268 CompInfo.Version = 0;
269 CompInfo.Key = Key;
270 CompInfo.Affinity = Affinity;
271
272 /* Set 'Component Information' value */
273 Error = RegSetValue(ComponentKey,
274 "Component Information",
275 REG_BINARY,
276 (PU8)&CompInfo,
277 sizeof(CM_COMPONENT_INFORMATION));
278 if (Error != ERROR_SUCCESS)
279 {
280 DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error));
281 }
282 }
283
284
285 static VOID
286 DetectPnpBios(HKEY SystemKey, U32 *BusNumber)
287 {
288 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
289 PCM_PNP_BIOS_DEVICE_NODE DeviceNode;
290 PCM_PNP_BIOS_INSTALLATION_CHECK InstData;
291 char Buffer[80];
292 HKEY BusKey;
293 U32 x;
294 U32 NodeSize = 0;
295 U32 NodeCount = 0;
296 U8 NodeNumber;
297 U32 FoundNodeCount;
298 int i;
299 U32 PnpBufferSize;
300 U32 Size;
301 char *Ptr;
302 S32 Error;
303
304 InstData = (PCM_PNP_BIOS_INSTALLATION_CHECK)PnpBiosSupported();
305 if (InstData == NULL || strncmp(InstData->Signature, "$PnP", 4))
306 {
307 DbgPrint((DPRINT_HWDETECT, "PnP-BIOS not supported\n"));
308 return;
309 }
310 DbgPrint((DPRINT_HWDETECT, "Signature '%c%c%c%c'\n",
311 InstData->Signature[0], InstData->Signature[1],
312 InstData->Signature[2], InstData->Signature[3]));
313
314
315 x = PnpBiosGetDeviceNodeCount(&NodeSize, &NodeCount);
316 if (x != 0 || NodeSize == 0 || NodeCount == 0)
317 {
318 DbgPrint((DPRINT_HWDETECT, "PnP-BIOS failed to enumerate device nodes\n"));
319 return;
320 }
321 DbgPrint((DPRINT_HWDETECT, "PnP-BIOS supported\n"));
322 DbgPrint((DPRINT_HWDETECT, "MaxNodeSize %u NodeCount %u\n", NodeSize, NodeCount));
323 DbgPrint((DPRINT_HWDETECT, "Estimated buffer size %u\n", NodeSize * NodeCount));
324
325 /* Create new bus key */
326 sprintf(Buffer,
327 "MultifunctionAdapter\\%u", *BusNumber);
328 Error = RegCreateKey(SystemKey,
329 Buffer,
330 &BusKey);
331 if (Error != ERROR_SUCCESS)
332 {
333 DbgPrint((DPRINT_HWDETECT, "RegCreateKey() failed (Error %u)\n", (int)Error));
334 return;
335 }
336
337 /* Increment bus number */
338 (*BusNumber)++;
339
340 /* Set 'Identifier' value */
341 Error = RegSetValue(BusKey,
342 "Identifier",
343 REG_SZ,
344 (PU8)"PNP BIOS",
345 9);
346 if (Error != ERROR_SUCCESS)
347 {
348 DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error));
349 return;
350 }
351
352 /* Set 'Configuration Data' value */
353 Size = sizeof(CM_FULL_RESOURCE_DESCRIPTOR) + (NodeSize * NodeCount);
354 FullResourceDescriptor = MmAllocateMemory(Size);
355 if (FullResourceDescriptor == NULL)
356 {
357 DbgPrint((DPRINT_HWDETECT,
358 "Failed to allocate resource descriptor\n"));
359 return;
360 }
361 memset(FullResourceDescriptor, 0, Size);
362
363 /* Initialize resource descriptor */
364 FullResourceDescriptor->InterfaceType = Internal;
365 FullResourceDescriptor->BusNumber = 0;
366 FullResourceDescriptor->PartialResourceList.Count = 1;
367 FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].Type =
368 CmResourceTypeDeviceSpecific;
369 FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].ShareDisposition =
370 CmResourceShareUndetermined;
371 // FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].Flags =
372
373 Ptr = (char *)(((PVOID)&FullResourceDescriptor->PartialResourceList.PartialDescriptors[0]) +
374 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
375
376 /* Set instalation check data */
377 memcpy (Ptr, InstData, sizeof(CM_PNP_BIOS_INSTALLATION_CHECK));
378 Ptr += sizeof(CM_PNP_BIOS_INSTALLATION_CHECK);
379
380 /* Copy device nodes */
381 FoundNodeCount = 0;
382 PnpBufferSize = sizeof(CM_PNP_BIOS_INSTALLATION_CHECK);
383 for (i = 0; i < 0xFF; i++)
384 {
385 NodeNumber = (U8)i;
386
387 x = PnpBiosGetDeviceNode(&NodeNumber, (PVOID)DISKREADBUFFER);
388 if (x == 0)
389 {
390 DeviceNode = (PCM_PNP_BIOS_DEVICE_NODE)DISKREADBUFFER;
391
392 DbgPrint((DPRINT_HWDETECT,
393 "Node: %u Size %u (0x%x)\n",
394 DeviceNode->Node,
395 DeviceNode->Size,
396 DeviceNode->Size));
397 // printf("Node: %u Size %u (0x%x)\n",
398 // DeviceNode->Node,
399 // DeviceNode->Size,
400 // DeviceNode->Size);
401
402 memcpy (Ptr,
403 DeviceNode,
404 DeviceNode->Size);
405
406 Ptr += DeviceNode->Size;
407 PnpBufferSize += DeviceNode->Size;
408
409 FoundNodeCount++;
410 if (FoundNodeCount >= NodeCount)
411 break;
412 }
413 }
414
415 /* Set real data size */
416 FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].u.DeviceSpecificData.DataSize =
417 PnpBufferSize;
418 Size = sizeof(CM_FULL_RESOURCE_DESCRIPTOR) + PnpBufferSize;
419
420 DbgPrint((DPRINT_HWDETECT, "Real buffer size: %u\n", PnpBufferSize));
421 DbgPrint((DPRINT_HWDETECT, "Resource size: %u\n", Size));
422
423 /* Set 'Configuration Data' value */
424 Error = RegSetValue(BusKey,
425 "Configuration Data",
426 REG_FULL_RESOURCE_DESCRIPTOR,
427 (PU8) FullResourceDescriptor,
428 Size);
429 MmFreeMemory(FullResourceDescriptor);
430 if (Error != ERROR_SUCCESS)
431 {
432 DbgPrint((DPRINT_HWDETECT,
433 "RegSetValue(Configuration Data) failed (Error %u)\n",
434 (int)Error));
435 }
436 }
437
438
439
440 static VOID
441 SetHarddiskConfigurationData(HKEY DiskKey,
442 U32 DriveNumber)
443 {
444 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
445 PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry;
446 EXTENDED_GEOMETRY ExtGeometry;
447 GEOMETRY Geometry;
448 U32 Size;
449 S32 Error;
450
451 /* Set 'Configuration Data' value */
452 Size = sizeof(CM_FULL_RESOURCE_DESCRIPTOR) +
453 sizeof(CM_DISK_GEOMETRY_DEVICE_DATA);
454 FullResourceDescriptor = MmAllocateMemory(Size);
455 if (FullResourceDescriptor == NULL)
456 {
457 DbgPrint((DPRINT_HWDETECT,
458 "Failed to allocate a full resource descriptor\n"));
459 return;
460 }
461
462 memset(FullResourceDescriptor, 0, Size);
463 FullResourceDescriptor->InterfaceType = InterfaceTypeUndefined;
464 FullResourceDescriptor->BusNumber = 0;
465 FullResourceDescriptor->PartialResourceList.Count = 1;
466 FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].Type =
467 CmResourceTypeDeviceSpecific;
468 // FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].ShareDisposition =
469 // FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].Flags =
470 FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].u.DeviceSpecificData.DataSize =
471 sizeof(CM_DISK_GEOMETRY_DEVICE_DATA);
472
473 /* Get pointer to geometry data */
474 DiskGeometry = ((PVOID)FullResourceDescriptor) + sizeof(CM_FULL_RESOURCE_DESCRIPTOR);
475
476 /* Get the disk geometry */
477 ExtGeometry.Size = sizeof(EXTENDED_GEOMETRY);
478 if (DiskGetExtendedDriveParameters(DriveNumber, &ExtGeometry, ExtGeometry.Size))
479 {
480 DiskGeometry->BytesPerSector = ExtGeometry.BytesPerSector;
481 DiskGeometry->NumberOfCylinders = ExtGeometry.Cylinders;
482 DiskGeometry->SectorsPerTrack = ExtGeometry.SectorsPerTrack;
483 DiskGeometry->NumberOfHeads = ExtGeometry.Heads;
484 }
485 else if(DiskGetDriveParameters(DriveNumber, &Geometry))
486 {
487 DiskGeometry->BytesPerSector = Geometry.BytesPerSector;
488 DiskGeometry->NumberOfCylinders = Geometry.Cylinders;
489 DiskGeometry->SectorsPerTrack = Geometry.Sectors;
490 DiskGeometry->NumberOfHeads = Geometry.Heads;
491 }
492 else
493 {
494 DbgPrint((DPRINT_HWDETECT, "Reading disk geometry failed\n"));
495 MmFreeMemory(FullResourceDescriptor);
496 return;
497 }
498 DbgPrint((DPRINT_HWDETECT,
499 "Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n",
500 DriveNumber,
501 DiskGeometry->NumberOfCylinders,
502 DiskGeometry->NumberOfHeads,
503 DiskGeometry->SectorsPerTrack,
504 DiskGeometry->BytesPerSector));
505
506 Error = RegSetValue(DiskKey,
507 "Configuration Data",
508 REG_FULL_RESOURCE_DESCRIPTOR,
509 (PU8) FullResourceDescriptor,
510 Size);
511 MmFreeMemory(FullResourceDescriptor);
512 if (Error != ERROR_SUCCESS)
513 {
514 DbgPrint((DPRINT_HWDETECT,
515 "RegSetValue(Configuration Data) failed (Error %u)\n",
516 (int)Error));
517 }
518 }
519
520
521 static VOID
522 SetHarddiskIdentifier(HKEY DiskKey,
523 U32 DriveNumber)
524 {
525 PMASTER_BOOT_RECORD Mbr;
526 U32 *Buffer;
527 U32 i;
528 U32 Checksum;
529 U32 Signature;
530 char Identifier[20];
531 S32 Error;
532
533 /* Read the MBR */
534 if (!DiskReadLogicalSectors(DriveNumber, 0ULL, 1, (PVOID)DISKREADBUFFER))
535 {
536 DbgPrint((DPRINT_HWDETECT, "Reading MBR failed\n"));
537 return;
538 }
539
540 Buffer = (U32*)DISKREADBUFFER;
541 Mbr = (PMASTER_BOOT_RECORD)DISKREADBUFFER;
542
543 Signature = Mbr->Signature;
544 DbgPrint((DPRINT_HWDETECT, "Signature: %x\n", Signature));
545
546 /* Calculate the MBR checksum */
547 Checksum = 0;
548 for (i = 0; i < 128; i++)
549 {
550 Checksum += Buffer[i];
551 }
552 Checksum = ~Checksum + 1;
553 DbgPrint((DPRINT_HWDETECT, "Checksum: %x\n", Checksum));
554
555 /* Convert checksum and signature to identifier string */
556 Identifier[0] = Hex[(Checksum >> 28) & 0x0F];
557 Identifier[1] = Hex[(Checksum >> 24) & 0x0F];
558 Identifier[2] = Hex[(Checksum >> 20) & 0x0F];
559 Identifier[3] = Hex[(Checksum >> 16) & 0x0F];
560 Identifier[4] = Hex[(Checksum >> 12) & 0x0F];
561 Identifier[5] = Hex[(Checksum >> 8) & 0x0F];
562 Identifier[6] = Hex[(Checksum >> 4) & 0x0F];
563 Identifier[7] = Hex[Checksum & 0x0F];
564 Identifier[8] = '-';
565 Identifier[9] = Hex[(Signature >> 28) & 0x0F];
566 Identifier[10] = Hex[(Signature >> 24) & 0x0F];
567 Identifier[11] = Hex[(Signature >> 20) & 0x0F];
568 Identifier[12] = Hex[(Signature >> 16) & 0x0F];
569 Identifier[13] = Hex[(Signature >> 12) & 0x0F];
570 Identifier[14] = Hex[(Signature >> 8) & 0x0F];
571 Identifier[15] = Hex[(Signature >> 4) & 0x0F];
572 Identifier[16] = Hex[Signature & 0x0F];
573 Identifier[17] = '-';
574 Identifier[18] = 'A';
575 Identifier[19] = 0;
576 DbgPrint((DPRINT_HWDETECT, "Identifier: %xsn", Identifier));
577
578 /* Set identifier */
579 Error = RegSetValue(DiskKey,
580 "Identifier",
581 REG_SZ,
582 (PU8) Identifier,
583 20);
584 if (Error != ERROR_SUCCESS)
585 {
586 DbgPrint((DPRINT_HWDETECT,
587 "RegSetValue(Identifier) failed (Error %u)\n",
588 (int)Error));
589 }
590 }
591
592
593 static VOID
594 DetectBiosDisks(HKEY SystemKey,
595 HKEY BusKey)
596 {
597 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
598 PCM_INT13_DRIVE_PARAMETER Int13Drives;
599 GEOMETRY Geometry;
600 CHAR Buffer[80];
601 HKEY DiskKey;
602 U32 DiskCount;
603 U32 Size;
604 U32 i;
605 S32 Error;
606
607 /* Count the number of visible drives */
608 DiskReportError(FALSE);
609 DiskCount = 0;
610 while (DiskReadLogicalSectors(0x80 + DiskCount, 0ULL, 1, (PVOID)DISKREADBUFFER))
611 {
612 DiskCount++;
613 }
614 DiskReportError(TRUE);
615 DbgPrint((DPRINT_HWDETECT, "BIOS reports %d harddisk%s\n",
616 (int)DiskCount, (DiskCount == 1) ? "": "s"));
617
618 /* Allocate resource descriptor */
619 Size = sizeof(CM_FULL_RESOURCE_DESCRIPTOR) +
620 sizeof(CM_INT13_DRIVE_PARAMETER) * DiskCount;
621 FullResourceDescriptor = MmAllocateMemory(Size);
622 if (FullResourceDescriptor == NULL)
623 {
624 DbgPrint((DPRINT_HWDETECT,
625 "Failed to allocate resource descriptor\n"));
626 return;
627 }
628
629 /* Initialize resource descriptor */
630 memset(FullResourceDescriptor, 0, Size);
631 FullResourceDescriptor->InterfaceType = InterfaceTypeUndefined;
632 FullResourceDescriptor->BusNumber = -1;
633 FullResourceDescriptor->PartialResourceList.Count = 1;
634 FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].Type =
635 CmResourceTypeDeviceSpecific;
636 // FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].ShareDisposition =
637 // FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].Flags =
638 FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].u.DeviceSpecificData.DataSize =
639 sizeof(CM_INT13_DRIVE_PARAMETER) * DiskCount;
640
641 /* Get harddisk Int13 geometry data */
642 Int13Drives = ((PVOID)FullResourceDescriptor) + sizeof(CM_FULL_RESOURCE_DESCRIPTOR);
643 for (i = 0; i < DiskCount; i++)
644 {
645 if (DiskGetDriveParameters(0x80 + i, &Geometry))
646 {
647 Int13Drives[i].DriveSelect = 0x80 + i;
648 Int13Drives[i].MaxCylinders = Geometry.Cylinders - 1;
649 Int13Drives[i].SectorsPerTrack = Geometry.Sectors;
650 Int13Drives[i].MaxHeads = Geometry.Heads - 1;
651 Int13Drives[i].NumberDrives = DiskCount;
652
653 DbgPrint((DPRINT_HWDETECT,
654 "Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n",
655 0x80 + i,
656 Geometry.Cylinders - 1,
657 Geometry.Heads -1,
658 Geometry.Sectors,
659 Geometry.BytesPerSector));
660 }
661 }
662
663 /* Set 'Configuration Data' value */
664 Error = RegSetValue(SystemKey,
665 "Configuration Data",
666 REG_FULL_RESOURCE_DESCRIPTOR,
667 (PU8) FullResourceDescriptor,
668 Size);
669 MmFreeMemory(FullResourceDescriptor);
670 if (Error != ERROR_SUCCESS)
671 {
672 DbgPrint((DPRINT_HWDETECT,
673 "RegSetValue(Configuration Data) failed (Error %u)\n",
674 (int)Error));
675 return;
676 }
677
678 /* Create and fill subkey for each harddisk */
679 for (i = 0; i < DiskCount; i++)
680 {
681 /* Create disk key */
682 sprintf (Buffer,
683 "DiskController\\0\\DiskPeripheral\\%u",
684 i);
685
686 Error = RegCreateKey(BusKey,
687 Buffer,
688 &DiskKey);
689 if (Error != ERROR_SUCCESS)
690 {
691 DbgPrint((DPRINT_HWDETECT, "Failed to create drive key\n"));
692 continue;
693 }
694 DbgPrint((DPRINT_HWDETECT, "Created key: %s\n", Buffer));
695
696 /* Set disk values */
697 SetHarddiskConfigurationData(DiskKey, 0x80 + i);
698 SetHarddiskIdentifier(DiskKey, 0x80 + i);
699 }
700 }
701
702
703 static VOID
704 InitializeSerialPort(U32 Port,
705 U32 LineControl)
706 {
707 WRITE_PORT_UCHAR((PUCHAR)Port + 3, 0x80); /* set DLAB on */
708 WRITE_PORT_UCHAR((PUCHAR)Port, 0x60); /* speed LO byte */
709 WRITE_PORT_UCHAR((PUCHAR)Port + 1, 0); /* speed HI byte */
710 WRITE_PORT_UCHAR((PUCHAR)Port + 3, LineControl);
711 WRITE_PORT_UCHAR((PUCHAR)Port + 1, 0); /* set comm and DLAB to 0 */
712 WRITE_PORT_UCHAR((PUCHAR)Port + 4, 0x09); /* DR int enable */
713 READ_PORT_UCHAR((PUCHAR)Port + 5); /* clear error bits */
714 }
715
716
717 static U32
718 DetectMicrosoftMouse(U32 Port)
719 {
720 CHAR Buffer[4];
721 U32 i;
722 U32 TimeOut = 250;
723 U8 LineControl;
724
725 /* Shutdown mouse or something like that */
726 LineControl = READ_PORT_UCHAR((PUCHAR)Port + 4);
727 WRITE_PORT_UCHAR((PUCHAR)Port + 4, (LineControl & ~0x02) | 0x01);
728 KeStallExecutionProcessor(500000);
729
730 /* Clear buffer */
731 while (READ_PORT_UCHAR((PUCHAR)Port + 5) & 0x01)
732 READ_PORT_UCHAR((PUCHAR)Port);
733
734 /*
735 * Send modem control with 'Data Terminal Ready', 'Request To Send' and
736 * 'Output Line 2' message. This enables mouse to identify.
737 */
738 WRITE_PORT_UCHAR((PUCHAR)Port + 4, 0x0b);
739
740 /* Wait 10 milliseconds for the mouse getting ready */
741 KeStallExecutionProcessor(10000);
742
743 /* Read first four bytes, which contains Microsoft Mouse signs */
744 for (i = 0; i < 4; i++)
745 {
746 while (((READ_PORT_UCHAR((PUCHAR)Port + 5) & 1) == 0) && (TimeOut > 0))
747 {
748 KeStallExecutionProcessor(1000);
749 --TimeOut;
750 if (TimeOut == 0)
751 return MOUSE_TYPE_NONE;
752 }
753 Buffer[i] = READ_PORT_UCHAR((PUCHAR)Port);
754 }
755
756 DbgPrint((DPRINT_HWDETECT,
757 "Mouse data: %x %x %x %x\n",
758 Buffer[0],Buffer[1],Buffer[2],Buffer[3]));
759
760 /* Check that four bytes for signs */
761 for (i = 0; i < 4; ++i)
762 {
763 if (Buffer[i] == 'B')
764 {
765 /* Sign for Microsoft Ballpoint */
766 // DbgPrint("Microsoft Ballpoint device detected\n");
767 // DbgPrint("THIS DEVICE IS NOT SUPPORTED, YET\n");
768 return MOUSE_TYPE_NONE;
769 }
770 else if (Buffer[i] == 'M')
771 {
772 /* Sign for Microsoft Mouse protocol followed by button specifier */
773 if (i == 3)
774 {
775 /* Overflow Error */
776 return MOUSE_TYPE_NONE;
777 }
778
779 switch (Buffer[i + 1])
780 {
781 case '3':
782 DbgPrint((DPRINT_HWDETECT,
783 "Microsoft Mouse with 3-buttons detected\n"));
784 return MOUSE_TYPE_LOGITECH;
785
786 case 'Z':
787 DbgPrint((DPRINT_HWDETECT,
788 "Microsoft Wheel Mouse detected\n"));
789 return MOUSE_TYPE_WHEELZ;
790
791 /* case '2': */
792 default:
793 DbgPrint((DPRINT_HWDETECT,
794 "Microsoft Mouse with 2-buttons detected\n"));
795 return MOUSE_TYPE_MICROSOFT;
796 }
797 }
798 }
799
800 return MOUSE_TYPE_NONE;
801 }
802
803
804 static U32
805 GetMousePnpId(U32 Port, char *Buffer)
806 {
807 U32 TimeOut;
808 U32 i = 0;
809 char c;
810 char x;
811
812 WRITE_PORT_UCHAR((PUCHAR)Port + 4, 0x09);
813
814 /* Wait 10 milliseconds for the mouse getting ready */
815 KeStallExecutionProcessor(200000);
816
817 WRITE_PORT_UCHAR((PUCHAR)Port + 4, 0x0b);
818
819 KeStallExecutionProcessor(200000);
820
821 for (;;)
822 {
823 TimeOut = 250;
824 while (((READ_PORT_UCHAR((PUCHAR)Port + 5) & 1) == 0) && (TimeOut > 0))
825 {
826 KeStallExecutionProcessor(1000);
827 --TimeOut;
828 if (TimeOut == 0)
829 {
830 return 0;
831 }
832 }
833
834 c = READ_PORT_UCHAR((PUCHAR)Port);
835 if (c == 0x08 || c == 0x28)
836 break;
837 }
838
839 Buffer[i++] = c;
840 x = c + 1;
841
842 for (;;)
843 {
844 TimeOut = 250;
845 while (((READ_PORT_UCHAR((PUCHAR)Port + 5) & 1) == 0) && (TimeOut > 0))
846 {
847 KeStallExecutionProcessor(1000);
848 --TimeOut;
849 if (TimeOut == 0)
850 return 0;
851 }
852 c = READ_PORT_UCHAR((PUCHAR)Port);
853 Buffer[i++] = c;
854 if (c == x)
855 break;
856 if (i >= 256)
857 break;
858 }
859
860 return i;
861 }
862
863
864 static VOID
865 DetectSerialPointerPeripheral(HKEY ControllerKey,
866 U32 Base)
867 {
868 CM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
869 char Buffer[256];
870 char Identifier[256];
871 HKEY PeripheralKey;
872 U32 MouseType;
873 U32 Length;
874 U32 i;
875 U32 j;
876 S32 Error;
877
878 DbgPrint((DPRINT_HWDETECT,
879 "DetectSerialPointerPeripheral()\n"));
880
881 Identifier[0] = 0;
882
883 InitializeSerialPort(Base, 2);
884 MouseType = DetectMicrosoftMouse(Base);
885
886 if (MouseType != MOUSE_TYPE_NONE)
887 {
888 Length = GetMousePnpId(Base, Buffer);
889 DbgPrint((DPRINT_HWDETECT,
890 "PnP ID length: %u\n",
891 Length));
892
893 if (Length != 0)
894 {
895 /* Convert PnP sting to ASCII */
896 if (Buffer[0] == 0x08)
897 {
898 for (i = 0; i < Length; i++)
899 Buffer[i] += 0x20;
900 }
901 Buffer[Length] = 0;
902
903 DbgPrint((DPRINT_HWDETECT,
904 "PnP ID string: %s\n",
905 Buffer));
906
907 /* Copy PnpId string */
908 memcpy(&Identifier[0],
909 &Buffer[3],
910 7);
911 memcpy(&Identifier[7],
912 " - ",
913 4);
914
915 /* Skip device serial number */
916 i = 10;
917 if (Buffer[i] == '\\')
918 {
919 for (j = ++i; i < Length; ++i)
920 {
921 if (Buffer[i] == '\\')
922 break;
923 }
924 if (i >= Length)
925 i -= 3;
926 }
927
928 /* Skip PnP class */
929 if (Buffer[i] == '\\')
930 {
931 for (j = ++i; i < Length; ++i)
932 {
933 if (Buffer[i] == '\\')
934 break;
935 }
936
937 if (i >= Length)
938 i -= 3;
939 }
940
941 /* Skip compatible PnP Id */
942 if (Buffer[i] == '\\')
943 {
944 for (j = ++i; i < Length; ++i)
945 {
946 if (Buffer[i] == '\\')
947 break;
948 }
949 if (Buffer[j] == '*')
950 ++j;
951 if (i >= Length)
952 i -= 3;
953 }
954
955 /* Get product description */
956 if (Buffer[i] == '\\')
957 {
958 for (j = ++i; i < Length; ++i)
959 {
960 if (Buffer[i] == ';')
961 break;
962 }
963 if (i >= Length)
964 i -= 3;
965 if (i > j + 1)
966 {
967 memcpy(&Identifier[10],
968 &Buffer[j],
969 i - j);
970 Identifier[10 + (i-j)] = 0;
971 }
972 }
973
974 DbgPrint((DPRINT_HWDETECT,
975 "Identifier string: %s\n",
976 Identifier));
977 }
978
979 if (Length == 0 || strlen(Identifier) < 11)
980 {
981 switch (MouseType)
982 {
983 case MOUSE_TYPE_LOGITECH:
984 strcpy (Identifier,
985 "LOGITECH SERIAL MOUSE");
986 break;
987
988 case MOUSE_TYPE_WHEELZ:
989 strcpy (Identifier,
990 "MICROSOFT SERIAL MOUSE WITH WHEEL");
991 break;
992
993 case MOUSE_TYPE_MICROSOFT:
994 default:
995 strcpy (Identifier,
996 "MICROSOFT SERIAL MOUSE");
997 break;
998 }
999 }
1000
1001 /* Create 'PointerPeripheral' key */
1002 Error = RegCreateKey(ControllerKey,
1003 "PointerPeripheral\\0",
1004 &PeripheralKey);
1005 if (Error != ERROR_SUCCESS)
1006 {
1007 DbgPrint((DPRINT_HWDETECT,
1008 "Failed to create peripheral key\n"));
1009 return;
1010 }
1011 DbgPrint((DPRINT_HWDETECT,
1012 "Created key: PointerPeripheral\\0\n"));
1013
1014 /* Set 'ComponentInformation' value */
1015 SetComponentInformation(PeripheralKey,
1016 0x20,
1017 0,
1018 0xFFFFFFFF);
1019
1020 /* Set 'Configuration Data' value */
1021 memset(&FullResourceDescriptor, 0, sizeof(CM_FULL_RESOURCE_DESCRIPTOR));
1022 FullResourceDescriptor.InterfaceType = Isa;
1023 FullResourceDescriptor.BusNumber = 0;
1024 FullResourceDescriptor.PartialResourceList.Count = 0;
1025
1026 Error = RegSetValue(PeripheralKey,
1027 "Configuration Data",
1028 REG_FULL_RESOURCE_DESCRIPTOR,
1029 (PU8)&FullResourceDescriptor,
1030 sizeof(CM_FULL_RESOURCE_DESCRIPTOR) -
1031 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
1032 if (Error != ERROR_SUCCESS)
1033 {
1034 DbgPrint((DPRINT_HWDETECT,
1035 "RegSetValue(Configuration Data) failed (Error %u)\n",
1036 (int)Error));
1037 }
1038
1039 /* Set 'Identifier' value */
1040 Error = RegSetValue(PeripheralKey,
1041 "Identifier",
1042 REG_SZ,
1043 (PU8)Identifier,
1044 strlen(Identifier) + 1);
1045 if (Error != ERROR_SUCCESS)
1046 {
1047 DbgPrint((DPRINT_HWDETECT,
1048 "RegSetValue() failed (Error %u)\n",
1049 (int)Error));
1050 }
1051 }
1052 }
1053
1054
1055 static VOID
1056 DetectSerialPorts(HKEY BusKey)
1057 {
1058 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
1059 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
1060 PCM_SERIAL_DEVICE_DATA SerialDeviceData;
1061 U32 Base[4] = {0x3F8, 0x2F8, 0x3E8, 0x2E8};
1062 U32 Irq[4] = {4, 3, 4, 3};
1063 char Buffer[80];
1064 U32 ControllerNumber = 0;
1065 HKEY ControllerKey;
1066 U32 i;
1067 S32 Error;
1068 U32 Size;
1069
1070 DbgPrint((DPRINT_HWDETECT, "DetectSerialPorts()\n"));
1071
1072 for (i = 0; i < 4; i++)
1073 {
1074 WRITE_PORT_UCHAR ((PUCHAR)(Base[i] + 4), 0x10);
1075 if (!(READ_PORT_UCHAR((PUCHAR)Base[i] + 6) & 0xf0))
1076 {
1077 DbgPrint((DPRINT_HWDETECT,
1078 "Found COM%u port at 0x%x\n",
1079 i + 1,
1080 Base[i]));
1081
1082 /* Create controller key */
1083 sprintf(Buffer,
1084 "SerialController\\%u",
1085 ControllerNumber);
1086
1087 Error = RegCreateKey(BusKey,
1088 Buffer,
1089 &ControllerKey);
1090 if (Error != ERROR_SUCCESS)
1091 {
1092 DbgPrint((DPRINT_HWDETECT, "Failed to create controller key\n"));
1093 continue;
1094 }
1095 DbgPrint((DPRINT_HWDETECT, "Created key: %s\n", Buffer));
1096
1097 /* Set 'ComponentInformation' value */
1098 SetComponentInformation(ControllerKey,
1099 0x78,
1100 ControllerNumber,
1101 0xFFFFFFFF);
1102
1103 /* Build full device descriptor */
1104 Size = sizeof(CM_FULL_RESOURCE_DESCRIPTOR) +
1105 2 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) +
1106 sizeof(CM_SERIAL_DEVICE_DATA);
1107 FullResourceDescriptor = MmAllocateMemory(Size);
1108 if (FullResourceDescriptor == NULL)
1109 {
1110 DbgPrint((DPRINT_HWDETECT,
1111 "Failed to allocate resource descriptor\n"));
1112 continue;
1113 }
1114 memset(FullResourceDescriptor, 0, Size);
1115
1116 /* Initialize resource descriptor */
1117 FullResourceDescriptor->InterfaceType = Isa;
1118 FullResourceDescriptor->BusNumber = 0;
1119 FullResourceDescriptor->PartialResourceList.Count = 3;
1120
1121 /* Set IO Port */
1122 PartialDescriptor = &FullResourceDescriptor->PartialResourceList.PartialDescriptors[0];
1123 PartialDescriptor->Type = CmResourceTypePort;
1124 PartialDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1125 PartialDescriptor->Flags = CM_RESOURCE_PORT_IO;
1126 PartialDescriptor->u.Port.Start = (U64)Base[i];
1127 PartialDescriptor->u.Port.Length = 7;
1128
1129 /* Set Interrupt */
1130 PartialDescriptor = &FullResourceDescriptor->PartialResourceList.PartialDescriptors[1];
1131 PartialDescriptor->Type = CmResourceTypeInterrupt;
1132 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
1133 PartialDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
1134 PartialDescriptor->u.Interrupt.Level = Irq[i];
1135 PartialDescriptor->u.Interrupt.Vector = Irq[i];
1136 PartialDescriptor->u.Interrupt.Affinity = 0xFFFFFFFF;
1137
1138 /* Set serial data (device specific) */
1139 PartialDescriptor = &FullResourceDescriptor->PartialResourceList.PartialDescriptors[2];
1140 PartialDescriptor->Type = CmResourceTypeDeviceSpecific;
1141 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
1142 PartialDescriptor->Flags = 0;
1143 PartialDescriptor->u.DeviceSpecificData.DataSize = sizeof(CM_SERIAL_DEVICE_DATA);
1144
1145 SerialDeviceData =
1146 (PCM_SERIAL_DEVICE_DATA)&FullResourceDescriptor->PartialResourceList.PartialDescriptors[3];
1147 SerialDeviceData->BaudClock = 1843200; /* UART Clock frequency (Hertz) */
1148
1149 /* Set 'Configuration Data' value */
1150 Error = RegSetValue(ControllerKey,
1151 "Configuration Data",
1152 REG_FULL_RESOURCE_DESCRIPTOR,
1153 (PU8) FullResourceDescriptor,
1154 Size);
1155 MmFreeMemory(FullResourceDescriptor);
1156 if (Error != ERROR_SUCCESS)
1157 {
1158 DbgPrint((DPRINT_HWDETECT,
1159 "RegSetValue(Configuration Data) failed (Error %u)\n",
1160 (int)Error));
1161 }
1162
1163 /* Set 'Identifier' value */
1164 sprintf(Buffer,
1165 "COM%u",
1166 i + 1);
1167 Error = RegSetValue(BusKey,
1168 "Identifier",
1169 REG_SZ,
1170 (PU8)Buffer,
1171 5);
1172 if (Error != ERROR_SUCCESS)
1173 {
1174 DbgPrint((DPRINT_HWDETECT,
1175 "RegSetValue() failed (Error %u)\n",
1176 (int)Error));
1177 continue;
1178 }
1179 DbgPrint((DPRINT_HWDETECT,
1180 "Created value: Identifier %s\n",
1181 Buffer));
1182
1183 /* Detect serial mouse */
1184 DetectSerialPointerPeripheral(ControllerKey, Base[i]);
1185
1186 ControllerNumber++;
1187 }
1188 }
1189 }
1190
1191
1192 static VOID
1193 PS2ControllerWait(VOID)
1194 {
1195 U32 Timeout;
1196 U8 Status;
1197
1198 for (Timeout = 0; Timeout < CONTROLLER_TIMEOUT; Timeout++)
1199 {
1200 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
1201 if ((Status & CONTROLLER_STATUS_INPUT_BUFFER_FULL) == 0)
1202 return;
1203
1204 /* Sleep for one millisecond */
1205 KeStallExecutionProcessor(1000);
1206 }
1207 }
1208
1209
1210 static BOOLEAN
1211 DetectPS2AuxPort(VOID)
1212 {
1213 U32 Loops;
1214 U8 Scancode;
1215 U8 Status;
1216
1217 /* Put the value 0x5A in the output buffer using the
1218 * "WriteAuxiliary Device Output Buffer" command (0xD3).
1219 * Poll the Status Register for a while to see if the value really turns up
1220 * in the Data Register. If the KEYBOARD_STATUS_MOUSE_OBF bit is also set
1221 * to 1 in the Status Register, we assume this controller has an
1222 * Auxiliary Port (a.k.a. Mouse Port).
1223 */
1224 PS2ControllerWait();
1225 WRITE_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_CONTROL,
1226 CONTROLLER_COMMAND_WRITE_MOUSE_OUTPUT_BUFFER);
1227 PS2ControllerWait();
1228
1229 /* 0x5A is a random dummy value */
1230 WRITE_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA,
1231 0x5A);
1232
1233 for (Loops = 0; Loops < 10; Loops++)
1234 {
1235 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
1236
1237 if ((Status & CONTROLLER_STATUS_OUTPUT_BUFFER_FULL) != 0)
1238 {
1239 Scancode = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA);
1240 if ((Status & CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL) != 0)
1241 {
1242 return TRUE;
1243 }
1244 break;
1245 }
1246
1247 KeStallExecutionProcessor(10000);
1248 }
1249
1250 return FALSE;
1251 }
1252
1253
1254 static BOOLEAN
1255 DetectPS2AuxDevice(VOID)
1256 {
1257 U8 Scancode;
1258 U8 Status;
1259
1260 PS2ControllerWait();
1261 WRITE_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_CONTROL,
1262 CONTROLLER_COMMAND_WRITE_MOUSE);
1263 PS2ControllerWait();
1264
1265 /* Identify device */
1266 WRITE_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA,
1267 0xF2);
1268
1269 KeStallExecutionProcessor(10000);
1270
1271 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
1272 if ((Status & CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL) == 0)
1273 {
1274 return FALSE;
1275 }
1276
1277 Scancode = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA);
1278 if (Scancode != 0xFA)
1279 return FALSE;
1280
1281 KeStallExecutionProcessor(10000);
1282
1283 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
1284 if ((Status & CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL) == 0)
1285 {
1286 return FALSE;
1287 }
1288
1289 Scancode = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA);
1290 if (Scancode != 0x00)
1291 return FALSE;
1292
1293 return TRUE;
1294 }
1295
1296
1297 static VOID
1298 DetectPS2Mouse(HKEY BusKey)
1299 {
1300 CM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
1301 HKEY ControllerKey;
1302 HKEY PeripheralKey;
1303 S32 Error;
1304
1305 if (DetectPS2AuxPort())
1306 {
1307 DbgPrint((DPRINT_HWDETECT, "Detected PS2 port\n"));
1308
1309 /* Create controller key */
1310 Error = RegCreateKey(BusKey,
1311 "PointerController\\0",
1312 &ControllerKey);
1313 if (Error != ERROR_SUCCESS)
1314 {
1315 DbgPrint((DPRINT_HWDETECT, "Failed to create controller key\n"));
1316 return;
1317 }
1318 DbgPrint((DPRINT_HWDETECT, "Created key: PointerController\\0\n"));
1319
1320 /* Set 'ComponentInformation' value */
1321 SetComponentInformation(ControllerKey,
1322 0x20,
1323 0,
1324 0xFFFFFFFF);
1325
1326 memset(&FullResourceDescriptor, 0, sizeof(CM_FULL_RESOURCE_DESCRIPTOR));
1327
1328 /* Initialize resource descriptor */
1329 FullResourceDescriptor.InterfaceType = Isa;
1330 FullResourceDescriptor.BusNumber = 0;
1331 FullResourceDescriptor.PartialResourceList.Count = 1;
1332
1333 /* Set Interrupt */
1334 FullResourceDescriptor.PartialResourceList.PartialDescriptors[0].Type = CmResourceTypeInterrupt;
1335 FullResourceDescriptor.PartialResourceList.PartialDescriptors[0].ShareDisposition = CmResourceShareUndetermined;
1336 FullResourceDescriptor.PartialResourceList.PartialDescriptors[0].Flags = CM_RESOURCE_INTERRUPT_LATCHED;
1337 FullResourceDescriptor.PartialResourceList.PartialDescriptors[0].u.Interrupt.Level = 12;
1338 FullResourceDescriptor.PartialResourceList.PartialDescriptors[0].u.Interrupt.Vector = 12;
1339 FullResourceDescriptor.PartialResourceList.PartialDescriptors[0].u.Interrupt.Affinity = 0xFFFFFFFF;
1340
1341 /* Set 'Configuration Data' value */
1342 Error = RegSetValue(ControllerKey,
1343 "Configuration Data",
1344 REG_FULL_RESOURCE_DESCRIPTOR,
1345 (PU8)&FullResourceDescriptor,
1346 sizeof(CM_FULL_RESOURCE_DESCRIPTOR));
1347 if (Error != ERROR_SUCCESS)
1348 {
1349 DbgPrint((DPRINT_HWDETECT,
1350 "RegSetValue(Configuration Data) failed (Error %u)\n",
1351 (int)Error));
1352 return;
1353 }
1354
1355
1356 if (DetectPS2AuxDevice())
1357 {
1358 DbgPrint((DPRINT_HWDETECT, "Detected PS2 mouse\n"));
1359
1360 /* Create peripheral key */
1361 Error = RegCreateKey(ControllerKey,
1362 "PointerPeripheral\\0",
1363 &PeripheralKey);
1364 if (Error != ERROR_SUCCESS)
1365 {
1366 DbgPrint((DPRINT_HWDETECT, "Failed to create peripheral key\n"));
1367 return;
1368 }
1369 DbgPrint((DPRINT_HWDETECT, "Created key: PointerPeripheral\\0\n"));
1370
1371 /* Set 'ComponentInformation' value */
1372 SetComponentInformation(PeripheralKey,
1373 0x20,
1374 0,
1375 0xFFFFFFFF);
1376
1377 /* Initialize resource descriptor */
1378 memset(&FullResourceDescriptor, 0, sizeof(CM_FULL_RESOURCE_DESCRIPTOR));
1379 FullResourceDescriptor.InterfaceType = Isa;
1380 FullResourceDescriptor.BusNumber = 0;
1381 FullResourceDescriptor.PartialResourceList.Count = 0;
1382
1383 /* Set 'Configuration Data' value */
1384 Error = RegSetValue(PeripheralKey,
1385 "Configuration Data",
1386 REG_FULL_RESOURCE_DESCRIPTOR,
1387 (PU8)&FullResourceDescriptor,
1388 sizeof(CM_FULL_RESOURCE_DESCRIPTOR) -
1389 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
1390 if (Error != ERROR_SUCCESS)
1391 {
1392 DbgPrint((DPRINT_HWDETECT,
1393 "RegSetValue(Configuration Data) failed (Error %u)\n",
1394 (int)Error));
1395 return;
1396 }
1397
1398 /* Set 'Identifier' value */
1399 Error = RegSetValue(PeripheralKey,
1400 "Identifier",
1401 REG_SZ,
1402 (PU8)"MICROSOFT PS2 MOUSE",
1403 20);
1404 if (Error != ERROR_SUCCESS)
1405 {
1406 DbgPrint((DPRINT_HWDETECT,
1407 "RegSetValue() failed (Error %u)\n",
1408 (int)Error));
1409 return;
1410 }
1411 }
1412 }
1413 }
1414
1415
1416 static VOID
1417 DetectIsaBios(HKEY SystemKey, U32 *BusNumber)
1418 {
1419 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
1420 char Buffer[80];
1421 HKEY BusKey;
1422 U32 Size;
1423 S32 Error;
1424
1425 /* Create new bus key */
1426 sprintf(Buffer,
1427 "MultifunctionAdapter\\%u", *BusNumber);
1428 Error = RegCreateKey(SystemKey,
1429 Buffer,
1430 &BusKey);
1431 if (Error != ERROR_SUCCESS)
1432 {
1433 DbgPrint((DPRINT_HWDETECT, "RegCreateKey() failed (Error %u)\n", (int)Error));
1434 return;
1435 }
1436
1437 /* Increment bus number */
1438 (*BusNumber)++;
1439
1440 /* Set 'Identifier' value */
1441 Error = RegSetValue(BusKey,
1442 "Identifier",
1443 REG_SZ,
1444 (PU8)"ISA",
1445 4);
1446 if (Error != ERROR_SUCCESS)
1447 {
1448 DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error));
1449 return;
1450 }
1451
1452 /* Set 'Configuration Data' value */
1453 Size = sizeof(CM_FULL_RESOURCE_DESCRIPTOR) -
1454 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
1455 FullResourceDescriptor = MmAllocateMemory(Size);
1456 if (FullResourceDescriptor == NULL)
1457 {
1458 DbgPrint((DPRINT_HWDETECT,
1459 "Failed to allocate resource descriptor\n"));
1460 return;
1461 }
1462
1463 /* Initialize resource descriptor */
1464 memset(FullResourceDescriptor, 0, Size);
1465 FullResourceDescriptor->InterfaceType = Isa;
1466 FullResourceDescriptor->BusNumber = 0;
1467 FullResourceDescriptor->PartialResourceList.Count = 0;
1468
1469 /* Set 'Configuration Data' value */
1470 Error = RegSetValue(SystemKey,
1471 "Configuration Data",
1472 REG_FULL_RESOURCE_DESCRIPTOR,
1473 (PU8) FullResourceDescriptor,
1474 Size);
1475 MmFreeMemory(FullResourceDescriptor);
1476 if (Error != ERROR_SUCCESS)
1477 {
1478 DbgPrint((DPRINT_HWDETECT,
1479 "RegSetValue(Configuration Data) failed (Error %u)\n",
1480 (int)Error));
1481 return;
1482 }
1483
1484
1485 /* Detect ISA/BIOS devices */
1486 DetectBiosDisks(SystemKey, BusKey);
1487
1488 #if 0
1489 DetectBiosFloppyDisks(SystemKey, BusKey);
1490 #endif
1491
1492 DetectSerialPorts(BusKey);
1493
1494 #if 0
1495 DetectBiosParallelPorts();
1496 #endif
1497
1498 #if 0
1499 DetectBiosKeyboard(BusKey);
1500 #endif
1501
1502 DetectPS2Mouse(BusKey);
1503
1504 /* FIXME: Detect more ISA devices */
1505 }
1506
1507
1508 VOID
1509 DetectHardware(VOID)
1510 {
1511 HKEY SystemKey;
1512 U32 BusNumber = 0;
1513 S32 Error;
1514
1515 DbgPrint((DPRINT_HWDETECT, "DetectHardware()\n"));
1516
1517 HalpCalibrateStallExecution ();
1518
1519 /* Create the 'System' key */
1520 Error = RegCreateKey(NULL,
1521 "\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System",
1522 &SystemKey);
1523 if (Error != ERROR_SUCCESS)
1524 {
1525 DbgPrint((DPRINT_HWDETECT, "RegCreateKey() failed (Error %u)\n", (int)Error));
1526 return;
1527 }
1528
1529 #if 0
1530 DetectSystemData();
1531 #endif
1532 DetectCPUs(SystemKey);
1533
1534 /* Detect buses */
1535 #if 0
1536 DetectPciBios(&BusNumber);
1537 DetectApmBios(&BusNumber);
1538 #endif
1539 DetectPnpBios(SystemKey, &BusNumber);
1540 DetectIsaBios(SystemKey, &BusNumber);
1541 #if 0
1542 DetectAcpiBios(&BusNumber);
1543 #endif
1544
1545
1546 DbgPrint((DPRINT_HWDETECT, "DetectHardware() Done\n"));
1547
1548 #if 0
1549 printf("*** System stopped ***\n");
1550 for (;;);
1551 #endif
1552 }
1553
1554 /* EOF */