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