f99e26780d64f6acbf837571f8a79a1075445609
[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 CHAR FileName[1];
437
438 if (!DissectArcPath(Path, FileName, &DriveNumber, &DrivePartition))
439 return EINVAL;
440
441 if (DrivePartition == 0xff)
442 {
443 /* This is a CD-ROM device */
444 SectorSize = 2048;
445 }
446 else
447 {
448 /* This is either a floppy disk device (DrivePartition == 0) or
449 * a hard disk device (DrivePartition != 0 && DrivePartition != 0xFF) but
450 * it doesn't matter which one because they both have 512 bytes per sector */
451 SectorSize = 512;
452 }
453
454 if (DrivePartition != 0xff && DrivePartition != 0)
455 {
456 if (!DiskGetPartitionEntry(DriveNumber, DrivePartition, &PartitionTableEntry))
457 return EINVAL;
458 SectorOffset = PartitionTableEntry.SectorCountBeforePartition;
459 SectorCount = PartitionTableEntry.PartitionSectorCount;
460 }
461
462 Context = MmHeapAlloc(sizeof(DISKCONTEXT));
463 if (!Context)
464 return ENOMEM;
465 Context->DriveNumber = DriveNumber;
466 Context->SectorSize = SectorSize;
467 Context->SectorOffset = SectorOffset;
468 Context->SectorCount = SectorCount;
469 Context->SectorNumber = 0;
470 FsSetDeviceSpecific(*FileId, Context);
471
472 return ESUCCESS;
473 }
474
475 static LONG DiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count)
476 {
477 DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
478 UCHAR* Ptr = (UCHAR*)Buffer;
479 ULONG i, Length;
480 BOOLEAN ret;
481
482 *Count = 0;
483 i = 0;
484 while (N > 0)
485 {
486 Length = N;
487 if (Length > Context->SectorSize)
488 Length = Context->SectorSize;
489 ret = MachDiskReadLogicalSectors(
490 Context->DriveNumber,
491 Context->SectorNumber + Context->SectorOffset + i,
492 1,
493 (PVOID)DISKREADBUFFER);
494 if (!ret)
495 return EIO;
496 RtlCopyMemory(Ptr, (PVOID)DISKREADBUFFER, Length);
497 Ptr += Length;
498 *Count += Length;
499 N -= Length;
500 i++;
501 }
502
503 return ESUCCESS;
504 }
505
506 static LONG DiskSeek(ULONG FileId, LARGE_INTEGER* Position, SEEKMODE SeekMode)
507 {
508 DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
509
510 if (SeekMode != SeekAbsolute)
511 return EINVAL;
512 if (Position->LowPart & (Context->SectorSize - 1))
513 return EINVAL;
514
515 /* FIXME: take HighPart into account */
516 Context->SectorNumber = Position->LowPart / Context->SectorSize;
517 return ESUCCESS;
518 }
519
520 static const DEVVTBL DiskVtbl = {
521 DiskClose,
522 DiskGetFileInformation,
523 DiskOpen,
524 DiskRead,
525 DiskSeek,
526 };
527
528 static VOID
529 GetHarddiskIdentifier(PCHAR Identifier,
530 ULONG DriveNumber)
531 {
532 PMASTER_BOOT_RECORD Mbr;
533 ULONG *Buffer;
534 ULONG i;
535 ULONG Checksum;
536 ULONG Signature;
537 CHAR ArcName[256];
538 PARTITION_TABLE_ENTRY PartitionTableEntry;
539
540 /* Read the MBR */
541 if (!MachDiskReadLogicalSectors(DriveNumber, 0ULL, 1, (PVOID)DISKREADBUFFER))
542 {
543 DPRINTM(DPRINT_HWDETECT, "Reading MBR failed\n");
544 return;
545 }
546
547 Buffer = (ULONG*)DISKREADBUFFER;
548 Mbr = (PMASTER_BOOT_RECORD)DISKREADBUFFER;
549
550 Signature = Mbr->Signature;
551 DPRINTM(DPRINT_HWDETECT, "Signature: %x\n", Signature);
552
553 /* Calculate the MBR checksum */
554 Checksum = 0;
555 for (i = 0; i < 128; i++)
556 {
557 Checksum += Buffer[i];
558 }
559 Checksum = ~Checksum + 1;
560 DPRINTM(DPRINT_HWDETECT, "Checksum: %x\n", Checksum);
561
562 /* Fill out the ARC disk block */
563 reactos_arc_disk_info[reactos_disk_count].Signature = Signature;
564 reactos_arc_disk_info[reactos_disk_count].CheckSum = Checksum;
565 sprintf(ArcName, "multi(0)disk(0)rdisk(%lu)", reactos_disk_count);
566 strcpy(reactos_arc_strings[reactos_disk_count], ArcName);
567 reactos_arc_disk_info[reactos_disk_count].ArcName =
568 reactos_arc_strings[reactos_disk_count];
569 reactos_disk_count++;
570
571 sprintf(ArcName, "multi(0)disk(0)rdisk(%lu)partition(0)", DriveNumber - 0x80);
572 FsRegisterDevice(ArcName, &DiskVtbl);
573
574 /* Add partitions */
575 i = 1;
576 DiskReportError(FALSE);
577 while (DiskGetPartitionEntry(DriveNumber, i, &PartitionTableEntry))
578 {
579 if (PartitionTableEntry.SystemIndicator != PARTITION_ENTRY_UNUSED)
580 {
581 sprintf(ArcName, "multi(0)disk(0)rdisk(%lu)partition(%lu)", DriveNumber - 0x80, i);
582 FsRegisterDevice(ArcName, &DiskVtbl);
583 }
584 i++;
585 }
586 DiskReportError(TRUE);
587
588 /* Convert checksum and signature to identifier string */
589 Identifier[0] = Hex[(Checksum >> 28) & 0x0F];
590 Identifier[1] = Hex[(Checksum >> 24) & 0x0F];
591 Identifier[2] = Hex[(Checksum >> 20) & 0x0F];
592 Identifier[3] = Hex[(Checksum >> 16) & 0x0F];
593 Identifier[4] = Hex[(Checksum >> 12) & 0x0F];
594 Identifier[5] = Hex[(Checksum >> 8) & 0x0F];
595 Identifier[6] = Hex[(Checksum >> 4) & 0x0F];
596 Identifier[7] = Hex[Checksum & 0x0F];
597 Identifier[8] = '-';
598 Identifier[9] = Hex[(Signature >> 28) & 0x0F];
599 Identifier[10] = Hex[(Signature >> 24) & 0x0F];
600 Identifier[11] = Hex[(Signature >> 20) & 0x0F];
601 Identifier[12] = Hex[(Signature >> 16) & 0x0F];
602 Identifier[13] = Hex[(Signature >> 12) & 0x0F];
603 Identifier[14] = Hex[(Signature >> 8) & 0x0F];
604 Identifier[15] = Hex[(Signature >> 4) & 0x0F];
605 Identifier[16] = Hex[Signature & 0x0F];
606 Identifier[17] = '-';
607 Identifier[18] = 'A';
608 Identifier[19] = 0;
609 DPRINTM(DPRINT_HWDETECT, "Identifier: %s\n", Identifier);
610 }
611
612 static ULONG
613 GetFloppyCount(VOID)
614 {
615 UCHAR Data;
616
617 WRITE_PORT_UCHAR((PUCHAR)0x70, 0x10);
618 Data = READ_PORT_UCHAR((PUCHAR)0x71);
619
620 return ((Data & 0xF0) ? 1 : 0) + ((Data & 0x0F) ? 1 : 0);
621 }
622
623
624 static UCHAR
625 GetFloppyType(UCHAR DriveNumber)
626 {
627 UCHAR Data;
628
629 WRITE_PORT_UCHAR((PUCHAR)0x70, 0x10);
630 Data = READ_PORT_UCHAR((PUCHAR)0x71);
631
632 if (DriveNumber == 0)
633 return Data >> 4;
634 else if (DriveNumber == 1)
635 return Data & 0x0F;
636
637 return 0;
638 }
639
640
641 static PVOID
642 GetInt1eTable(VOID)
643 {
644 PUSHORT SegPtr = (PUSHORT)0x7A;
645 PUSHORT OfsPtr = (PUSHORT)0x78;
646
647 return (PVOID)((ULONG_PTR)(((ULONG)(*SegPtr)) << 4) + (ULONG)(*OfsPtr));
648 }
649
650
651 static VOID
652 DetectBiosFloppyPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey)
653 {
654 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
655 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
656 PCM_FLOPPY_DEVICE_DATA FloppyData;
657 CHAR Identifier[20];
658 PCONFIGURATION_COMPONENT_DATA PeripheralKey;
659 ULONG Size;
660 ULONG FloppyNumber;
661 UCHAR FloppyType;
662 ULONG MaxDensity[6] = {0, 360, 1200, 720, 1440, 2880};
663 PUCHAR Ptr;
664
665 for (FloppyNumber = 0; FloppyNumber < 2; FloppyNumber++)
666 {
667 FloppyType = GetFloppyType(FloppyNumber);
668
669 if ((FloppyType > 5) || (FloppyType == 0))
670 continue;
671
672 DiskResetController(FloppyNumber);
673
674 Ptr = GetInt1eTable();
675
676 /* Set 'Identifier' value */
677 sprintf(Identifier, "FLOPPY%ld", FloppyNumber + 1);
678
679 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) +
680 sizeof(CM_FLOPPY_DEVICE_DATA);
681 PartialResourceList = MmHeapAlloc(Size);
682 if (PartialResourceList == NULL)
683 {
684 DPRINTM(DPRINT_HWDETECT,
685 "Failed to allocate resource descriptor\n");
686 return;
687 }
688
689 memset(PartialResourceList, 0, Size);
690 PartialResourceList->Version = 1;
691 PartialResourceList->Revision = 1;
692 PartialResourceList->Count = 1;
693
694 PartialDescriptor = &PartialResourceList->PartialDescriptors[0];
695 PartialDescriptor->Type = CmResourceTypeDeviceSpecific;
696 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
697 PartialDescriptor->u.DeviceSpecificData.DataSize = sizeof(CM_FLOPPY_DEVICE_DATA);
698
699 FloppyData = (PVOID)(((ULONG_PTR)PartialResourceList) + sizeof(CM_PARTIAL_RESOURCE_LIST));
700 FloppyData->Version = 2;
701 FloppyData->Revision = 0;
702 FloppyData->MaxDensity = MaxDensity[FloppyType];
703 FloppyData->MountDensity = 0;
704 RtlCopyMemory(&FloppyData->StepRateHeadUnloadTime,
705 Ptr,
706 11);
707 FloppyData->MaximumTrackValue = (FloppyType == 1) ? 39 : 79;
708 FloppyData->DataTransferRate = 0;
709
710 FldrCreateComponentKey(ControllerKey,
711 PeripheralClass,
712 FloppyDiskPeripheral,
713 Input | Output,
714 FloppyNumber,
715 0xFFFFFFFF,
716 Identifier,
717 PartialResourceList,
718 Size,
719 &PeripheralKey);
720
721 MmHeapFree(PartialResourceList);
722 }
723 }
724
725
726 static VOID
727 DetectBiosFloppyController(PCONFIGURATION_COMPONENT_DATA BusKey)
728 {
729 PCONFIGURATION_COMPONENT_DATA ControllerKey;
730 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
731 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
732 ULONG Size;
733 ULONG FloppyCount;
734
735 FloppyCount = GetFloppyCount();
736 DPRINTM(DPRINT_HWDETECT,
737 "Floppy count: %u\n",
738 FloppyCount);
739
740 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) +
741 2 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
742 PartialResourceList = MmHeapAlloc(Size);
743 if (PartialResourceList == NULL)
744 {
745 DPRINTM(DPRINT_HWDETECT,
746 "Failed to allocate resource descriptor\n");
747 return;
748 }
749 memset(PartialResourceList, 0, Size);
750
751 /* Initialize resource descriptor */
752 PartialResourceList->Version = 1;
753 PartialResourceList->Revision = 1;
754 PartialResourceList->Count = 3;
755
756 /* Set IO Port */
757 PartialDescriptor = &PartialResourceList->PartialDescriptors[0];
758 PartialDescriptor->Type = CmResourceTypePort;
759 PartialDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
760 PartialDescriptor->Flags = CM_RESOURCE_PORT_IO;
761 PartialDescriptor->u.Port.Start.LowPart = 0x03F0;
762 PartialDescriptor->u.Port.Start.HighPart = 0x0;
763 PartialDescriptor->u.Port.Length = 8;
764
765 /* Set Interrupt */
766 PartialDescriptor = &PartialResourceList->PartialDescriptors[1];
767 PartialDescriptor->Type = CmResourceTypeInterrupt;
768 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
769 PartialDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
770 PartialDescriptor->u.Interrupt.Level = 6;
771 PartialDescriptor->u.Interrupt.Vector = 6;
772 PartialDescriptor->u.Interrupt.Affinity = 0xFFFFFFFF;
773
774 /* Set DMA channel */
775 PartialDescriptor = &PartialResourceList->PartialDescriptors[2];
776 PartialDescriptor->Type = CmResourceTypeDma;
777 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
778 PartialDescriptor->Flags = 0;
779 PartialDescriptor->u.Dma.Channel = 2;
780 PartialDescriptor->u.Dma.Port = 0;
781
782 /* Create floppy disk controller */
783 FldrCreateComponentKey(BusKey,
784 ControllerClass,
785 DiskController,
786 Output | Input,
787 0x0,
788 0xFFFFFFFF,
789 NULL,
790 PartialResourceList,
791 Size,
792 &ControllerKey);
793 DPRINTM(DPRINT_HWDETECT, "Created key: DiskController\\0\n");
794
795 MmHeapFree(PartialResourceList);
796
797 if (FloppyCount) DetectBiosFloppyPeripheral(ControllerKey);
798 }
799
800 static PCONFIGURATION_COMPONENT_DATA
801 DetectSystem(VOID)
802 {
803 PCONFIGURATION_COMPONENT_DATA SystemKey;
804 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
805 PCM_INT13_DRIVE_PARAMETER Int13Drives;
806 GEOMETRY Geometry;
807 ULONG DiskCount;
808 ULONG Size;
809 ULONG i;
810 BOOLEAN Changed;
811
812 /* Count the number of visible drives */
813 DiskReportError(FALSE);
814 DiskCount = 0;
815
816 /* There are some really broken BIOSes out there. There are even BIOSes
817 * that happily report success when you ask them to read from non-existent
818 * harddisks. So, we set the buffer to known contents first, then try to
819 * read. If the BIOS reports success but the buffer contents haven't
820 * changed then we fail anyway */
821 memset((PVOID) DISKREADBUFFER, 0xcd, 512);
822 while (MachDiskReadLogicalSectors(0x80 + DiskCount, 0ULL, 1, (PVOID)DISKREADBUFFER))
823 {
824 Changed = FALSE;
825 for (i = 0; ! Changed && i < 512; i++)
826 {
827 Changed = ((PUCHAR)DISKREADBUFFER)[i] != 0xcd;
828 }
829 if (! Changed)
830 {
831 DPRINTM(DPRINT_HWDETECT, "BIOS reports success for disk %d but data didn't change\n",
832 (int)DiskCount);
833 break;
834 }
835 DiskCount++;
836 memset((PVOID) DISKREADBUFFER, 0xcd, 512);
837 }
838 DiskReportError(TRUE);
839 DPRINTM(DPRINT_HWDETECT, "BIOS reports %d harddisk%s\n",
840 (int)DiskCount, (DiskCount == 1) ? "": "s");
841
842 /* Allocate resource descriptor */
843 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) +
844 sizeof(CM_INT13_DRIVE_PARAMETER) * DiskCount;
845 PartialResourceList = MmHeapAlloc(Size);
846 if (PartialResourceList == NULL)
847 {
848 DPRINTM(DPRINT_HWDETECT,
849 "Failed to allocate resource descriptor\n");
850 return NULL;
851 }
852
853 /* Initialize resource descriptor */
854 memset(PartialResourceList, 0, Size);
855 PartialResourceList->Version = 1;
856 PartialResourceList->Revision = 1;
857 PartialResourceList->Count = 1;
858 PartialResourceList->PartialDescriptors[0].Type = CmResourceTypeDeviceSpecific;
859 PartialResourceList->PartialDescriptors[0].ShareDisposition = 0;
860 PartialResourceList->PartialDescriptors[0].Flags = 0;
861 PartialResourceList->PartialDescriptors[0].u.DeviceSpecificData.DataSize =
862 sizeof(CM_INT13_DRIVE_PARAMETER) * DiskCount;
863
864 /* Get harddisk Int13 geometry data */
865 Int13Drives = (PVOID)(((ULONG_PTR)PartialResourceList) + sizeof(CM_PARTIAL_RESOURCE_LIST));
866 for (i = 0; i < DiskCount; i++)
867 {
868 if (MachDiskGetDriveGeometry(0x80 + i, &Geometry))
869 {
870 Int13Drives[i].DriveSelect = 0x80 + i;
871 Int13Drives[i].MaxCylinders = Geometry.Cylinders - 1;
872 Int13Drives[i].SectorsPerTrack = Geometry.Sectors;
873 Int13Drives[i].MaxHeads = Geometry.Heads - 1;
874 Int13Drives[i].NumberDrives = DiskCount;
875
876 DPRINTM(DPRINT_HWDETECT,
877 "Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n",
878 0x80 + i,
879 Geometry.Cylinders - 1,
880 Geometry.Heads -1,
881 Geometry.Sectors,
882 Geometry.BytesPerSector);
883 }
884 }
885
886 FldrCreateComponentKey(NULL,
887 SystemClass,
888 MaximumType,
889 0x0,
890 0x0,
891 0xFFFFFFFF,
892 NULL,
893 PartialResourceList,
894 Size,
895 &SystemKey);
896
897 MmHeapFree(PartialResourceList);
898
899 return SystemKey;
900 }
901
902 static ULONG
903 GetDiskCount(PCONFIGURATION_COMPONENT_DATA BusKey)
904 {
905 PCONFIGURATION_COMPONENT_DATA System;
906 ULONG ConfigurationDataLength;
907 ULONG DiskCount = 0;
908
909 //
910 // Get root component
911 //
912 System = BusKey;
913 while (System->Parent)
914 System = System->Parent;
915
916 //
917 // Get root configuration data length
918 //
919 ConfigurationDataLength = System->ComponentEntry.ConfigurationDataLength;
920
921 //
922 // We assume that nothing wrong happened, and that configuration
923 // only consists of one CM_PARTIAL_RESOURCE_LIST entry, followed
924 // by n entries of CM_INT13_DRIVE_PARAMETER
925 //
926 if (ConfigurationDataLength > 0)
927 DiskCount = (ConfigurationDataLength - sizeof(CM_PARTIAL_RESOURCE_LIST))
928 / sizeof(CM_INT13_DRIVE_PARAMETER);
929
930 //
931 // Return number of disks
932 //
933 DPRINTM(DPRINT_HWDETECT, "Retrieving %lu INT13 disks\\0\n", DiskCount);
934 return DiskCount;
935 };
936
937 static VOID
938 DetectBiosDisks(PCONFIGURATION_COMPONENT_DATA BusKey)
939 {
940 PCONFIGURATION_COMPONENT_DATA DiskKey, ControllerKey;
941 BOOLEAN BootDriveReported = FALSE;
942 ULONG i;
943 ULONG DiskCount = GetDiskCount(BusKey);
944 CHAR BootPath[512];
945
946 FldrCreateComponentKey(BusKey,
947 ControllerClass,
948 DiskController,
949 Output | Input,
950 0x0,
951 0xFFFFFFFF,
952 NULL,
953 NULL,
954 0,
955 &ControllerKey);
956 DPRINTM(DPRINT_HWDETECT, "Created key: DiskController\\0\n");
957
958 /* Create and fill subkey for each harddisk */
959 for (i = 0; i < DiskCount; i++)
960 {
961 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
962 ULONG Size;
963 CHAR Identifier[20];
964
965 if (BootDrive == 0x80 + i)
966 BootDriveReported = TRUE;
967
968 /* Get disk values */
969 PartialResourceList = GetHarddiskConfigurationData(0x80 + i, &Size);
970 GetHarddiskIdentifier(Identifier, 0x80 + i);
971
972 /* Create disk key */
973 FldrCreateComponentKey(ControllerKey,
974 PeripheralClass,
975 DiskPeripheral,
976 Output | Input,
977 0x0,
978 0xFFFFFFFF,
979 Identifier,
980 PartialResourceList,
981 Size,
982 &DiskKey);
983 }
984
985 /* Get the drive we're booting from */
986 MachDiskGetBootPath(BootPath, sizeof(BootPath));
987
988 /* Add it, if it's a floppy or cdrom */
989 if ((BootDrive >= 0x80 && !BootDriveReported) ||
990 DiskIsDriveRemovable(BootDrive))
991 {
992 /* TODO: Check if it's really a cdrom drive */
993 ULONG* Buffer;
994 ULONG Checksum = 0;
995
996 /* Read the MBR */
997 if (!MachDiskReadLogicalSectors(BootDrive, 16ULL, 1, (PVOID)DISKREADBUFFER))
998 {
999 DPRINTM(DPRINT_HWDETECT, "Reading MBR failed\n");
1000 return;
1001 }
1002
1003 Buffer = (ULONG*)DISKREADBUFFER;
1004
1005 /* Calculate the MBR checksum */
1006 for (i = 0; i < 2048 / sizeof(ULONG); i++) Checksum += Buffer[i];
1007 DPRINTM(DPRINT_HWDETECT, "Checksum: %x\n", Checksum);
1008
1009 /* Fill out the ARC disk block */
1010 reactos_arc_disk_info[reactos_disk_count].CheckSum = Checksum;
1011 strcpy(reactos_arc_strings[reactos_disk_count], BootPath);
1012 reactos_arc_disk_info[reactos_disk_count].ArcName =
1013 reactos_arc_strings[reactos_disk_count];
1014 reactos_disk_count++;
1015
1016 FsRegisterDevice(BootPath, &DiskVtbl);
1017 }
1018 }
1019
1020 static VOID
1021 InitializeSerialPort(PUCHAR Port,
1022 ULONG LineControl)
1023 {
1024 WRITE_PORT_UCHAR(Port + 3, 0x80); /* set DLAB on */
1025 WRITE_PORT_UCHAR(Port, 0x60); /* speed LO byte */
1026 WRITE_PORT_UCHAR(Port + 1, 0); /* speed HI byte */
1027 WRITE_PORT_UCHAR(Port + 3, LineControl);
1028 WRITE_PORT_UCHAR(Port + 1, 0); /* set comm and DLAB to 0 */
1029 WRITE_PORT_UCHAR(Port + 4, 0x09); /* DR int enable */
1030 READ_PORT_UCHAR(Port + 5); /* clear error bits */
1031 }
1032
1033
1034 static ULONG
1035 DetectSerialMouse(PUCHAR Port)
1036 {
1037 CHAR Buffer[4];
1038 ULONG i;
1039 ULONG TimeOut;
1040 UCHAR LineControl;
1041
1042 /* Shutdown mouse or something like that */
1043 LineControl = READ_PORT_UCHAR(Port + 4);
1044 WRITE_PORT_UCHAR(Port + 4, (LineControl & ~0x02) | 0x01);
1045 StallExecutionProcessor(100000);
1046
1047 /*
1048 * Clear buffer
1049 * Maybe there is no serial port although BIOS reported one (this
1050 * is the case on Apple hardware), or the serial port is misbehaving,
1051 * therefore we must give up after some time.
1052 */
1053 TimeOut = 200;
1054 while (READ_PORT_UCHAR(Port + 5) & 0x01)
1055 {
1056 if (--TimeOut == 0)
1057 return MOUSE_TYPE_NONE;
1058 READ_PORT_UCHAR(Port);
1059 }
1060
1061 /*
1062 * Send modem control with 'Data Terminal Ready', 'Request To Send' and
1063 * 'Output Line 2' message. This enables mouse to identify.
1064 */
1065 WRITE_PORT_UCHAR(Port + 4, 0x0b);
1066
1067 /* Wait 10 milliseconds for the mouse getting ready */
1068 StallExecutionProcessor(10000);
1069
1070 /* Read first four bytes, which contains Microsoft Mouse signs */
1071 TimeOut = 200;
1072 for (i = 0; i < 4; i++)
1073 {
1074 while (((READ_PORT_UCHAR(Port + 5) & 1) == 0) && (TimeOut > 0))
1075 {
1076 StallExecutionProcessor(1000);
1077 --TimeOut;
1078 if (TimeOut == 0)
1079 return MOUSE_TYPE_NONE;
1080 }
1081 Buffer[i] = READ_PORT_UCHAR(Port);
1082 }
1083
1084 DPRINTM(DPRINT_HWDETECT,
1085 "Mouse data: %x %x %x %x\n",
1086 Buffer[0],Buffer[1],Buffer[2],Buffer[3]);
1087
1088 /* Check that four bytes for signs */
1089 for (i = 0; i < 4; ++i)
1090 {
1091 if (Buffer[i] == 'B')
1092 {
1093 /* Sign for Microsoft Ballpoint */
1094 // DbgPrint("Microsoft Ballpoint device detected\n");
1095 // DbgPrint("THIS DEVICE IS NOT SUPPORTED, YET\n");
1096 return MOUSE_TYPE_NONE;
1097 }
1098 else if (Buffer[i] == 'M')
1099 {
1100 /* Sign for Microsoft Mouse protocol followed by button specifier */
1101 if (i == 3)
1102 {
1103 /* Overflow Error */
1104 return MOUSE_TYPE_NONE;
1105 }
1106
1107 switch (Buffer[i + 1])
1108 {
1109 case '3':
1110 DPRINTM(DPRINT_HWDETECT,
1111 "Microsoft Mouse with 3-buttons detected\n");
1112 return MOUSE_TYPE_LOGITECH;
1113
1114 case 'Z':
1115 DPRINTM(DPRINT_HWDETECT,
1116 "Microsoft Wheel Mouse detected\n");
1117 return MOUSE_TYPE_WHEELZ;
1118
1119 /* case '2': */
1120 default:
1121 DPRINTM(DPRINT_HWDETECT,
1122 "Microsoft Mouse with 2-buttons detected\n");
1123 return MOUSE_TYPE_MICROSOFT;
1124 }
1125 }
1126 }
1127
1128 return MOUSE_TYPE_NONE;
1129 }
1130
1131
1132 static ULONG
1133 GetSerialMousePnpId(PUCHAR Port, char *Buffer)
1134 {
1135 ULONG TimeOut;
1136 ULONG i = 0;
1137 char c;
1138 char x;
1139
1140 WRITE_PORT_UCHAR(Port + 4, 0x09);
1141
1142 /* Wait 10 milliseconds for the mouse getting ready */
1143 StallExecutionProcessor(10000);
1144
1145 WRITE_PORT_UCHAR(Port + 4, 0x0b);
1146
1147 StallExecutionProcessor(10000);
1148
1149 for (;;)
1150 {
1151 TimeOut = 200;
1152 while (((READ_PORT_UCHAR(Port + 5) & 1) == 0) && (TimeOut > 0))
1153 {
1154 StallExecutionProcessor(1000);
1155 --TimeOut;
1156 if (TimeOut == 0)
1157 {
1158 return 0;
1159 }
1160 }
1161
1162 c = READ_PORT_UCHAR(Port);
1163 if (c == 0x08 || c == 0x28)
1164 break;
1165 }
1166
1167 Buffer[i++] = c;
1168 x = c + 1;
1169
1170 for (;;)
1171 {
1172 TimeOut = 200;
1173 while (((READ_PORT_UCHAR(Port + 5) & 1) == 0) && (TimeOut > 0))
1174 {
1175 StallExecutionProcessor(1000);
1176 --TimeOut;
1177 if (TimeOut == 0)
1178 return 0;
1179 }
1180 c = READ_PORT_UCHAR(Port);
1181 Buffer[i++] = c;
1182 if (c == x)
1183 break;
1184 if (i >= 256)
1185 break;
1186 }
1187
1188 return i;
1189 }
1190
1191
1192 static VOID
1193 DetectSerialPointerPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey,
1194 PUCHAR Base)
1195 {
1196 CM_PARTIAL_RESOURCE_LIST PartialResourceList;
1197 char Buffer[256];
1198 CHAR Identifier[256];
1199 PCONFIGURATION_COMPONENT_DATA PeripheralKey;
1200 ULONG MouseType;
1201 ULONG Length;
1202 ULONG i;
1203 ULONG j;
1204 ULONG k;
1205
1206 DPRINTM(DPRINT_HWDETECT,
1207 "DetectSerialPointerPeripheral()\n");
1208
1209 Identifier[0] = 0;
1210
1211 InitializeSerialPort(Base, 2);
1212 MouseType = DetectSerialMouse(Base);
1213
1214 if (MouseType != MOUSE_TYPE_NONE)
1215 {
1216 Length = GetSerialMousePnpId(Base, Buffer);
1217 DPRINTM(DPRINT_HWDETECT,
1218 "PnP ID length: %u\n",
1219 Length);
1220
1221 if (Length != 0)
1222 {
1223 /* Convert PnP sting to ASCII */
1224 if (Buffer[0] == 0x08)
1225 {
1226 for (i = 0; i < Length; i++)
1227 Buffer[i] += 0x20;
1228 }
1229 Buffer[Length] = 0;
1230
1231 DPRINTM(DPRINT_HWDETECT,
1232 "PnP ID string: %s\n",
1233 Buffer);
1234
1235 /* Copy PnpId string */
1236 for (i = 0; i < 7; i++)
1237 {
1238 Identifier[i] = Buffer[3+i];
1239 }
1240 memcpy(&Identifier[7],
1241 L" - ",
1242 3 * sizeof(WCHAR));
1243
1244 /* Skip device serial number */
1245 i = 10;
1246 if (Buffer[i] == '\\')
1247 {
1248 for (j = ++i; i < Length; ++i)
1249 {
1250 if (Buffer[i] == '\\')
1251 break;
1252 }
1253 if (i >= Length)
1254 i -= 3;
1255 }
1256
1257 /* Skip PnP class */
1258 if (Buffer[i] == '\\')
1259 {
1260 for (j = ++i; i < Length; ++i)
1261 {
1262 if (Buffer[i] == '\\')
1263 break;
1264 }
1265
1266 if (i >= Length)
1267 i -= 3;
1268 }
1269
1270 /* Skip compatible PnP Id */
1271 if (Buffer[i] == '\\')
1272 {
1273 for (j = ++i; i < Length; ++i)
1274 {
1275 if (Buffer[i] == '\\')
1276 break;
1277 }
1278 if (Buffer[j] == '*')
1279 ++j;
1280 if (i >= Length)
1281 i -= 3;
1282 }
1283
1284 /* Get product description */
1285 if (Buffer[i] == '\\')
1286 {
1287 for (j = ++i; i < Length; ++i)
1288 {
1289 if (Buffer[i] == ';')
1290 break;
1291 }
1292 if (i >= Length)
1293 i -= 3;
1294 if (i > j + 1)
1295 {
1296 for (k = 0; k < i - j; k++)
1297 {
1298 Identifier[k + 10] = Buffer[k + j];
1299 }
1300 Identifier[10 + (i-j)] = 0;
1301 }
1302 }
1303
1304 DPRINTM(DPRINT_HWDETECT,
1305 "Identifier string: %s\n",
1306 Identifier);
1307 }
1308
1309 if (Length == 0 || strlen(Identifier) < 11)
1310 {
1311 switch (MouseType)
1312 {
1313 case MOUSE_TYPE_LOGITECH:
1314 strcpy (Identifier,
1315 "LOGITECH SERIAL MOUSE");
1316 break;
1317
1318 case MOUSE_TYPE_WHEELZ:
1319 strcpy (Identifier,
1320 "MICROSOFT SERIAL MOUSE WITH WHEEL");
1321 break;
1322
1323 case MOUSE_TYPE_MICROSOFT:
1324 default:
1325 strcpy (Identifier,
1326 "MICROSOFT SERIAL MOUSE");
1327 break;
1328 }
1329 }
1330
1331 /* Set 'Configuration Data' value */
1332 memset(&PartialResourceList, 0, sizeof(CM_PARTIAL_RESOURCE_LIST));
1333 PartialResourceList.Version = 1;
1334 PartialResourceList.Revision = 1;
1335 PartialResourceList.Count = 0;
1336
1337 /* Create 'PointerPeripheral' key */
1338 FldrCreateComponentKey(ControllerKey,
1339 PeripheralClass,
1340 PointerPeripheral,
1341 Input,
1342 0x0,
1343 0xFFFFFFFF,
1344 Identifier,
1345 &PartialResourceList,
1346 sizeof(CM_PARTIAL_RESOURCE_LIST) -
1347 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR),
1348 &PeripheralKey);
1349
1350 DPRINTM(DPRINT_HWDETECT,
1351 "Created key: PointerPeripheral\\0\n");
1352 }
1353 }
1354
1355
1356 static VOID
1357 DetectSerialPorts(PCONFIGURATION_COMPONENT_DATA BusKey)
1358 {
1359 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
1360 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
1361 PCM_SERIAL_DEVICE_DATA SerialDeviceData;
1362 ULONG Irq[4] = {4, 3, 4, 3};
1363 ULONG Base;
1364 CHAR Buffer[80];
1365 PUSHORT BasePtr;
1366 ULONG ControllerNumber = 0;
1367 PCONFIGURATION_COMPONENT_DATA ControllerKey;
1368 ULONG i;
1369 ULONG Size;
1370
1371 DPRINTM(DPRINT_HWDETECT, "DetectSerialPorts()\n");
1372
1373 ControllerNumber = 0;
1374 BasePtr = (PUSHORT)0x400;
1375 for (i = 0; i < 4; i++, BasePtr++)
1376 {
1377 Base = (ULONG)*BasePtr;
1378 if (Base == 0)
1379 continue;
1380
1381 DPRINTM(DPRINT_HWDETECT,
1382 "Found COM%u port at 0x%x\n",
1383 i + 1,
1384 Base);
1385
1386 /* Set 'Identifier' value */
1387 sprintf(Buffer, "COM%ld", i + 1);
1388
1389 /* Build full device descriptor */
1390 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) +
1391 2 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) +
1392 sizeof(CM_SERIAL_DEVICE_DATA);
1393 PartialResourceList = MmHeapAlloc(Size);
1394 if (PartialResourceList == NULL)
1395 {
1396 DPRINTM(DPRINT_HWDETECT,
1397 "Failed to allocate resource descriptor\n");
1398 continue;
1399 }
1400 memset(PartialResourceList, 0, Size);
1401
1402 /* Initialize resource descriptor */
1403 PartialResourceList->Version = 1;
1404 PartialResourceList->Revision = 1;
1405 PartialResourceList->Count = 3;
1406
1407 /* Set IO Port */
1408 PartialDescriptor = &PartialResourceList->PartialDescriptors[0];
1409 PartialDescriptor->Type = CmResourceTypePort;
1410 PartialDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1411 PartialDescriptor->Flags = CM_RESOURCE_PORT_IO;
1412 PartialDescriptor->u.Port.Start.LowPart = Base;
1413 PartialDescriptor->u.Port.Start.HighPart = 0x0;
1414 PartialDescriptor->u.Port.Length = 7;
1415
1416 /* Set Interrupt */
1417 PartialDescriptor = &PartialResourceList->PartialDescriptors[1];
1418 PartialDescriptor->Type = CmResourceTypeInterrupt;
1419 PartialDescriptor->ShareDisposition = CmResourceShareShared;
1420 PartialDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
1421 PartialDescriptor->u.Interrupt.Level = Irq[i];
1422 PartialDescriptor->u.Interrupt.Vector = Irq[i];
1423 PartialDescriptor->u.Interrupt.Affinity = 0xFFFFFFFF;
1424
1425 /* Set serial data (device specific) */
1426 PartialDescriptor = &PartialResourceList->PartialDescriptors[2];
1427 PartialDescriptor->Type = CmResourceTypeDeviceSpecific;
1428 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
1429 PartialDescriptor->Flags = 0;
1430 PartialDescriptor->u.DeviceSpecificData.DataSize = sizeof(CM_SERIAL_DEVICE_DATA);
1431
1432 SerialDeviceData =
1433 (PCM_SERIAL_DEVICE_DATA)&PartialResourceList->PartialDescriptors[3];
1434 SerialDeviceData->BaudClock = 1843200; /* UART Clock frequency (Hertz) */
1435
1436 /* Create controller key */
1437 FldrCreateComponentKey(BusKey,
1438 ControllerClass,
1439 SerialController,
1440 Output | Input | ConsoleIn | ConsoleOut,
1441 ControllerNumber,
1442 0xFFFFFFFF,
1443 Buffer,
1444 PartialResourceList,
1445 Size,
1446 &ControllerKey);
1447
1448 MmHeapFree(PartialResourceList);
1449
1450 if (!Rs232PortInUse(Base))
1451 {
1452 /* Detect serial mouse */
1453 DetectSerialPointerPeripheral(ControllerKey, UlongToPtr(Base));
1454 }
1455
1456 ControllerNumber++;
1457 }
1458 }
1459
1460
1461 static VOID
1462 DetectParallelPorts(PCONFIGURATION_COMPONENT_DATA BusKey)
1463 {
1464 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
1465 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
1466 ULONG Irq[3] = {7, 5, (ULONG)-1};
1467 CHAR Buffer[80];
1468 PCONFIGURATION_COMPONENT_DATA ControllerKey;
1469 PUSHORT BasePtr;
1470 ULONG Base;
1471 ULONG ControllerNumber;
1472 ULONG i;
1473 ULONG Size;
1474
1475 DPRINTM(DPRINT_HWDETECT, "DetectParallelPorts() called\n");
1476
1477 ControllerNumber = 0;
1478 BasePtr = (PUSHORT)0x408;
1479 for (i = 0; i < 3; i++, BasePtr++)
1480 {
1481 Base = (ULONG)*BasePtr;
1482 if (Base == 0)
1483 continue;
1484
1485 DPRINTM(DPRINT_HWDETECT,
1486 "Parallel port %u: %x\n",
1487 ControllerNumber,
1488 Base);
1489
1490 /* Set 'Identifier' value */
1491 sprintf(Buffer, "PARALLEL%ld", i + 1);
1492
1493 /* Build full device descriptor */
1494 Size = sizeof(CM_PARTIAL_RESOURCE_LIST);
1495 if (Irq[i] != (ULONG)-1)
1496 Size += sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
1497
1498 PartialResourceList = MmHeapAlloc(Size);
1499 if (PartialResourceList == NULL)
1500 {
1501 DPRINTM(DPRINT_HWDETECT,
1502 "Failed to allocate resource descriptor\n");
1503 continue;
1504 }
1505 memset(PartialResourceList, 0, Size);
1506
1507 /* Initialize resource descriptor */
1508 PartialResourceList->Version = 1;
1509 PartialResourceList->Revision = 1;
1510 PartialResourceList->Count = (Irq[i] != (ULONG)-1) ? 2 : 1;
1511
1512 /* Set IO Port */
1513 PartialDescriptor = &PartialResourceList->PartialDescriptors[0];
1514 PartialDescriptor->Type = CmResourceTypePort;
1515 PartialDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1516 PartialDescriptor->Flags = CM_RESOURCE_PORT_IO;
1517 PartialDescriptor->u.Port.Start.LowPart = Base;
1518 PartialDescriptor->u.Port.Start.HighPart = 0x0;
1519 PartialDescriptor->u.Port.Length = 3;
1520
1521 /* Set Interrupt */
1522 if (Irq[i] != (ULONG)-1)
1523 {
1524 PartialDescriptor = &PartialResourceList->PartialDescriptors[1];
1525 PartialDescriptor->Type = CmResourceTypeInterrupt;
1526 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
1527 PartialDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
1528 PartialDescriptor->u.Interrupt.Level = Irq[i];
1529 PartialDescriptor->u.Interrupt.Vector = Irq[i];
1530 PartialDescriptor->u.Interrupt.Affinity = 0xFFFFFFFF;
1531 }
1532
1533 /* Create controller key */
1534 FldrCreateComponentKey(BusKey,
1535 ControllerClass,
1536 ParallelController,
1537 Output,
1538 ControllerNumber,
1539 0xFFFFFFFF,
1540 Buffer,
1541 PartialResourceList,
1542 Size,
1543 &ControllerKey);
1544
1545 MmHeapFree(PartialResourceList);
1546
1547 ControllerNumber++;
1548 }
1549
1550 DPRINTM(DPRINT_HWDETECT, "DetectParallelPorts() done\n");
1551 }
1552
1553
1554 static BOOLEAN
1555 DetectKeyboardDevice(VOID)
1556 {
1557 UCHAR Status;
1558 UCHAR Scancode;
1559 ULONG Loops;
1560 BOOLEAN Result = TRUE;
1561
1562 /* Identify device */
1563 WRITE_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA,
1564 0xF2);
1565
1566 /* Wait for reply */
1567 for (Loops = 0; Loops < 100; Loops++)
1568 {
1569 StallExecutionProcessor(10000);
1570 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
1571 if ((Status & CONTROLLER_STATUS_OUTPUT_BUFFER_FULL) != 0)
1572 break;
1573 }
1574
1575 if ((Status & CONTROLLER_STATUS_OUTPUT_BUFFER_FULL) == 0)
1576 {
1577 /* PC/XT keyboard or no keyboard */
1578 Result = FALSE;
1579 }
1580
1581 Scancode = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA);
1582 if (Scancode != 0xFA)
1583 {
1584 /* No ACK received */
1585 Result = FALSE;
1586 }
1587
1588 StallExecutionProcessor(10000);
1589
1590 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
1591 if ((Status & CONTROLLER_STATUS_OUTPUT_BUFFER_FULL) == 0)
1592 {
1593 /* Found AT keyboard */
1594 return Result;
1595 }
1596
1597 Scancode = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA);
1598 if (Scancode != 0xAB)
1599 {
1600 /* No 0xAB received */
1601 Result = FALSE;
1602 }
1603
1604 StallExecutionProcessor(10000);
1605
1606 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
1607 if ((Status & CONTROLLER_STATUS_OUTPUT_BUFFER_FULL) == 0)
1608 {
1609 /* No byte in buffer */
1610 Result = FALSE;
1611 }
1612
1613 Scancode = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA);
1614 if (Scancode != 0x41)
1615 {
1616 /* No 0x41 received */
1617 Result = FALSE;
1618 }
1619
1620 /* Found MF-II keyboard */
1621 return Result;
1622 }
1623
1624
1625 static VOID
1626 DetectKeyboardPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey)
1627 {
1628 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
1629 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
1630 PCM_KEYBOARD_DEVICE_DATA KeyboardData;
1631 PCONFIGURATION_COMPONENT_DATA PeripheralKey;
1632 ULONG Size;
1633
1634 /* HACK: don't call DetectKeyboardDevice() as it fails in Qemu 0.8.2 */
1635 if (TRUE || DetectKeyboardDevice())
1636 {
1637 /* Set 'Configuration Data' value */
1638 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) +
1639 sizeof(CM_KEYBOARD_DEVICE_DATA);
1640 PartialResourceList = MmHeapAlloc(Size);
1641 if (PartialResourceList == NULL)
1642 {
1643 DPRINTM(DPRINT_HWDETECT,
1644 "Failed to allocate resource descriptor\n");
1645 return;
1646 }
1647
1648 /* Initialize resource descriptor */
1649 memset(PartialResourceList, 0, Size);
1650 PartialResourceList->Version = 1;
1651 PartialResourceList->Revision = 1;
1652 PartialResourceList->Count = 1;
1653
1654 PartialDescriptor = &PartialResourceList->PartialDescriptors[0];
1655 PartialDescriptor->Type = CmResourceTypeDeviceSpecific;
1656 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
1657 PartialDescriptor->u.DeviceSpecificData.DataSize = sizeof(CM_KEYBOARD_DEVICE_DATA);
1658
1659 KeyboardData = (PCM_KEYBOARD_DEVICE_DATA)(PartialDescriptor + 1);
1660 KeyboardData->Version = 1;
1661 KeyboardData->Revision = 1;
1662 KeyboardData->Type = 4;
1663 KeyboardData->Subtype = 0;
1664 KeyboardData->KeyboardFlags = 0x20;
1665
1666 /* Create controller key */
1667 FldrCreateComponentKey(ControllerKey,
1668 PeripheralClass,
1669 KeyboardPeripheral,
1670 Input | ConsoleIn,
1671 0x0,
1672 0xFFFFFFFF,
1673 "PCAT_ENHANCED",
1674 PartialResourceList,
1675 Size,
1676 &PeripheralKey);
1677 DPRINTM(DPRINT_HWDETECT, "Created key: KeyboardPeripheral\\0\n");
1678
1679 MmHeapFree(PartialResourceList);
1680 }
1681 }
1682
1683
1684 static VOID
1685 DetectKeyboardController(PCONFIGURATION_COMPONENT_DATA BusKey)
1686 {
1687 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
1688 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
1689 PCONFIGURATION_COMPONENT_DATA ControllerKey;
1690 ULONG Size;
1691
1692 /* Set 'Configuration Data' value */
1693 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) +
1694 2 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
1695 PartialResourceList = MmHeapAlloc(Size);
1696 if (PartialResourceList == NULL)
1697 {
1698 DPRINTM(DPRINT_HWDETECT,
1699 "Failed to allocate resource descriptor\n");
1700 return;
1701 }
1702
1703 /* Initialize resource descriptor */
1704 memset(PartialResourceList, 0, Size);
1705 PartialResourceList->Version = 1;
1706 PartialResourceList->Revision = 1;
1707 PartialResourceList->Count = 3;
1708
1709 /* Set Interrupt */
1710 PartialDescriptor = &PartialResourceList->PartialDescriptors[0];
1711 PartialDescriptor->Type = CmResourceTypeInterrupt;
1712 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
1713 PartialDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
1714 PartialDescriptor->u.Interrupt.Level = 1;
1715 PartialDescriptor->u.Interrupt.Vector = 1;
1716 PartialDescriptor->u.Interrupt.Affinity = 0xFFFFFFFF;
1717
1718 /* Set IO Port 0x60 */
1719 PartialDescriptor = &PartialResourceList->PartialDescriptors[1];
1720 PartialDescriptor->Type = CmResourceTypePort;
1721 PartialDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1722 PartialDescriptor->Flags = CM_RESOURCE_PORT_IO;
1723 PartialDescriptor->u.Port.Start.LowPart = 0x60;
1724 PartialDescriptor->u.Port.Start.HighPart = 0x0;
1725 PartialDescriptor->u.Port.Length = 1;
1726
1727 /* Set IO Port 0x64 */
1728 PartialDescriptor = &PartialResourceList->PartialDescriptors[2];
1729 PartialDescriptor->Type = CmResourceTypePort;
1730 PartialDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1731 PartialDescriptor->Flags = CM_RESOURCE_PORT_IO;
1732 PartialDescriptor->u.Port.Start.LowPart = 0x64;
1733 PartialDescriptor->u.Port.Start.HighPart = 0x0;
1734 PartialDescriptor->u.Port.Length = 1;
1735
1736 /* Create controller key */
1737 FldrCreateComponentKey(BusKey,
1738 ControllerClass,
1739 KeyboardController,
1740 Input | ConsoleIn,
1741 0x0,
1742 0xFFFFFFFF,
1743 NULL,
1744 PartialResourceList,
1745 Size,
1746 &ControllerKey);
1747 DPRINTM(DPRINT_HWDETECT, "Created key: KeyboardController\\0\n");
1748
1749 MmHeapFree(PartialResourceList);
1750
1751 DetectKeyboardPeripheral(ControllerKey);
1752 }
1753
1754
1755 static VOID
1756 PS2ControllerWait(VOID)
1757 {
1758 ULONG Timeout;
1759 UCHAR Status;
1760
1761 for (Timeout = 0; Timeout < CONTROLLER_TIMEOUT; Timeout++)
1762 {
1763 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
1764 if ((Status & CONTROLLER_STATUS_INPUT_BUFFER_FULL) == 0)
1765 return;
1766
1767 /* Sleep for one millisecond */
1768 StallExecutionProcessor(1000);
1769 }
1770 }
1771
1772
1773 static BOOLEAN
1774 DetectPS2AuxPort(VOID)
1775 {
1776 #if 1
1777 /* Current detection is too unreliable. Just do as if
1778 * the PS/2 aux port is always present
1779 */
1780 return TRUE;
1781 #else
1782 ULONG Loops;
1783 UCHAR Status;
1784
1785 /* Put the value 0x5A in the output buffer using the
1786 * "WriteAuxiliary Device Output Buffer" command (0xD3).
1787 * Poll the Status Register for a while to see if the value really turns up
1788 * in the Data Register. If the KEYBOARD_STATUS_MOUSE_OBF bit is also set
1789 * to 1 in the Status Register, we assume this controller has an
1790 * Auxiliary Port (a.k.a. Mouse Port).
1791 */
1792 PS2ControllerWait();
1793 WRITE_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_CONTROL,
1794 CONTROLLER_COMMAND_WRITE_MOUSE_OUTPUT_BUFFER);
1795 PS2ControllerWait();
1796
1797 /* 0x5A is a random dummy value */
1798 WRITE_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA,
1799 0x5A);
1800
1801 for (Loops = 0; Loops < 10; Loops++)
1802 {
1803 StallExecutionProcessor(10000);
1804 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
1805 if ((Status & CONTROLLER_STATUS_OUTPUT_BUFFER_FULL) != 0)
1806 break;
1807 }
1808
1809 READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA);
1810
1811 return (Status & CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL);
1812 #endif
1813 }
1814
1815
1816 static BOOLEAN
1817 DetectPS2AuxDevice(VOID)
1818 {
1819 UCHAR Scancode;
1820 UCHAR Status;
1821 ULONG Loops;
1822 BOOLEAN Result = TRUE;
1823
1824 PS2ControllerWait();
1825 WRITE_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_CONTROL,
1826 CONTROLLER_COMMAND_WRITE_MOUSE);
1827 PS2ControllerWait();
1828
1829 /* Identify device */
1830 WRITE_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA,
1831 0xF2);
1832
1833 /* Wait for reply */
1834 for (Loops = 0; Loops < 100; Loops++)
1835 {
1836 StallExecutionProcessor(10000);
1837 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
1838 if ((Status & CONTROLLER_STATUS_OUTPUT_BUFFER_FULL) != 0)
1839 break;
1840 }
1841
1842 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
1843 if ((Status & CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL) == 0)
1844 Result = FALSE;
1845
1846 Scancode = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA);
1847 if (Scancode != 0xFA)
1848 Result = FALSE;
1849
1850 StallExecutionProcessor(10000);
1851
1852 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
1853 if ((Status & CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL) == 0)
1854 Result = FALSE;
1855
1856 Scancode = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA);
1857 if (Scancode != 0x00)
1858 Result = FALSE;
1859
1860 return Result;
1861 }
1862
1863
1864 static VOID
1865 DetectPS2Mouse(PCONFIGURATION_COMPONENT_DATA BusKey)
1866 {
1867 CM_PARTIAL_RESOURCE_LIST PartialResourceList;
1868 PCONFIGURATION_COMPONENT_DATA ControllerKey;
1869 PCONFIGURATION_COMPONENT_DATA PeripheralKey;
1870
1871 if (DetectPS2AuxPort())
1872 {
1873 DPRINTM(DPRINT_HWDETECT, "Detected PS2 port\n");
1874
1875 memset(&PartialResourceList, 0, sizeof(CM_PARTIAL_RESOURCE_LIST));
1876
1877 /* Initialize resource descriptor */
1878 PartialResourceList.Version = 1;
1879 PartialResourceList.Revision = 1;
1880 PartialResourceList.Count = 1;
1881
1882 /* Set Interrupt */
1883 PartialResourceList.PartialDescriptors[0].Type = CmResourceTypeInterrupt;
1884 PartialResourceList.PartialDescriptors[0].ShareDisposition = CmResourceShareUndetermined;
1885 PartialResourceList.PartialDescriptors[0].Flags = CM_RESOURCE_INTERRUPT_LATCHED;
1886 PartialResourceList.PartialDescriptors[0].u.Interrupt.Level = 12;
1887 PartialResourceList.PartialDescriptors[0].u.Interrupt.Vector = 12;
1888 PartialResourceList.PartialDescriptors[0].u.Interrupt.Affinity = 0xFFFFFFFF;
1889
1890 /* Create controller key */
1891 FldrCreateComponentKey(BusKey,
1892 ControllerClass,
1893 PointerController,
1894 Input,
1895 0x0,
1896 0xFFFFFFFF,
1897 NULL,
1898 &PartialResourceList,
1899 sizeof(CM_PARTIAL_RESOURCE_LIST),
1900 &ControllerKey);
1901 DPRINTM(DPRINT_HWDETECT, "Created key: PointerController\\0\n");
1902
1903 if (DetectPS2AuxDevice())
1904 {
1905 DPRINTM(DPRINT_HWDETECT, "Detected PS2 mouse\n");
1906
1907 /* Initialize resource descriptor */
1908 memset(&PartialResourceList, 0, sizeof(CM_PARTIAL_RESOURCE_LIST));
1909 PartialResourceList.Version = 1;
1910 PartialResourceList.Revision = 1;
1911 PartialResourceList.Count = 0;
1912
1913 /* Create peripheral key */
1914 FldrCreateComponentKey(ControllerKey,
1915 ControllerClass,
1916 PointerPeripheral,
1917 Input,
1918 0x0,
1919 0xFFFFFFFF,
1920 "MICROSOFT PS2 MOUSE",
1921 &PartialResourceList,
1922 sizeof(CM_PARTIAL_RESOURCE_LIST) -
1923 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR),
1924 &PeripheralKey);
1925 DPRINTM(DPRINT_HWDETECT, "Created key: PointerPeripheral\\0\n");
1926 }
1927 }
1928 }
1929
1930
1931 static VOID
1932 DetectDisplayController(PCONFIGURATION_COMPONENT_DATA BusKey)
1933 {
1934 CHAR Buffer[80];
1935 PCONFIGURATION_COMPONENT_DATA ControllerKey;
1936 USHORT VesaVersion;
1937
1938 /* FIXME: Set 'ComponentInformation' value */
1939
1940 VesaVersion = BiosIsVesaSupported();
1941 if (VesaVersion != 0)
1942 {
1943 DPRINTM(DPRINT_HWDETECT,
1944 "VESA version %c.%c\n",
1945 (VesaVersion >> 8) + '0',
1946 (VesaVersion & 0xFF) + '0');
1947 }
1948 else
1949 {
1950 DPRINTM(DPRINT_HWDETECT,
1951 "VESA not supported\n");
1952 }
1953
1954 if (VesaVersion >= 0x0200)
1955 {
1956 strcpy(Buffer,
1957 "VBE Display");
1958 }
1959 else
1960 {
1961 strcpy(Buffer,
1962 "VGA Display");
1963 }
1964
1965 FldrCreateComponentKey(BusKey,
1966 ControllerClass,
1967 DisplayController,
1968 0x0,
1969 0x0,
1970 0xFFFFFFFF,
1971 Buffer,
1972 NULL,
1973 0,
1974 &ControllerKey);
1975 DPRINTM(DPRINT_HWDETECT, "Created key: DisplayController\\0\n");
1976
1977 /* FIXME: Add display peripheral (monitor) data */
1978 }
1979
1980
1981 static VOID
1982 DetectIsaBios(PCONFIGURATION_COMPONENT_DATA SystemKey, ULONG *BusNumber)
1983 {
1984 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
1985 PCONFIGURATION_COMPONENT_DATA BusKey;
1986 ULONG Size;
1987
1988 /* Increment bus number */
1989 (*BusNumber)++;
1990
1991 /* Set 'Configuration Data' value */
1992 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) -
1993 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
1994 PartialResourceList = MmHeapAlloc(Size);
1995 if (PartialResourceList == NULL)
1996 {
1997 DPRINTM(DPRINT_HWDETECT,
1998 "Failed to allocate resource descriptor\n");
1999 return;
2000 }
2001
2002 /* Initialize resource descriptor */
2003 memset(PartialResourceList, 0, Size);
2004 PartialResourceList->Version = 1;
2005 PartialResourceList->Revision = 1;
2006 PartialResourceList->Count = 0;
2007
2008 /* Create new bus key */
2009 FldrCreateComponentKey(SystemKey,
2010 AdapterClass,
2011 MultiFunctionAdapter,
2012 0x0,
2013 0x0,
2014 0xFFFFFFFF,
2015 "ISA",
2016 PartialResourceList,
2017 Size,
2018 &BusKey);
2019
2020 MmHeapFree(PartialResourceList);
2021
2022 /* Detect ISA/BIOS devices */
2023 DetectBiosDisks(BusKey);
2024
2025 DetectBiosFloppyController(BusKey);
2026
2027 DetectSerialPorts(BusKey);
2028
2029 DetectParallelPorts(BusKey);
2030
2031 DetectKeyboardController(BusKey);
2032
2033 DetectPS2Mouse(BusKey);
2034
2035 DetectDisplayController(BusKey);
2036
2037 /* FIXME: Detect more ISA devices */
2038 }
2039
2040
2041 PCONFIGURATION_COMPONENT_DATA
2042 PcHwDetect(VOID)
2043 {
2044 PCONFIGURATION_COMPONENT_DATA SystemKey;
2045 ULONG BusNumber = 0;
2046
2047 DPRINTM(DPRINT_HWDETECT, "DetectHardware()\n");
2048
2049 /* Create the 'System' key */
2050 SystemKey = DetectSystem();
2051
2052 /* Detect buses */
2053 DetectPciBios(SystemKey, &BusNumber);
2054 DetectApmBios(SystemKey, &BusNumber);
2055 DetectPnpBios(SystemKey, &BusNumber);
2056 DetectIsaBios(SystemKey, &BusNumber);
2057 DetectAcpiBios(SystemKey, &BusNumber);
2058
2059 DPRINTM(DPRINT_HWDETECT, "DetectHardware() Done\n");
2060
2061 return SystemKey;
2062 }
2063
2064 /* EOF */