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