4 * Copyright (C) 2003, 2004 Eric Kohl
5 * Copyright (C) 2009 Hervé Poussineau
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.
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.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
31 #define CLOCK_TICK_RATE (1193182)
32 #define LATCH (CLOCK_TICK_RATE / HZ)
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
49 /* Controller registers. */
50 #define CONTROLLER_REGISTER_STATUS 0x64
51 #define CONTROLLER_REGISTER_CONTROL 0x64
52 #define CONTROLLER_REGISTER_DATA 0x60
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
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)
80 /* Timeout in ms for sending to keyboard controller. */
81 #define CONTROLLER_TIMEOUT 250
83 static CHAR Hex
[] = "0123456789abcdef";
84 static unsigned int delay_count
= 1;
86 extern ULONG reactos_disk_count
;
87 extern ARC_DISK_SIGNATURE reactos_arc_disk_info
[];
88 extern char reactos_arc_strings
[32][256];
90 /* FUNCTIONS ****************************************************************/
94 __StallExecutionProcessor(ULONG Loops
)
96 register volatile unsigned int i
;
97 for (i
= 0; i
< Loops
; i
++);
101 VOID
StallExecutionProcessor(ULONG Microseconds
)
103 ULONGLONG LoopCount
= ((ULONGLONG
)delay_count
* (ULONGLONG
)Microseconds
) / 1000ULL;
104 __StallExecutionProcessor((ULONG
)LoopCount
);
113 WRITE_PORT_UCHAR((PUCHAR
)0x43, 0x00);
114 Count
= READ_PORT_UCHAR((PUCHAR
)0x40);
115 Count
|= READ_PORT_UCHAR((PUCHAR
)0x40) << 8;
122 WaitFor8254Wraparound(VOID
)
125 ULONG PrevCount
= ~0;
128 CurCount
= Read8254Timer();
132 PrevCount
= CurCount
;
133 CurCount
= Read8254Timer();
134 Delta
= CurCount
- PrevCount
;
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.
147 HalpCalibrateStallExecution(VOID
)
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 */
158 /* Stage 1: Coarse calibration */
160 WaitFor8254Wraparound();
165 delay_count
<<= 1; /* Next delay count to try */
167 WaitFor8254Wraparound();
169 __StallExecutionProcessor(delay_count
); /* Do the delay */
171 CurCount
= Read8254Timer();
172 } while (CurCount
> LATCH
/ 2);
174 delay_count
>>= 1; /* Get bottom value for delay */
176 /* Stage 2: Fine calibration */
178 calib_bit
= delay_count
; /* Which bit are we going to test */
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 */
184 delay_count
|= calib_bit
; /* Set the bit in delay_count */
186 WaitFor8254Wraparound();
188 __StallExecutionProcessor(delay_count
); /* Do the delay */
190 CurCount
= Read8254Timer();
191 if (CurCount
<= LATCH
/ 2) /* If a tick has passed, turn the */
192 delay_count
&= ~calib_bit
; /* calibrated bit back off */
195 /* We're finished: Do the finishing touches */
196 delay_count
/= (MILLISEC
/ 2); /* Calculate delay_count for 1ms */
200 DetectPnpBios(PCONFIGURATION_COMPONENT_DATA SystemKey
, ULONG
*BusNumber
)
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
;
210 ULONG FoundNodeCount
;
216 InstData
= (PCM_PNP_BIOS_INSTALLATION_CHECK
)PnpBiosSupported();
217 if (InstData
== NULL
|| strncmp((CHAR
*)InstData
->Signature
, "$PnP", 4))
219 DPRINTM(DPRINT_HWDETECT
, "PnP-BIOS not supported\n");
222 DPRINTM(DPRINT_HWDETECT
, "Signature '%c%c%c%c'\n",
223 InstData
->Signature
[0], InstData
->Signature
[1],
224 InstData
->Signature
[2], InstData
->Signature
[3]);
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)
233 DPRINTM(DPRINT_HWDETECT
, "PnP-BIOS failed to enumerate device nodes\n");
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
);
240 /* Set 'Configuration Data' value */
241 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) + (NodeSize
* NodeCount
);
242 PartialResourceList
= MmHeapAlloc(Size
);
243 if (PartialResourceList
== NULL
)
245 DPRINTM(DPRINT_HWDETECT
,
246 "Failed to allocate resource descriptor\n");
249 memset(PartialResourceList
, 0, Size
);
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
;
260 Ptr
= (char *)(((ULONG_PTR
)&PartialResourceList
->PartialDescriptors
[0]) +
261 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
));
263 /* Set instalation check data */
264 memcpy (Ptr
, InstData
, sizeof(CM_PNP_BIOS_INSTALLATION_CHECK
));
265 Ptr
+= sizeof(CM_PNP_BIOS_INSTALLATION_CHECK
);
267 /* Copy device nodes */
269 PnpBufferSize
= sizeof(CM_PNP_BIOS_INSTALLATION_CHECK
);
270 for (i
= 0; i
< 0xFF; i
++)
272 NodeNumber
= (UCHAR
)i
;
274 x
= PnpBiosGetDeviceNode(&NodeNumber
, (PVOID
)DISKREADBUFFER
);
277 DeviceNode
= (PCM_PNP_BIOS_DEVICE_NODE
)DISKREADBUFFER
;
279 DPRINTM(DPRINT_HWDETECT
,
280 "Node: %u Size %u (0x%x)\n",
289 Ptr
+= DeviceNode
->Size
;
290 PnpBufferSize
+= DeviceNode
->Size
;
293 if (FoundNodeCount
>= NodeCount
)
298 /* Set real data size */
299 PartialResourceList
->PartialDescriptors
[0].u
.DeviceSpecificData
.DataSize
=
301 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) + PnpBufferSize
;
303 DPRINTM(DPRINT_HWDETECT
, "Real buffer size: %u\n", PnpBufferSize
);
304 DPRINTM(DPRINT_HWDETECT
, "Resource size: %u\n", Size
);
306 /* Create component key */
307 FldrCreateComponentKey(SystemKey
,
309 MultiFunctionAdapter
,
320 MmHeapFree(PartialResourceList
);
325 static PCM_PARTIAL_RESOURCE_LIST
326 GetHarddiskConfigurationData(ULONG DriveNumber
, ULONG
* pSize
)
328 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
329 PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry
;
330 EXTENDED_GEOMETRY ExtGeometry
;
335 // Initialize returned size
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
)
345 DPRINTM(DPRINT_HWDETECT
,
346 "Failed to allocate a full resource descriptor\n");
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
);
361 /* Get pointer to geometry data */
362 DiskGeometry
= (PVOID
)(((ULONG_PTR
)PartialResourceList
) + sizeof(CM_PARTIAL_RESOURCE_LIST
));
364 /* Get the disk geometry */
365 ExtGeometry
.Size
= sizeof(EXTENDED_GEOMETRY
);
366 if (DiskGetExtendedDriveParameters(DriveNumber
, &ExtGeometry
, ExtGeometry
.Size
))
368 DiskGeometry
->BytesPerSector
= ExtGeometry
.BytesPerSector
;
369 DiskGeometry
->NumberOfCylinders
= ExtGeometry
.Cylinders
;
370 DiskGeometry
->SectorsPerTrack
= ExtGeometry
.SectorsPerTrack
;
371 DiskGeometry
->NumberOfHeads
= ExtGeometry
.Heads
;
373 else if(MachDiskGetDriveGeometry(DriveNumber
, &Geometry
))
375 DiskGeometry
->BytesPerSector
= Geometry
.BytesPerSector
;
376 DiskGeometry
->NumberOfCylinders
= Geometry
.Cylinders
;
377 DiskGeometry
->SectorsPerTrack
= Geometry
.Sectors
;
378 DiskGeometry
->NumberOfHeads
= Geometry
.Heads
;
382 DPRINTM(DPRINT_HWDETECT
, "Reading disk geometry failed\n");
383 MmHeapFree(PartialResourceList
);
386 DPRINTM(DPRINT_HWDETECT
,
387 "Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n",
389 DiskGeometry
->NumberOfCylinders
,
390 DiskGeometry
->NumberOfHeads
,
391 DiskGeometry
->SectorsPerTrack
,
392 DiskGeometry
->BytesPerSector
);
395 // Return configuration data
398 return PartialResourceList
;
401 typedef struct tagDISKCONTEXT
405 ULONGLONG SectorOffset
;
406 ULONGLONG SectorCount
;
407 ULONGLONG SectorNumber
;
410 static LONG
DiskClose(ULONG FileId
)
412 DISKCONTEXT
* Context
= FsGetDeviceSpecific(FileId
);
418 static LONG
DiskGetFileInformation(ULONG FileId
, FILEINFORMATION
* Information
)
420 DISKCONTEXT
* Context
= FsGetDeviceSpecific(FileId
);
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
;
429 static LONG
DiskOpen(CHAR
* Path
, OPENMODE OpenMode
, ULONG
* FileId
)
431 DISKCONTEXT
* Context
;
432 ULONG DriveNumber
, DrivePartition
, SectorSize
;
433 ULONGLONG SectorOffset
= 0;
434 ULONGLONG SectorCount
= 0;
435 PARTITION_TABLE_ENTRY PartitionTableEntry
;
437 EXTENDED_GEOMETRY ExtGeometry
;
440 if (!DissectArcPath(Path
, FileName
, &DriveNumber
, &DrivePartition
))
443 ExtGeometry
.Size
= sizeof(EXTENDED_GEOMETRY
);
444 if (DiskGetExtendedDriveParameters(DriveNumber
, &ExtGeometry
, ExtGeometry
.Size
))
446 SectorSize
= ExtGeometry
.BytesPerSector
;
447 SectorCount
= ExtGeometry
.Sectors
;
449 else if (MachDiskGetDriveGeometry(DriveNumber
, &Geometry
))
451 SectorSize
= Geometry
.BytesPerSector
;
452 SectorCount
= Geometry
.Sectors
;
457 if (DrivePartition
!= 0xff && DrivePartition
!= 0)
459 if (!DiskGetPartitionEntry(DriveNumber
, DrivePartition
, &PartitionTableEntry
))
461 SectorOffset
= PartitionTableEntry
.SectorCountBeforePartition
;
462 SectorCount
= PartitionTableEntry
.PartitionSectorCount
;
465 Context
= MmHeapAlloc(sizeof(DISKCONTEXT
));
468 Context
->DriveNumber
= DriveNumber
;
469 Context
->SectorSize
= SectorSize
;
470 Context
->SectorOffset
= SectorOffset
;
471 Context
->SectorCount
= SectorCount
;
472 Context
->SectorNumber
= 0;
473 FsSetDeviceSpecific(*FileId
, Context
);
478 static LONG
DiskRead(ULONG FileId
, VOID
* Buffer
, ULONG N
, ULONG
* Count
)
480 DISKCONTEXT
* Context
= FsGetDeviceSpecific(FileId
);
481 UCHAR
* Ptr
= (UCHAR
*)Buffer
;
490 if (Length
> Context
->SectorSize
)
491 Length
= Context
->SectorSize
;
492 ret
= MachDiskReadLogicalSectors(
493 Context
->DriveNumber
,
494 Context
->SectorNumber
+ Context
->SectorOffset
+ i
,
496 (PVOID
)DISKREADBUFFER
);
499 RtlCopyMemory(Ptr
, (PVOID
)DISKREADBUFFER
, Length
);
509 static LONG
DiskSeek(ULONG FileId
, LARGE_INTEGER
* Position
, SEEKMODE SeekMode
)
511 DISKCONTEXT
* Context
= FsGetDeviceSpecific(FileId
);
513 if (SeekMode
!= SeekAbsolute
)
515 if (Position
->LowPart
& (Context
->SectorSize
- 1))
518 /* FIXME: take HighPart into account */
519 Context
->SectorNumber
= Position
->LowPart
/ Context
->SectorSize
;
523 static const DEVVTBL DiskVtbl
= {
525 DiskGetFileInformation
,
532 GetHarddiskIdentifier(PCHAR Identifier
,
535 PMASTER_BOOT_RECORD Mbr
;
541 PARTITION_TABLE_ENTRY PartitionTableEntry
;
544 if (!MachDiskReadLogicalSectors(DriveNumber
, 0ULL, 1, (PVOID
)DISKREADBUFFER
))
546 DPRINTM(DPRINT_HWDETECT
, "Reading MBR failed\n");
550 Buffer
= (ULONG
*)DISKREADBUFFER
;
551 Mbr
= (PMASTER_BOOT_RECORD
)DISKREADBUFFER
;
553 Signature
= Mbr
->Signature
;
554 DPRINTM(DPRINT_HWDETECT
, "Signature: %x\n", Signature
);
556 /* Calculate the MBR checksum */
558 for (i
= 0; i
< 128; i
++)
560 Checksum
+= Buffer
[i
];
562 Checksum
= ~Checksum
+ 1;
563 DPRINTM(DPRINT_HWDETECT
, "Checksum: %x\n", Checksum
);
565 /* Fill out the ARC disk block */
566 reactos_arc_disk_info
[reactos_disk_count
].Signature
= Signature
;
567 reactos_arc_disk_info
[reactos_disk_count
].CheckSum
= Checksum
;
568 sprintf(ArcName
, "multi(0)disk(0)rdisk(%lu)", reactos_disk_count
);
569 strcpy(reactos_arc_strings
[reactos_disk_count
], ArcName
);
570 reactos_arc_disk_info
[reactos_disk_count
].ArcName
=
571 reactos_arc_strings
[reactos_disk_count
];
572 reactos_disk_count
++;
574 sprintf(ArcName
, "multi(0)disk(0)rdisk(%lu)partition(0)", DriveNumber
- 0x80);
575 FsRegisterDevice(ArcName
, &DiskVtbl
);
579 DiskReportError(FALSE
);
580 while (DiskGetPartitionEntry(DriveNumber
, i
, &PartitionTableEntry
))
582 if (PartitionTableEntry
.SystemIndicator
!= PARTITION_ENTRY_UNUSED
)
584 sprintf(ArcName
, "multi(0)disk(0)rdisk(%lu)partition(%lu)", DriveNumber
- 0x80, i
);
585 FsRegisterDevice(ArcName
, &DiskVtbl
);
589 DiskReportError(TRUE
);
591 /* Convert checksum and signature to identifier string */
592 Identifier
[0] = Hex
[(Checksum
>> 28) & 0x0F];
593 Identifier
[1] = Hex
[(Checksum
>> 24) & 0x0F];
594 Identifier
[2] = Hex
[(Checksum
>> 20) & 0x0F];
595 Identifier
[3] = Hex
[(Checksum
>> 16) & 0x0F];
596 Identifier
[4] = Hex
[(Checksum
>> 12) & 0x0F];
597 Identifier
[5] = Hex
[(Checksum
>> 8) & 0x0F];
598 Identifier
[6] = Hex
[(Checksum
>> 4) & 0x0F];
599 Identifier
[7] = Hex
[Checksum
& 0x0F];
601 Identifier
[9] = Hex
[(Signature
>> 28) & 0x0F];
602 Identifier
[10] = Hex
[(Signature
>> 24) & 0x0F];
603 Identifier
[11] = Hex
[(Signature
>> 20) & 0x0F];
604 Identifier
[12] = Hex
[(Signature
>> 16) & 0x0F];
605 Identifier
[13] = Hex
[(Signature
>> 12) & 0x0F];
606 Identifier
[14] = Hex
[(Signature
>> 8) & 0x0F];
607 Identifier
[15] = Hex
[(Signature
>> 4) & 0x0F];
608 Identifier
[16] = Hex
[Signature
& 0x0F];
609 Identifier
[17] = '-';
610 Identifier
[18] = 'A';
612 DPRINTM(DPRINT_HWDETECT
, "Identifier: %s\n", Identifier
);
620 WRITE_PORT_UCHAR((PUCHAR
)0x70, 0x10);
621 Data
= READ_PORT_UCHAR((PUCHAR
)0x71);
623 return ((Data
& 0xF0) ? 1 : 0) + ((Data
& 0x0F) ? 1 : 0);
628 GetFloppyType(UCHAR DriveNumber
)
632 WRITE_PORT_UCHAR((PUCHAR
)0x70, 0x10);
633 Data
= READ_PORT_UCHAR((PUCHAR
)0x71);
635 if (DriveNumber
== 0)
637 else if (DriveNumber
== 1)
647 PUSHORT SegPtr
= (PUSHORT
)0x7A;
648 PUSHORT OfsPtr
= (PUSHORT
)0x78;
650 return (PVOID
)((ULONG_PTR
)(((ULONG
)(*SegPtr
)) << 4) + (ULONG
)(*OfsPtr
));
655 DetectBiosFloppyPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey
)
657 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
658 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
659 PCM_FLOPPY_DEVICE_DATA FloppyData
;
661 PCONFIGURATION_COMPONENT_DATA PeripheralKey
;
665 ULONG MaxDensity
[6] = {0, 360, 1200, 720, 1440, 2880};
668 for (FloppyNumber
= 0; FloppyNumber
< 2; FloppyNumber
++)
670 FloppyType
= GetFloppyType(FloppyNumber
);
672 if ((FloppyType
> 5) || (FloppyType
== 0))
675 DiskResetController(FloppyNumber
);
677 Ptr
= GetInt1eTable();
679 /* Set 'Identifier' value */
680 sprintf(Identifier
, "FLOPPY%ld", FloppyNumber
+ 1);
682 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
683 sizeof(CM_FLOPPY_DEVICE_DATA
);
684 PartialResourceList
= MmHeapAlloc(Size
);
685 if (PartialResourceList
== NULL
)
687 DPRINTM(DPRINT_HWDETECT
,
688 "Failed to allocate resource descriptor\n");
692 memset(PartialResourceList
, 0, Size
);
693 PartialResourceList
->Version
= 1;
694 PartialResourceList
->Revision
= 1;
695 PartialResourceList
->Count
= 1;
697 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[0];
698 PartialDescriptor
->Type
= CmResourceTypeDeviceSpecific
;
699 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
700 PartialDescriptor
->u
.DeviceSpecificData
.DataSize
= sizeof(CM_FLOPPY_DEVICE_DATA
);
702 FloppyData
= (PVOID
)(((ULONG_PTR
)PartialResourceList
) + sizeof(CM_PARTIAL_RESOURCE_LIST
));
703 FloppyData
->Version
= 2;
704 FloppyData
->Revision
= 0;
705 FloppyData
->MaxDensity
= MaxDensity
[FloppyType
];
706 FloppyData
->MountDensity
= 0;
707 RtlCopyMemory(&FloppyData
->StepRateHeadUnloadTime
,
710 FloppyData
->MaximumTrackValue
= (FloppyType
== 1) ? 39 : 79;
711 FloppyData
->DataTransferRate
= 0;
713 FldrCreateComponentKey(ControllerKey
,
715 FloppyDiskPeripheral
,
724 MmHeapFree(PartialResourceList
);
730 DetectBiosFloppyController(PCONFIGURATION_COMPONENT_DATA BusKey
)
732 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
733 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
734 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
738 FloppyCount
= GetFloppyCount();
739 DPRINTM(DPRINT_HWDETECT
,
740 "Floppy count: %u\n",
743 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
744 2 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
745 PartialResourceList
= MmHeapAlloc(Size
);
746 if (PartialResourceList
== NULL
)
748 DPRINTM(DPRINT_HWDETECT
,
749 "Failed to allocate resource descriptor\n");
752 memset(PartialResourceList
, 0, Size
);
754 /* Initialize resource descriptor */
755 PartialResourceList
->Version
= 1;
756 PartialResourceList
->Revision
= 1;
757 PartialResourceList
->Count
= 3;
760 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[0];
761 PartialDescriptor
->Type
= CmResourceTypePort
;
762 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
763 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
764 PartialDescriptor
->u
.Port
.Start
.LowPart
= 0x03F0;
765 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0x0;
766 PartialDescriptor
->u
.Port
.Length
= 8;
769 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[1];
770 PartialDescriptor
->Type
= CmResourceTypeInterrupt
;
771 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
772 PartialDescriptor
->Flags
= CM_RESOURCE_INTERRUPT_LATCHED
;
773 PartialDescriptor
->u
.Interrupt
.Level
= 6;
774 PartialDescriptor
->u
.Interrupt
.Vector
= 6;
775 PartialDescriptor
->u
.Interrupt
.Affinity
= 0xFFFFFFFF;
777 /* Set DMA channel */
778 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[2];
779 PartialDescriptor
->Type
= CmResourceTypeDma
;
780 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
781 PartialDescriptor
->Flags
= 0;
782 PartialDescriptor
->u
.Dma
.Channel
= 2;
783 PartialDescriptor
->u
.Dma
.Port
= 0;
785 /* Create floppy disk controller */
786 FldrCreateComponentKey(BusKey
,
796 DPRINTM(DPRINT_HWDETECT
, "Created key: DiskController\\0\n");
798 MmHeapFree(PartialResourceList
);
800 if (FloppyCount
) DetectBiosFloppyPeripheral(ControllerKey
);
803 static PCONFIGURATION_COMPONENT_DATA
806 PCONFIGURATION_COMPONENT_DATA SystemKey
;
807 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
808 PCM_INT13_DRIVE_PARAMETER Int13Drives
;
815 /* Count the number of visible drives */
816 DiskReportError(FALSE
);
819 /* There are some really broken BIOSes out there. There are even BIOSes
820 * that happily report success when you ask them to read from non-existent
821 * harddisks. So, we set the buffer to known contents first, then try to
822 * read. If the BIOS reports success but the buffer contents haven't
823 * changed then we fail anyway */
824 memset((PVOID
) DISKREADBUFFER
, 0xcd, 512);
825 while (MachDiskReadLogicalSectors(0x80 + DiskCount
, 0ULL, 1, (PVOID
)DISKREADBUFFER
))
828 for (i
= 0; ! Changed
&& i
< 512; i
++)
830 Changed
= ((PUCHAR
)DISKREADBUFFER
)[i
] != 0xcd;
834 DPRINTM(DPRINT_HWDETECT
, "BIOS reports success for disk %d but data didn't change\n",
839 memset((PVOID
) DISKREADBUFFER
, 0xcd, 512);
841 DiskReportError(TRUE
);
842 DPRINTM(DPRINT_HWDETECT
, "BIOS reports %d harddisk%s\n",
843 (int)DiskCount
, (DiskCount
== 1) ? "": "s");
845 /* Allocate resource descriptor */
846 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
847 sizeof(CM_INT13_DRIVE_PARAMETER
) * DiskCount
;
848 PartialResourceList
= MmHeapAlloc(Size
);
849 if (PartialResourceList
== NULL
)
851 DPRINTM(DPRINT_HWDETECT
,
852 "Failed to allocate resource descriptor\n");
856 /* Initialize resource descriptor */
857 memset(PartialResourceList
, 0, Size
);
858 PartialResourceList
->Version
= 1;
859 PartialResourceList
->Revision
= 1;
860 PartialResourceList
->Count
= 1;
861 PartialResourceList
->PartialDescriptors
[0].Type
= CmResourceTypeDeviceSpecific
;
862 PartialResourceList
->PartialDescriptors
[0].ShareDisposition
= 0;
863 PartialResourceList
->PartialDescriptors
[0].Flags
= 0;
864 PartialResourceList
->PartialDescriptors
[0].u
.DeviceSpecificData
.DataSize
=
865 sizeof(CM_INT13_DRIVE_PARAMETER
) * DiskCount
;
867 /* Get harddisk Int13 geometry data */
868 Int13Drives
= (PVOID
)(((ULONG_PTR
)PartialResourceList
) + sizeof(CM_PARTIAL_RESOURCE_LIST
));
869 for (i
= 0; i
< DiskCount
; i
++)
871 if (MachDiskGetDriveGeometry(0x80 + i
, &Geometry
))
873 Int13Drives
[i
].DriveSelect
= 0x80 + i
;
874 Int13Drives
[i
].MaxCylinders
= Geometry
.Cylinders
- 1;
875 Int13Drives
[i
].SectorsPerTrack
= Geometry
.Sectors
;
876 Int13Drives
[i
].MaxHeads
= Geometry
.Heads
- 1;
877 Int13Drives
[i
].NumberDrives
= DiskCount
;
879 DPRINTM(DPRINT_HWDETECT
,
880 "Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n",
882 Geometry
.Cylinders
- 1,
885 Geometry
.BytesPerSector
);
889 FldrCreateComponentKey(NULL
,
900 MmHeapFree(PartialResourceList
);
906 GetDiskCount(PCONFIGURATION_COMPONENT_DATA BusKey
)
908 PCONFIGURATION_COMPONENT_DATA System
;
909 ULONG ConfigurationDataLength
;
913 // Get root component
916 while (System
->Parent
)
917 System
= System
->Parent
;
920 // Get root configuration data length
922 ConfigurationDataLength
= System
->ComponentEntry
.ConfigurationDataLength
;
925 // We assume that nothing wrong happened, and that configuration
926 // only consists of one CM_PARTIAL_RESOURCE_LIST entry, followed
927 // by n entries of CM_INT13_DRIVE_PARAMETER
929 if (ConfigurationDataLength
> 0)
930 DiskCount
= (ConfigurationDataLength
- sizeof(CM_PARTIAL_RESOURCE_LIST
))
931 / sizeof(CM_INT13_DRIVE_PARAMETER
);
934 // Return number of disks
936 DPRINTM(DPRINT_HWDETECT
, "Retrieving %lu INT13 disks\\0\n", DiskCount
);
941 DetectBiosDisks(PCONFIGURATION_COMPONENT_DATA BusKey
)
943 PCONFIGURATION_COMPONENT_DATA DiskKey
, ControllerKey
;
944 BOOLEAN BootDriveReported
= FALSE
;
946 ULONG DiskCount
= GetDiskCount(BusKey
);
949 FldrCreateComponentKey(BusKey
,
959 DPRINTM(DPRINT_HWDETECT
, "Created key: DiskController\\0\n");
961 /* Create and fill subkey for each harddisk */
962 for (i
= 0; i
< DiskCount
; i
++)
964 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
968 if (BootDrive
== 0x80 + i
)
969 BootDriveReported
= TRUE
;
971 /* Get disk values */
972 PartialResourceList
= GetHarddiskConfigurationData(0x80 + i
, &Size
);
973 GetHarddiskIdentifier(Identifier
, 0x80 + i
);
975 /* Create disk key */
976 FldrCreateComponentKey(ControllerKey
,
988 /* Get the drive we're booting from */
989 MachDiskGetBootPath(BootPath
, sizeof(BootPath
));
991 /* Add it, if it's a floppy or cdrom */
992 if ((BootDrive
>= 0x80 && !BootDriveReported
) ||
993 DiskIsDriveRemovable(BootDrive
))
995 /* TODO: Check if it's really a cdrom drive */
1000 if (!MachDiskReadLogicalSectors(BootDrive
, 16ULL, 1, (PVOID
)DISKREADBUFFER
))
1002 DPRINTM(DPRINT_HWDETECT
, "Reading MBR failed\n");
1006 Buffer
= (ULONG
*)DISKREADBUFFER
;
1008 /* Calculate the MBR checksum */
1009 for (i
= 0; i
< 2048 / sizeof(ULONG
); i
++) Checksum
+= Buffer
[i
];
1010 DPRINTM(DPRINT_HWDETECT
, "Checksum: %x\n", Checksum
);
1012 /* Fill out the ARC disk block */
1013 reactos_arc_disk_info
[reactos_disk_count
].CheckSum
= Checksum
;
1014 strcpy(reactos_arc_strings
[reactos_disk_count
], BootPath
);
1015 reactos_arc_disk_info
[reactos_disk_count
].ArcName
=
1016 reactos_arc_strings
[reactos_disk_count
];
1017 reactos_disk_count
++;
1019 FsRegisterDevice(BootPath
, &DiskVtbl
);
1024 InitializeSerialPort(PUCHAR Port
,
1027 WRITE_PORT_UCHAR(Port
+ 3, 0x80); /* set DLAB on */
1028 WRITE_PORT_UCHAR(Port
, 0x60); /* speed LO byte */
1029 WRITE_PORT_UCHAR(Port
+ 1, 0); /* speed HI byte */
1030 WRITE_PORT_UCHAR(Port
+ 3, LineControl
);
1031 WRITE_PORT_UCHAR(Port
+ 1, 0); /* set comm and DLAB to 0 */
1032 WRITE_PORT_UCHAR(Port
+ 4, 0x09); /* DR int enable */
1033 READ_PORT_UCHAR(Port
+ 5); /* clear error bits */
1038 DetectSerialMouse(PUCHAR Port
)
1045 /* Shutdown mouse or something like that */
1046 LineControl
= READ_PORT_UCHAR(Port
+ 4);
1047 WRITE_PORT_UCHAR(Port
+ 4, (LineControl
& ~0x02) | 0x01);
1048 StallExecutionProcessor(100000);
1052 * Maybe there is no serial port although BIOS reported one (this
1053 * is the case on Apple hardware), or the serial port is misbehaving,
1054 * therefore we must give up after some time.
1057 while (READ_PORT_UCHAR(Port
+ 5) & 0x01)
1060 return MOUSE_TYPE_NONE
;
1061 READ_PORT_UCHAR(Port
);
1065 * Send modem control with 'Data Terminal Ready', 'Request To Send' and
1066 * 'Output Line 2' message. This enables mouse to identify.
1068 WRITE_PORT_UCHAR(Port
+ 4, 0x0b);
1070 /* Wait 10 milliseconds for the mouse getting ready */
1071 StallExecutionProcessor(10000);
1073 /* Read first four bytes, which contains Microsoft Mouse signs */
1075 for (i
= 0; i
< 4; i
++)
1077 while (((READ_PORT_UCHAR(Port
+ 5) & 1) == 0) && (TimeOut
> 0))
1079 StallExecutionProcessor(1000);
1082 return MOUSE_TYPE_NONE
;
1084 Buffer
[i
] = READ_PORT_UCHAR(Port
);
1087 DPRINTM(DPRINT_HWDETECT
,
1088 "Mouse data: %x %x %x %x\n",
1089 Buffer
[0],Buffer
[1],Buffer
[2],Buffer
[3]);
1091 /* Check that four bytes for signs */
1092 for (i
= 0; i
< 4; ++i
)
1094 if (Buffer
[i
] == 'B')
1096 /* Sign for Microsoft Ballpoint */
1097 // DbgPrint("Microsoft Ballpoint device detected\n");
1098 // DbgPrint("THIS DEVICE IS NOT SUPPORTED, YET\n");
1099 return MOUSE_TYPE_NONE
;
1101 else if (Buffer
[i
] == 'M')
1103 /* Sign for Microsoft Mouse protocol followed by button specifier */
1106 /* Overflow Error */
1107 return MOUSE_TYPE_NONE
;
1110 switch (Buffer
[i
+ 1])
1113 DPRINTM(DPRINT_HWDETECT
,
1114 "Microsoft Mouse with 3-buttons detected\n");
1115 return MOUSE_TYPE_LOGITECH
;
1118 DPRINTM(DPRINT_HWDETECT
,
1119 "Microsoft Wheel Mouse detected\n");
1120 return MOUSE_TYPE_WHEELZ
;
1124 DPRINTM(DPRINT_HWDETECT
,
1125 "Microsoft Mouse with 2-buttons detected\n");
1126 return MOUSE_TYPE_MICROSOFT
;
1131 return MOUSE_TYPE_NONE
;
1136 GetSerialMousePnpId(PUCHAR Port
, char *Buffer
)
1143 WRITE_PORT_UCHAR(Port
+ 4, 0x09);
1145 /* Wait 10 milliseconds for the mouse getting ready */
1146 StallExecutionProcessor(10000);
1148 WRITE_PORT_UCHAR(Port
+ 4, 0x0b);
1150 StallExecutionProcessor(10000);
1155 while (((READ_PORT_UCHAR(Port
+ 5) & 1) == 0) && (TimeOut
> 0))
1157 StallExecutionProcessor(1000);
1165 c
= READ_PORT_UCHAR(Port
);
1166 if (c
== 0x08 || c
== 0x28)
1176 while (((READ_PORT_UCHAR(Port
+ 5) & 1) == 0) && (TimeOut
> 0))
1178 StallExecutionProcessor(1000);
1183 c
= READ_PORT_UCHAR(Port
);
1196 DetectSerialPointerPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey
,
1199 CM_PARTIAL_RESOURCE_LIST PartialResourceList
;
1201 CHAR Identifier
[256];
1202 PCONFIGURATION_COMPONENT_DATA PeripheralKey
;
1209 DPRINTM(DPRINT_HWDETECT
,
1210 "DetectSerialPointerPeripheral()\n");
1214 InitializeSerialPort(Base
, 2);
1215 MouseType
= DetectSerialMouse(Base
);
1217 if (MouseType
!= MOUSE_TYPE_NONE
)
1219 Length
= GetSerialMousePnpId(Base
, Buffer
);
1220 DPRINTM(DPRINT_HWDETECT
,
1221 "PnP ID length: %u\n",
1226 /* Convert PnP sting to ASCII */
1227 if (Buffer
[0] == 0x08)
1229 for (i
= 0; i
< Length
; i
++)
1234 DPRINTM(DPRINT_HWDETECT
,
1235 "PnP ID string: %s\n",
1238 /* Copy PnpId string */
1239 for (i
= 0; i
< 7; i
++)
1241 Identifier
[i
] = Buffer
[3+i
];
1243 memcpy(&Identifier
[7],
1247 /* Skip device serial number */
1249 if (Buffer
[i
] == '\\')
1251 for (j
= ++i
; i
< Length
; ++i
)
1253 if (Buffer
[i
] == '\\')
1260 /* Skip PnP class */
1261 if (Buffer
[i
] == '\\')
1263 for (j
= ++i
; i
< Length
; ++i
)
1265 if (Buffer
[i
] == '\\')
1273 /* Skip compatible PnP Id */
1274 if (Buffer
[i
] == '\\')
1276 for (j
= ++i
; i
< Length
; ++i
)
1278 if (Buffer
[i
] == '\\')
1281 if (Buffer
[j
] == '*')
1287 /* Get product description */
1288 if (Buffer
[i
] == '\\')
1290 for (j
= ++i
; i
< Length
; ++i
)
1292 if (Buffer
[i
] == ';')
1299 for (k
= 0; k
< i
- j
; k
++)
1301 Identifier
[k
+ 10] = Buffer
[k
+ j
];
1303 Identifier
[10 + (i
-j
)] = 0;
1307 DPRINTM(DPRINT_HWDETECT
,
1308 "Identifier string: %s\n",
1312 if (Length
== 0 || strlen(Identifier
) < 11)
1316 case MOUSE_TYPE_LOGITECH
:
1318 "LOGITECH SERIAL MOUSE");
1321 case MOUSE_TYPE_WHEELZ
:
1323 "MICROSOFT SERIAL MOUSE WITH WHEEL");
1326 case MOUSE_TYPE_MICROSOFT
:
1329 "MICROSOFT SERIAL MOUSE");
1334 /* Set 'Configuration Data' value */
1335 memset(&PartialResourceList
, 0, sizeof(CM_PARTIAL_RESOURCE_LIST
));
1336 PartialResourceList
.Version
= 1;
1337 PartialResourceList
.Revision
= 1;
1338 PartialResourceList
.Count
= 0;
1340 /* Create 'PointerPeripheral' key */
1341 FldrCreateComponentKey(ControllerKey
,
1348 &PartialResourceList
,
1349 sizeof(CM_PARTIAL_RESOURCE_LIST
) -
1350 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
),
1353 DPRINTM(DPRINT_HWDETECT
,
1354 "Created key: PointerPeripheral\\0\n");
1360 DetectSerialPorts(PCONFIGURATION_COMPONENT_DATA BusKey
)
1362 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
1363 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
1364 PCM_SERIAL_DEVICE_DATA SerialDeviceData
;
1365 ULONG Irq
[4] = {4, 3, 4, 3};
1369 ULONG ControllerNumber
= 0;
1370 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
1374 DPRINTM(DPRINT_HWDETECT
, "DetectSerialPorts()\n");
1376 ControllerNumber
= 0;
1377 BasePtr
= (PUSHORT
)0x400;
1378 for (i
= 0; i
< 4; i
++, BasePtr
++)
1380 Base
= (ULONG
)*BasePtr
;
1384 DPRINTM(DPRINT_HWDETECT
,
1385 "Found COM%u port at 0x%x\n",
1389 /* Set 'Identifier' value */
1390 sprintf(Buffer
, "COM%ld", i
+ 1);
1392 /* Build full device descriptor */
1393 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
1394 2 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
) +
1395 sizeof(CM_SERIAL_DEVICE_DATA
);
1396 PartialResourceList
= MmHeapAlloc(Size
);
1397 if (PartialResourceList
== NULL
)
1399 DPRINTM(DPRINT_HWDETECT
,
1400 "Failed to allocate resource descriptor\n");
1403 memset(PartialResourceList
, 0, Size
);
1405 /* Initialize resource descriptor */
1406 PartialResourceList
->Version
= 1;
1407 PartialResourceList
->Revision
= 1;
1408 PartialResourceList
->Count
= 3;
1411 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[0];
1412 PartialDescriptor
->Type
= CmResourceTypePort
;
1413 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
1414 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
1415 PartialDescriptor
->u
.Port
.Start
.LowPart
= Base
;
1416 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0x0;
1417 PartialDescriptor
->u
.Port
.Length
= 7;
1420 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[1];
1421 PartialDescriptor
->Type
= CmResourceTypeInterrupt
;
1422 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
1423 PartialDescriptor
->Flags
= CM_RESOURCE_INTERRUPT_LATCHED
;
1424 PartialDescriptor
->u
.Interrupt
.Level
= Irq
[i
];
1425 PartialDescriptor
->u
.Interrupt
.Vector
= 0;
1426 PartialDescriptor
->u
.Interrupt
.Affinity
= 0xFFFFFFFF;
1428 /* Set serial data (device specific) */
1429 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[2];
1430 PartialDescriptor
->Type
= CmResourceTypeDeviceSpecific
;
1431 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
1432 PartialDescriptor
->Flags
= 0;
1433 PartialDescriptor
->u
.DeviceSpecificData
.DataSize
= sizeof(CM_SERIAL_DEVICE_DATA
);
1436 (PCM_SERIAL_DEVICE_DATA
)&PartialResourceList
->PartialDescriptors
[3];
1437 SerialDeviceData
->BaudClock
= 1843200; /* UART Clock frequency (Hertz) */
1439 /* Create controller key */
1440 FldrCreateComponentKey(BusKey
,
1443 Output
| Input
| ConsoleIn
| ConsoleOut
,
1447 PartialResourceList
,
1451 MmHeapFree(PartialResourceList
);
1453 if (!Rs232PortInUse(Base
))
1455 /* Detect serial mouse */
1456 DetectSerialPointerPeripheral(ControllerKey
, UlongToPtr(Base
));
1465 DetectParallelPorts(PCONFIGURATION_COMPONENT_DATA BusKey
)
1467 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
1468 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
1469 ULONG Irq
[3] = {7, 5, (ULONG
)-1};
1471 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
1474 ULONG ControllerNumber
;
1478 DPRINTM(DPRINT_HWDETECT
, "DetectParallelPorts() called\n");
1480 ControllerNumber
= 0;
1481 BasePtr
= (PUSHORT
)0x408;
1482 for (i
= 0; i
< 3; i
++, BasePtr
++)
1484 Base
= (ULONG
)*BasePtr
;
1488 DPRINTM(DPRINT_HWDETECT
,
1489 "Parallel port %u: %x\n",
1493 /* Set 'Identifier' value */
1494 sprintf(Buffer
, "PARALLEL%ld", i
+ 1);
1496 /* Build full device descriptor */
1497 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
);
1498 if (Irq
[i
] != (ULONG
)-1)
1499 Size
+= sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1501 PartialResourceList
= MmHeapAlloc(Size
);
1502 if (PartialResourceList
== NULL
)
1504 DPRINTM(DPRINT_HWDETECT
,
1505 "Failed to allocate resource descriptor\n");
1508 memset(PartialResourceList
, 0, Size
);
1510 /* Initialize resource descriptor */
1511 PartialResourceList
->Version
= 1;
1512 PartialResourceList
->Revision
= 1;
1513 PartialResourceList
->Count
= (Irq
[i
] != (ULONG
)-1) ? 2 : 1;
1516 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[0];
1517 PartialDescriptor
->Type
= CmResourceTypePort
;
1518 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
1519 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
1520 PartialDescriptor
->u
.Port
.Start
.LowPart
= Base
;
1521 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0x0;
1522 PartialDescriptor
->u
.Port
.Length
= 3;
1525 if (Irq
[i
] != (ULONG
)-1)
1527 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[1];
1528 PartialDescriptor
->Type
= CmResourceTypeInterrupt
;
1529 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
1530 PartialDescriptor
->Flags
= CM_RESOURCE_INTERRUPT_LATCHED
;
1531 PartialDescriptor
->u
.Interrupt
.Level
= Irq
[i
];
1532 PartialDescriptor
->u
.Interrupt
.Vector
= 0;
1533 PartialDescriptor
->u
.Interrupt
.Affinity
= 0xFFFFFFFF;
1536 /* Create controller key */
1537 FldrCreateComponentKey(BusKey
,
1544 PartialResourceList
,
1548 MmHeapFree(PartialResourceList
);
1553 DPRINTM(DPRINT_HWDETECT
, "DetectParallelPorts() done\n");
1558 DetectKeyboardDevice(VOID
)
1563 BOOLEAN Result
= TRUE
;
1565 /* Identify device */
1566 WRITE_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
,
1569 /* Wait for reply */
1570 for (Loops
= 0; Loops
< 100; Loops
++)
1572 StallExecutionProcessor(10000);
1573 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1574 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) != 0)
1578 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) == 0)
1580 /* PC/XT keyboard or no keyboard */
1584 Scancode
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
1585 if (Scancode
!= 0xFA)
1587 /* No ACK received */
1591 StallExecutionProcessor(10000);
1593 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1594 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) == 0)
1596 /* Found AT keyboard */
1600 Scancode
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
1601 if (Scancode
!= 0xAB)
1603 /* No 0xAB received */
1607 StallExecutionProcessor(10000);
1609 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1610 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) == 0)
1612 /* No byte in buffer */
1616 Scancode
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
1617 if (Scancode
!= 0x41)
1619 /* No 0x41 received */
1623 /* Found MF-II keyboard */
1629 DetectKeyboardPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey
)
1631 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
1632 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
1633 PCM_KEYBOARD_DEVICE_DATA KeyboardData
;
1634 PCONFIGURATION_COMPONENT_DATA PeripheralKey
;
1637 /* HACK: don't call DetectKeyboardDevice() as it fails in Qemu 0.8.2 */
1638 if (TRUE
|| DetectKeyboardDevice())
1640 /* Set 'Configuration Data' value */
1641 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
1642 sizeof(CM_KEYBOARD_DEVICE_DATA
);
1643 PartialResourceList
= MmHeapAlloc(Size
);
1644 if (PartialResourceList
== NULL
)
1646 DPRINTM(DPRINT_HWDETECT
,
1647 "Failed to allocate resource descriptor\n");
1651 /* Initialize resource descriptor */
1652 memset(PartialResourceList
, 0, Size
);
1653 PartialResourceList
->Version
= 1;
1654 PartialResourceList
->Revision
= 1;
1655 PartialResourceList
->Count
= 1;
1657 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[0];
1658 PartialDescriptor
->Type
= CmResourceTypeDeviceSpecific
;
1659 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
1660 PartialDescriptor
->u
.DeviceSpecificData
.DataSize
= sizeof(CM_KEYBOARD_DEVICE_DATA
);
1662 KeyboardData
= (PCM_KEYBOARD_DEVICE_DATA
)(PartialDescriptor
+ 1);
1663 KeyboardData
->Version
= 1;
1664 KeyboardData
->Revision
= 1;
1665 KeyboardData
->Type
= 4;
1666 KeyboardData
->Subtype
= 0;
1667 KeyboardData
->KeyboardFlags
= 0x20;
1669 /* Create controller key */
1670 FldrCreateComponentKey(ControllerKey
,
1677 PartialResourceList
,
1680 DPRINTM(DPRINT_HWDETECT
, "Created key: KeyboardPeripheral\\0\n");
1682 MmHeapFree(PartialResourceList
);
1688 DetectKeyboardController(PCONFIGURATION_COMPONENT_DATA BusKey
)
1690 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
1691 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
1692 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
1695 /* Set 'Configuration Data' value */
1696 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
1697 2 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1698 PartialResourceList
= MmHeapAlloc(Size
);
1699 if (PartialResourceList
== NULL
)
1701 DPRINTM(DPRINT_HWDETECT
,
1702 "Failed to allocate resource descriptor\n");
1706 /* Initialize resource descriptor */
1707 memset(PartialResourceList
, 0, Size
);
1708 PartialResourceList
->Version
= 1;
1709 PartialResourceList
->Revision
= 1;
1710 PartialResourceList
->Count
= 3;
1713 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[0];
1714 PartialDescriptor
->Type
= CmResourceTypeInterrupt
;
1715 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
1716 PartialDescriptor
->Flags
= CM_RESOURCE_INTERRUPT_LATCHED
;
1717 PartialDescriptor
->u
.Interrupt
.Level
= 1;
1718 PartialDescriptor
->u
.Interrupt
.Vector
= 0;
1719 PartialDescriptor
->u
.Interrupt
.Affinity
= 0xFFFFFFFF;
1721 /* Set IO Port 0x60 */
1722 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[1];
1723 PartialDescriptor
->Type
= CmResourceTypePort
;
1724 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
1725 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
1726 PartialDescriptor
->u
.Port
.Start
.LowPart
= 0x60;
1727 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0x0;
1728 PartialDescriptor
->u
.Port
.Length
= 1;
1730 /* Set IO Port 0x64 */
1731 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[2];
1732 PartialDescriptor
->Type
= CmResourceTypePort
;
1733 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
1734 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
1735 PartialDescriptor
->u
.Port
.Start
.LowPart
= 0x64;
1736 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0x0;
1737 PartialDescriptor
->u
.Port
.Length
= 1;
1739 /* Create controller key */
1740 FldrCreateComponentKey(BusKey
,
1747 PartialResourceList
,
1750 DPRINTM(DPRINT_HWDETECT
, "Created key: KeyboardController\\0\n");
1752 MmHeapFree(PartialResourceList
);
1754 DetectKeyboardPeripheral(ControllerKey
);
1759 PS2ControllerWait(VOID
)
1764 for (Timeout
= 0; Timeout
< CONTROLLER_TIMEOUT
; Timeout
++)
1766 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1767 if ((Status
& CONTROLLER_STATUS_INPUT_BUFFER_FULL
) == 0)
1770 /* Sleep for one millisecond */
1771 StallExecutionProcessor(1000);
1777 DetectPS2AuxPort(VOID
)
1780 /* Current detection is too unreliable. Just do as if
1781 * the PS/2 aux port is always present
1788 /* Put the value 0x5A in the output buffer using the
1789 * "WriteAuxiliary Device Output Buffer" command (0xD3).
1790 * Poll the Status Register for a while to see if the value really turns up
1791 * in the Data Register. If the KEYBOARD_STATUS_MOUSE_OBF bit is also set
1792 * to 1 in the Status Register, we assume this controller has an
1793 * Auxiliary Port (a.k.a. Mouse Port).
1795 PS2ControllerWait();
1796 WRITE_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_CONTROL
,
1797 CONTROLLER_COMMAND_WRITE_MOUSE_OUTPUT_BUFFER
);
1798 PS2ControllerWait();
1800 /* 0x5A is a random dummy value */
1801 WRITE_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
,
1804 for (Loops
= 0; Loops
< 10; Loops
++)
1806 StallExecutionProcessor(10000);
1807 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1808 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) != 0)
1812 READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
1814 return (Status
& CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL
);
1820 DetectPS2AuxDevice(VOID
)
1825 BOOLEAN Result
= TRUE
;
1827 PS2ControllerWait();
1828 WRITE_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_CONTROL
,
1829 CONTROLLER_COMMAND_WRITE_MOUSE
);
1830 PS2ControllerWait();
1832 /* Identify device */
1833 WRITE_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
,
1836 /* Wait for reply */
1837 for (Loops
= 0; Loops
< 100; Loops
++)
1839 StallExecutionProcessor(10000);
1840 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1841 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) != 0)
1845 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1846 if ((Status
& CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL
) == 0)
1849 Scancode
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
1850 if (Scancode
!= 0xFA)
1853 StallExecutionProcessor(10000);
1855 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1856 if ((Status
& CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL
) == 0)
1859 Scancode
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
1860 if (Scancode
!= 0x00)
1868 DetectPS2Mouse(PCONFIGURATION_COMPONENT_DATA BusKey
)
1870 CM_PARTIAL_RESOURCE_LIST PartialResourceList
;
1871 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
1872 PCONFIGURATION_COMPONENT_DATA PeripheralKey
;
1874 if (DetectPS2AuxPort())
1876 DPRINTM(DPRINT_HWDETECT
, "Detected PS2 port\n");
1878 memset(&PartialResourceList
, 0, sizeof(CM_PARTIAL_RESOURCE_LIST
));
1880 /* Initialize resource descriptor */
1881 PartialResourceList
.Version
= 1;
1882 PartialResourceList
.Revision
= 1;
1883 PartialResourceList
.Count
= 1;
1886 PartialResourceList
.PartialDescriptors
[0].Type
= CmResourceTypeInterrupt
;
1887 PartialResourceList
.PartialDescriptors
[0].ShareDisposition
= CmResourceShareUndetermined
;
1888 PartialResourceList
.PartialDescriptors
[0].Flags
= CM_RESOURCE_INTERRUPT_LATCHED
;
1889 PartialResourceList
.PartialDescriptors
[0].u
.Interrupt
.Level
= 12;
1890 PartialResourceList
.PartialDescriptors
[0].u
.Interrupt
.Vector
= 0;
1891 PartialResourceList
.PartialDescriptors
[0].u
.Interrupt
.Affinity
= 0xFFFFFFFF;
1893 /* Create controller key */
1894 FldrCreateComponentKey(BusKey
,
1901 &PartialResourceList
,
1902 sizeof(CM_PARTIAL_RESOURCE_LIST
),
1904 DPRINTM(DPRINT_HWDETECT
, "Created key: PointerController\\0\n");
1906 if (DetectPS2AuxDevice())
1908 DPRINTM(DPRINT_HWDETECT
, "Detected PS2 mouse\n");
1910 /* Initialize resource descriptor */
1911 memset(&PartialResourceList
, 0, sizeof(CM_PARTIAL_RESOURCE_LIST
));
1912 PartialResourceList
.Version
= 1;
1913 PartialResourceList
.Revision
= 1;
1914 PartialResourceList
.Count
= 0;
1916 /* Create peripheral key */
1917 FldrCreateComponentKey(ControllerKey
,
1923 "MICROSOFT PS2 MOUSE",
1924 &PartialResourceList
,
1925 sizeof(CM_PARTIAL_RESOURCE_LIST
) -
1926 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
),
1928 DPRINTM(DPRINT_HWDETECT
, "Created key: PointerPeripheral\\0\n");
1935 DetectDisplayController(PCONFIGURATION_COMPONENT_DATA BusKey
)
1938 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
1941 /* FIXME: Set 'ComponentInformation' value */
1943 VesaVersion
= BiosIsVesaSupported();
1944 if (VesaVersion
!= 0)
1946 DPRINTM(DPRINT_HWDETECT
,
1947 "VESA version %c.%c\n",
1948 (VesaVersion
>> 8) + '0',
1949 (VesaVersion
& 0xFF) + '0');
1953 DPRINTM(DPRINT_HWDETECT
,
1954 "VESA not supported\n");
1957 if (VesaVersion
>= 0x0200)
1968 FldrCreateComponentKey(BusKey
,
1978 DPRINTM(DPRINT_HWDETECT
, "Created key: DisplayController\\0\n");
1980 /* FIXME: Add display peripheral (monitor) data */
1985 DetectIsaBios(PCONFIGURATION_COMPONENT_DATA SystemKey
, ULONG
*BusNumber
)
1987 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
1988 PCONFIGURATION_COMPONENT_DATA BusKey
;
1991 /* Increment bus number */
1994 /* Set 'Configuration Data' value */
1995 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) -
1996 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1997 PartialResourceList
= MmHeapAlloc(Size
);
1998 if (PartialResourceList
== NULL
)
2000 DPRINTM(DPRINT_HWDETECT
,
2001 "Failed to allocate resource descriptor\n");
2005 /* Initialize resource descriptor */
2006 memset(PartialResourceList
, 0, Size
);
2007 PartialResourceList
->Version
= 1;
2008 PartialResourceList
->Revision
= 1;
2009 PartialResourceList
->Count
= 0;
2011 /* Create new bus key */
2012 FldrCreateComponentKey(SystemKey
,
2014 MultiFunctionAdapter
,
2019 PartialResourceList
,
2023 MmHeapFree(PartialResourceList
);
2025 /* Detect ISA/BIOS devices */
2026 DetectBiosDisks(BusKey
);
2028 DetectBiosFloppyController(BusKey
);
2030 DetectSerialPorts(BusKey
);
2032 DetectParallelPorts(BusKey
);
2034 DetectKeyboardController(BusKey
);
2036 DetectPS2Mouse(BusKey
);
2038 DetectDisplayController(BusKey
);
2040 /* FIXME: Detect more ISA devices */
2044 PCONFIGURATION_COMPONENT_DATA
2047 PCONFIGURATION_COMPONENT_DATA SystemKey
;
2048 ULONG BusNumber
= 0;
2050 DPRINTM(DPRINT_HWDETECT
, "DetectHardware()\n");
2052 /* Create the 'System' key */
2053 SystemKey
= DetectSystem();
2056 DetectPciBios(SystemKey
, &BusNumber
);
2057 DetectApmBios(SystemKey
, &BusNumber
);
2058 DetectPnpBios(SystemKey
, &BusNumber
);
2059 DetectIsaBios(SystemKey
, &BusNumber
);
2060 DetectAcpiBios(SystemKey
, &BusNumber
);
2062 DPRINTM(DPRINT_HWDETECT
, "DetectHardware() Done\n");