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