ReactOS Intel Mac compatibility commits, part 1/2, by Michael Steil.
[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 = 0;
941 PartialDescriptor->u.Interrupt.Vector = 6;
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 = 0;
1426 PartialDescriptor->u.Interrupt.Vector = Irq[i];
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 = 0;
1574 PartialDescriptor->u.Interrupt.Vector = Irq[i];
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
1625 WRITE_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA,
1626 0xF2);
1627
1628 StallExecutionProcessor(10000);
1629
1630 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
1631 if ((Status & 0x01) != 0x01)
1632 {
1633 /* PC/XT keyboard or no keyboard */
1634 return FALSE;
1635 }
1636
1637 Scancode = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA);
1638 if (Scancode != 0xFA)
1639 {
1640 /* No ACK received */
1641 return FALSE;
1642 }
1643
1644 StallExecutionProcessor(10000);
1645 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
1646 if ((Status & 0x01) != 0x01)
1647 {
1648 /* Found AT keyboard */
1649 return TRUE;
1650 }
1651
1652 Scancode = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA);
1653 if (Scancode != 0xAB)
1654 {
1655 /* No 0xAB received */
1656 return FALSE;
1657 }
1658
1659 StallExecutionProcessor(10000);
1660 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
1661 if ((Status & 0x01) != 0x01)
1662 {
1663 /* No byte in buffer */
1664 return FALSE;
1665 }
1666
1667 Scancode = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA);
1668 if (Scancode != 0x41)
1669 {
1670 /* No 0x41 received */
1671 return FALSE;
1672 }
1673
1674 /* Found MF-II keyboard */
1675 return TRUE;
1676 }
1677
1678
1679 static VOID
1680 DetectKeyboardPeripheral(FRLDRHKEY ControllerKey)
1681 {
1682 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
1683 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
1684 PCM_KEYBOARD_DEVICE_DATA KeyboardData;
1685 FRLDRHKEY PeripheralKey;
1686 ULONG Size;
1687 LONG Error;
1688
1689 /* HACK: don't call DetectKeyboardDevice() as it fails in Qemu 0.8.2 */
1690 if (TRUE || DetectKeyboardDevice())
1691 {
1692 /* Create controller key */
1693 Error = RegCreateKey(ControllerKey,
1694 L"KeyboardPeripheral\\0",
1695 &PeripheralKey);
1696 if (Error != ERROR_SUCCESS)
1697 {
1698 DbgPrint((DPRINT_HWDETECT, "Failed to create peripheral key\n"));
1699 return;
1700 }
1701 DbgPrint((DPRINT_HWDETECT, "Created key: KeyboardPeripheral\\0\n"));
1702
1703 /* Set 'ComponentInformation' value */
1704 SetComponentInformation(ControllerKey,
1705 0x28,
1706 0,
1707 0xFFFFFFFF);
1708
1709 /* Set 'Configuration Data' value */
1710 Size = sizeof(CM_FULL_RESOURCE_DESCRIPTOR) +
1711 sizeof(CM_KEYBOARD_DEVICE_DATA);
1712 FullResourceDescriptor = MmAllocateMemory(Size);
1713 if (FullResourceDescriptor == NULL)
1714 {
1715 DbgPrint((DPRINT_HWDETECT,
1716 "Failed to allocate resource descriptor\n"));
1717 return;
1718 }
1719
1720 /* Initialize resource descriptor */
1721 memset(FullResourceDescriptor, 0, Size);
1722 FullResourceDescriptor->InterfaceType = Isa;
1723 FullResourceDescriptor->BusNumber = 0;
1724 FullResourceDescriptor->PartialResourceList.Version = 1;
1725 FullResourceDescriptor->PartialResourceList.Revision = 1;
1726 FullResourceDescriptor->PartialResourceList.Count = 1;
1727
1728 PartialDescriptor = &FullResourceDescriptor->PartialResourceList.PartialDescriptors[0];
1729 PartialDescriptor->Type = CmResourceTypeDeviceSpecific;
1730 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
1731 PartialDescriptor->u.DeviceSpecificData.DataSize = sizeof(CM_KEYBOARD_DEVICE_DATA);
1732
1733 KeyboardData = (PCM_KEYBOARD_DEVICE_DATA)(PartialDescriptor + 1);
1734 KeyboardData->Version = 1;
1735 KeyboardData->Revision = 1;
1736 KeyboardData->Type = 4;
1737 KeyboardData->Subtype = 0;
1738 KeyboardData->KeyboardFlags = 0x20;
1739
1740 /* Set 'Configuration Data' value */
1741 Error = RegSetValue(PeripheralKey,
1742 L"Configuration Data",
1743 REG_FULL_RESOURCE_DESCRIPTOR,
1744 (PCHAR)FullResourceDescriptor,
1745 Size);
1746 MmFreeMemory(FullResourceDescriptor);
1747 if (Error != ERROR_SUCCESS)
1748 {
1749 DbgPrint((DPRINT_HWDETECT,
1750 "RegSetValue(Configuration Data) failed (Error %u)\n",
1751 (int)Error));
1752 }
1753
1754 /* Set 'Identifier' value */
1755 Error = RegSetValue(PeripheralKey,
1756 L"Identifier",
1757 REG_SZ,
1758 (PCHAR)L"PCAT_ENHANCED",
1759 14 * sizeof(WCHAR));
1760 if (Error != ERROR_SUCCESS)
1761 {
1762 DbgPrint((DPRINT_HWDETECT,
1763 "RegSetValue() failed (Error %u)\n",
1764 (int)Error));
1765 }
1766 }
1767 }
1768
1769
1770 static VOID
1771 DetectKeyboardController(FRLDRHKEY BusKey)
1772 {
1773 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
1774 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
1775 FRLDRHKEY ControllerKey;
1776 ULONG Size;
1777 LONG Error;
1778
1779 /* Create controller key */
1780 Error = RegCreateKey(BusKey,
1781 L"KeyboardController\\0",
1782 &ControllerKey);
1783 if (Error != ERROR_SUCCESS)
1784 {
1785 DbgPrint((DPRINT_HWDETECT, "Failed to create controller key\n"));
1786 return;
1787 }
1788 DbgPrint((DPRINT_HWDETECT, "Created key: KeyboardController\\0\n"));
1789
1790 /* Set 'ComponentInformation' value */
1791 SetComponentInformation(ControllerKey,
1792 0x28,
1793 0,
1794 0xFFFFFFFF);
1795
1796 /* Set 'Configuration Data' value */
1797 Size = sizeof(CM_FULL_RESOURCE_DESCRIPTOR) +
1798 2 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
1799 FullResourceDescriptor = MmAllocateMemory(Size);
1800 if (FullResourceDescriptor == NULL)
1801 {
1802 DbgPrint((DPRINT_HWDETECT,
1803 "Failed to allocate resource descriptor\n"));
1804 return;
1805 }
1806
1807 /* Initialize resource descriptor */
1808 memset(FullResourceDescriptor, 0, Size);
1809 FullResourceDescriptor->InterfaceType = Isa;
1810 FullResourceDescriptor->BusNumber = 0;
1811 FullResourceDescriptor->PartialResourceList.Version = 1;
1812 FullResourceDescriptor->PartialResourceList.Revision = 1;
1813 FullResourceDescriptor->PartialResourceList.Count = 3;
1814
1815 /* Set Interrupt */
1816 PartialDescriptor = &FullResourceDescriptor->PartialResourceList.PartialDescriptors[0];
1817 PartialDescriptor->Type = CmResourceTypeInterrupt;
1818 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
1819 PartialDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
1820 PartialDescriptor->u.Interrupt.Level = 0;
1821 PartialDescriptor->u.Interrupt.Vector = 1;
1822 PartialDescriptor->u.Interrupt.Affinity = 0xFFFFFFFF;
1823
1824 /* Set IO Port 0x60 */
1825 PartialDescriptor = &FullResourceDescriptor->PartialResourceList.PartialDescriptors[1];
1826 PartialDescriptor->Type = CmResourceTypePort;
1827 PartialDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1828 PartialDescriptor->Flags = CM_RESOURCE_PORT_IO;
1829 PartialDescriptor->u.Port.Start.LowPart = 0x60;
1830 PartialDescriptor->u.Port.Start.HighPart = 0x0;
1831 PartialDescriptor->u.Port.Length = 1;
1832
1833 /* Set IO Port 0x64 */
1834 PartialDescriptor = &FullResourceDescriptor->PartialResourceList.PartialDescriptors[2];
1835 PartialDescriptor->Type = CmResourceTypePort;
1836 PartialDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1837 PartialDescriptor->Flags = CM_RESOURCE_PORT_IO;
1838 PartialDescriptor->u.Port.Start.LowPart = 0x64;
1839 PartialDescriptor->u.Port.Start.HighPart = 0x0;
1840 PartialDescriptor->u.Port.Length = 1;
1841
1842 /* Set 'Configuration Data' value */
1843 Error = RegSetValue(ControllerKey,
1844 L"Configuration Data",
1845 REG_FULL_RESOURCE_DESCRIPTOR,
1846 (PCHAR)FullResourceDescriptor,
1847 Size);
1848 MmFreeMemory(FullResourceDescriptor);
1849 if (Error != ERROR_SUCCESS)
1850 {
1851 DbgPrint((DPRINT_HWDETECT,
1852 "RegSetValue(Configuration Data) failed (Error %u)\n",
1853 (int)Error));
1854 return;
1855 }
1856
1857 DetectKeyboardPeripheral(ControllerKey);
1858 }
1859
1860
1861 static VOID
1862 PS2ControllerWait(VOID)
1863 {
1864 ULONG Timeout;
1865 UCHAR Status;
1866
1867 for (Timeout = 0; Timeout < CONTROLLER_TIMEOUT; Timeout++)
1868 {
1869 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
1870 if ((Status & CONTROLLER_STATUS_INPUT_BUFFER_FULL) == 0)
1871 return;
1872
1873 /* Sleep for one millisecond */
1874 StallExecutionProcessor(1000);
1875 }
1876 }
1877
1878
1879 static BOOLEAN
1880 DetectPS2AuxPort(VOID)
1881 {
1882 ULONG Loops;
1883 UCHAR Scancode;
1884 UCHAR Status;
1885
1886 /* Put the value 0x5A in the output buffer using the
1887 * "WriteAuxiliary Device Output Buffer" command (0xD3).
1888 * Poll the Status Register for a while to see if the value really turns up
1889 * in the Data Register. If the KEYBOARD_STATUS_MOUSE_OBF bit is also set
1890 * to 1 in the Status Register, we assume this controller has an
1891 * Auxiliary Port (a.k.a. Mouse Port).
1892 */
1893 PS2ControllerWait();
1894 WRITE_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_CONTROL,
1895 CONTROLLER_COMMAND_WRITE_MOUSE_OUTPUT_BUFFER);
1896 PS2ControllerWait();
1897
1898 /* 0x5A is a random dummy value */
1899 WRITE_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA,
1900 0x5A);
1901
1902 for (Loops = 0; Loops < 10; Loops++)
1903 {
1904 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
1905
1906 if ((Status & CONTROLLER_STATUS_OUTPUT_BUFFER_FULL) != 0)
1907 {
1908 Scancode = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA);
1909 if ((Status & CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL) != 0)
1910 {
1911 return TRUE;
1912 }
1913 break;
1914 }
1915
1916 StallExecutionProcessor(10000);
1917 }
1918
1919 return FALSE;
1920 }
1921
1922
1923 static BOOLEAN
1924 DetectPS2AuxDevice(VOID)
1925 {
1926 UCHAR Scancode;
1927 UCHAR Status;
1928
1929 PS2ControllerWait();
1930 WRITE_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_CONTROL,
1931 CONTROLLER_COMMAND_WRITE_MOUSE);
1932 PS2ControllerWait();
1933
1934 /* Identify device */
1935 WRITE_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA,
1936 0xF2);
1937
1938 StallExecutionProcessor(10000);
1939
1940 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
1941 if ((Status & CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL) == 0)
1942 {
1943 return FALSE;
1944 }
1945
1946 Scancode = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA);
1947 if (Scancode != 0xFA)
1948 return FALSE;
1949
1950 StallExecutionProcessor(10000);
1951
1952 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
1953 if ((Status & CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL) == 0)
1954 {
1955 return FALSE;
1956 }
1957
1958 Scancode = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA);
1959 if (Scancode != 0x00)
1960 return FALSE;
1961
1962 return TRUE;
1963 }
1964
1965
1966 static VOID
1967 DetectPS2Mouse(FRLDRHKEY BusKey)
1968 {
1969 CM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
1970 FRLDRHKEY ControllerKey;
1971 FRLDRHKEY PeripheralKey;
1972 LONG Error;
1973
1974 if (DetectPS2AuxPort())
1975 {
1976 DbgPrint((DPRINT_HWDETECT, "Detected PS2 port\n"));
1977
1978 /* Create controller key */
1979 Error = RegCreateKey(BusKey,
1980 L"PointerController\\0",
1981 &ControllerKey);
1982 if (Error != ERROR_SUCCESS)
1983 {
1984 DbgPrint((DPRINT_HWDETECT, "Failed to create controller key\n"));
1985 return;
1986 }
1987 DbgPrint((DPRINT_HWDETECT, "Created key: PointerController\\0\n"));
1988
1989 /* Set 'ComponentInformation' value */
1990 SetComponentInformation(ControllerKey,
1991 0x20,
1992 0,
1993 0xFFFFFFFF);
1994
1995 memset(&FullResourceDescriptor, 0, sizeof(CM_FULL_RESOURCE_DESCRIPTOR));
1996
1997 /* Initialize resource descriptor */
1998 FullResourceDescriptor.InterfaceType = Isa;
1999 FullResourceDescriptor.BusNumber = 0;
2000 FullResourceDescriptor.PartialResourceList.Version = 1;
2001 FullResourceDescriptor.PartialResourceList.Revision = 1;
2002 FullResourceDescriptor.PartialResourceList.Count = 1;
2003
2004 /* Set Interrupt */
2005 FullResourceDescriptor.PartialResourceList.PartialDescriptors[0].Type = CmResourceTypeInterrupt;
2006 FullResourceDescriptor.PartialResourceList.PartialDescriptors[0].ShareDisposition = CmResourceShareUndetermined;
2007 FullResourceDescriptor.PartialResourceList.PartialDescriptors[0].Flags = CM_RESOURCE_INTERRUPT_LATCHED;
2008 FullResourceDescriptor.PartialResourceList.PartialDescriptors[0].u.Interrupt.Level = 0;
2009 FullResourceDescriptor.PartialResourceList.PartialDescriptors[0].u.Interrupt.Vector = 12;
2010 FullResourceDescriptor.PartialResourceList.PartialDescriptors[0].u.Interrupt.Affinity = 0xFFFFFFFF;
2011
2012 /* Set 'Configuration Data' value */
2013 Error = RegSetValue(ControllerKey,
2014 L"Configuration Data",
2015 REG_FULL_RESOURCE_DESCRIPTOR,
2016 (PCHAR)&FullResourceDescriptor,
2017 sizeof(CM_FULL_RESOURCE_DESCRIPTOR));
2018 if (Error != ERROR_SUCCESS)
2019 {
2020 DbgPrint((DPRINT_HWDETECT,
2021 "RegSetValue(Configuration Data) failed (Error %u)\n",
2022 (int)Error));
2023 return;
2024 }
2025
2026
2027 if (DetectPS2AuxDevice())
2028 {
2029 DbgPrint((DPRINT_HWDETECT, "Detected PS2 mouse\n"));
2030
2031 /* Create peripheral key */
2032 Error = RegCreateKey(ControllerKey,
2033 L"PointerPeripheral\\0",
2034 &PeripheralKey);
2035 if (Error != ERROR_SUCCESS)
2036 {
2037 DbgPrint((DPRINT_HWDETECT, "Failed to create peripheral key\n"));
2038 return;
2039 }
2040 DbgPrint((DPRINT_HWDETECT, "Created key: PointerPeripheral\\0\n"));
2041
2042 /* Set 'ComponentInformation' value */
2043 SetComponentInformation(PeripheralKey,
2044 0x20,
2045 0,
2046 0xFFFFFFFF);
2047
2048 /* Initialize resource descriptor */
2049 memset(&FullResourceDescriptor, 0, sizeof(CM_FULL_RESOURCE_DESCRIPTOR));
2050 FullResourceDescriptor.InterfaceType = Isa;
2051 FullResourceDescriptor.BusNumber = 0;
2052 FullResourceDescriptor.PartialResourceList.Version = 1;
2053 FullResourceDescriptor.PartialResourceList.Revision = 1;
2054 FullResourceDescriptor.PartialResourceList.Count = 0;
2055
2056 /* Set 'Configuration Data' value */
2057 Error = RegSetValue(PeripheralKey,
2058 L"Configuration Data",
2059 REG_FULL_RESOURCE_DESCRIPTOR,
2060 (PCHAR)&FullResourceDescriptor,
2061 sizeof(CM_FULL_RESOURCE_DESCRIPTOR) -
2062 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
2063 if (Error != ERROR_SUCCESS)
2064 {
2065 DbgPrint((DPRINT_HWDETECT,
2066 "RegSetValue(Configuration Data) failed (Error %u)\n",
2067 (int)Error));
2068 return;
2069 }
2070
2071 /* Set 'Identifier' value */
2072 Error = RegSetValue(PeripheralKey,
2073 L"Identifier",
2074 REG_SZ,
2075 (PCHAR)L"MICROSOFT PS2 MOUSE",
2076 20 * sizeof(WCHAR));
2077 if (Error != ERROR_SUCCESS)
2078 {
2079 DbgPrint((DPRINT_HWDETECT,
2080 "RegSetValue() failed (Error %u)\n",
2081 (int)Error));
2082 return;
2083 }
2084 }
2085 }
2086 }
2087
2088
2089 static VOID
2090 DetectDisplayController(FRLDRHKEY BusKey)
2091 {
2092 WCHAR Buffer[80];
2093 FRLDRHKEY ControllerKey;
2094 USHORT VesaVersion;
2095 LONG Error;
2096
2097 Error = RegCreateKey(BusKey,
2098 L"DisplayController\\0",
2099 &ControllerKey);
2100 if (Error != ERROR_SUCCESS)
2101 {
2102 DbgPrint((DPRINT_HWDETECT, "Failed to create controller key\n"));
2103 return;
2104 }
2105 DbgPrint((DPRINT_HWDETECT, "Created key: PointerController\\0\n"));
2106
2107 /* Set 'ComponentInformation' value */
2108 SetComponentInformation(ControllerKey,
2109 0x00,
2110 0,
2111 0xFFFFFFFF);
2112
2113 /* FIXME: Set 'ComponentInformation' value */
2114
2115 VesaVersion = BiosIsVesaSupported();
2116 if (VesaVersion != 0)
2117 {
2118 DbgPrint((DPRINT_HWDETECT,
2119 "VESA version %c.%c\n",
2120 (VesaVersion >> 8) + '0',
2121 (VesaVersion & 0xFF) + '0'));
2122 }
2123 else
2124 {
2125 DbgPrint((DPRINT_HWDETECT,
2126 "VESA not supported\n"));
2127 }
2128
2129 if (VesaVersion >= 0x0200)
2130 {
2131 wcscpy(Buffer,
2132 L"VBE Display");
2133 }
2134 else
2135 {
2136 wcscpy(Buffer,
2137 L"VGA Display");
2138 }
2139
2140 /* Set 'Identifier' value */
2141 Error = RegSetValue(ControllerKey,
2142 L"Identifier",
2143 REG_SZ,
2144 (PCHAR)Buffer,
2145 (wcslen(Buffer) + 1) * sizeof(WCHAR));
2146 if (Error != ERROR_SUCCESS)
2147 {
2148 DbgPrint((DPRINT_HWDETECT,
2149 "RegSetValue() failed (Error %u)\n",
2150 (int)Error));
2151 return;
2152 }
2153
2154 /* FIXME: Add display peripheral (monitor) data */
2155 }
2156
2157
2158 static VOID
2159 DetectIsaBios(FRLDRHKEY SystemKey, ULONG *BusNumber)
2160 {
2161 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
2162 WCHAR Buffer[80];
2163 FRLDRHKEY BusKey;
2164 ULONG Size;
2165 LONG Error;
2166
2167 /* Create new bus key */
2168 swprintf(Buffer,
2169 L"MultifunctionAdapter\\%u", *BusNumber);
2170 Error = RegCreateKey(SystemKey,
2171 Buffer,
2172 &BusKey);
2173 if (Error != ERROR_SUCCESS)
2174 {
2175 DbgPrint((DPRINT_HWDETECT, "RegCreateKey() failed (Error %u)\n", (int)Error));
2176 return;
2177 }
2178
2179 /* Set 'Component Information' value similar to my NT4 box */
2180 SetComponentInformation(BusKey,
2181 0x0,
2182 0x0,
2183 0xFFFFFFFF);
2184
2185 /* Increment bus number */
2186 (*BusNumber)++;
2187
2188 /* Set 'Identifier' value */
2189 Error = RegSetValue(BusKey,
2190 L"Identifier",
2191 REG_SZ,
2192 (PCHAR)L"ISA",
2193 4 * sizeof(WCHAR));
2194 if (Error != ERROR_SUCCESS)
2195 {
2196 DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error));
2197 return;
2198 }
2199
2200 /* Set 'Configuration Data' value */
2201 Size = sizeof(CM_FULL_RESOURCE_DESCRIPTOR) -
2202 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
2203 FullResourceDescriptor = MmAllocateMemory(Size);
2204 if (FullResourceDescriptor == NULL)
2205 {
2206 DbgPrint((DPRINT_HWDETECT,
2207 "Failed to allocate resource descriptor\n"));
2208 return;
2209 }
2210
2211 /* Initialize resource descriptor */
2212 memset(FullResourceDescriptor, 0, Size);
2213 FullResourceDescriptor->InterfaceType = Isa;
2214 FullResourceDescriptor->BusNumber = 0;
2215 FullResourceDescriptor->PartialResourceList.Version = 1;
2216 FullResourceDescriptor->PartialResourceList.Revision = 1;
2217 FullResourceDescriptor->PartialResourceList.Count = 0;
2218
2219 /* Set 'Configuration Data' value */
2220 Error = RegSetValue(BusKey,
2221 L"Configuration Data",
2222 REG_FULL_RESOURCE_DESCRIPTOR,
2223 (PCHAR) FullResourceDescriptor,
2224 Size);
2225 MmFreeMemory(FullResourceDescriptor);
2226 if (Error != ERROR_SUCCESS)
2227 {
2228 DbgPrint((DPRINT_HWDETECT,
2229 "RegSetValue(Configuration Data) failed (Error %u)\n",
2230 (int)Error));
2231 return;
2232 }
2233
2234 /* Detect ISA/BIOS devices */
2235 DetectBiosDisks(SystemKey, BusKey);
2236
2237 DetectBiosFloppyController(SystemKey, BusKey);
2238
2239 DetectSerialPorts(BusKey);
2240
2241 DetectParallelPorts(BusKey);
2242
2243 DetectKeyboardController(BusKey);
2244
2245 DetectPS2Mouse(BusKey);
2246
2247 DetectDisplayController(BusKey);
2248
2249 /* FIXME: Detect more ISA devices */
2250 }
2251
2252
2253 VOID
2254 PcHwDetect(VOID)
2255 {
2256 FRLDRHKEY SystemKey;
2257 ULONG BusNumber = 0;
2258 LONG Error;
2259
2260 DbgPrint((DPRINT_HWDETECT, "DetectHardware()\n"));
2261
2262 /* Create the 'System' key */
2263 Error = RegCreateKey(NULL,
2264 L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System",
2265 &SystemKey);
2266 if (Error != ERROR_SUCCESS)
2267 {
2268 DbgPrint((DPRINT_HWDETECT, "RegCreateKey() failed (Error %u)\n", (int)Error));
2269 return;
2270 }
2271
2272 #if 0
2273 DetectSystemData();
2274 #endif
2275 DetectCPUs(SystemKey);
2276
2277 /* Detect buses */
2278 DetectPciBios(SystemKey, &BusNumber);
2279 DetectApmBios(SystemKey, &BusNumber);
2280 DetectPnpBios(SystemKey, &BusNumber);
2281 DetectIsaBios(SystemKey, &BusNumber);
2282 DetectAcpiBios(SystemKey, &BusNumber);
2283
2284 DbgPrint((DPRINT_HWDETECT, "DetectHardware() Done\n"));
2285
2286 #if 0
2287 printf("*** System stopped ***\n");
2288 for (;;);
2289 #endif
2290 }
2291
2292 /* EOF */