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