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