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