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