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