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