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