4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #include <cportlib/cportlib.h>
25 DBG_DEFAULT_CHANNEL(HWDETECT
);
28 /* Maximum number of COM and LPT ports */
29 #define MAX_COM_PORTS 4
30 #define MAX_LPT_PORTS 3
33 #define MOUSE_TYPE_NONE 0
34 /* Microsoft Mouse with 2 buttons */
35 #define MOUSE_TYPE_MICROSOFT 1
36 /* Logitech Mouse with 3 buttons */
37 #define MOUSE_TYPE_LOGITECH 2
38 /* Microsoft Wheel Mouse (aka Z Mouse) */
39 #define MOUSE_TYPE_WHEELZ 3
40 /* Mouse Systems Mouse */
41 #define MOUSE_TYPE_MOUSESYSTEMS 4
46 /* Controller registers. */
47 #define CONTROLLER_REGISTER_STATUS 0x64
48 #define CONTROLLER_REGISTER_CONTROL 0x64
49 #define CONTROLLER_REGISTER_DATA 0x60
51 /* Controller commands. */
52 #define CONTROLLER_COMMAND_READ_MODE 0x20
53 #define CONTROLLER_COMMAND_WRITE_MODE 0x60
54 #define CONTROLLER_COMMAND_GET_VERSION 0xA1
55 #define CONTROLLER_COMMAND_MOUSE_DISABLE 0xA7
56 #define CONTROLLER_COMMAND_MOUSE_ENABLE 0xA8
57 #define CONTROLLER_COMMAND_TEST_MOUSE 0xA9
58 #define CONTROLLER_COMMAND_SELF_TEST 0xAA
59 #define CONTROLLER_COMMAND_KEYBOARD_TEST 0xAB
60 #define CONTROLLER_COMMAND_KEYBOARD_DISABLE 0xAD
61 #define CONTROLLER_COMMAND_KEYBOARD_ENABLE 0xAE
62 #define CONTROLLER_COMMAND_WRITE_MOUSE_OUTPUT_BUFFER 0xD3
63 #define CONTROLLER_COMMAND_WRITE_MOUSE 0xD4
65 /* Controller status */
66 #define CONTROLLER_STATUS_OUTPUT_BUFFER_FULL 0x01
67 #define CONTROLLER_STATUS_INPUT_BUFFER_FULL 0x02
68 #define CONTROLLER_STATUS_SELF_TEST 0x04
69 #define CONTROLLER_STATUS_COMMAND 0x08
70 #define CONTROLLER_STATUS_UNLOCKED 0x10
71 #define CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL 0x20
72 #define CONTROLLER_STATUS_GENERAL_TIMEOUT 0x40
73 #define CONTROLLER_STATUS_PARITY_ERROR 0x80
74 #define AUX_STATUS_OUTPUT_BUFFER_FULL (CONTROLLER_STATUS_OUTPUT_BUFFER_FULL | \
75 CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL)
77 /* Timeout in ms for sending to keyboard controller. */
78 #define CONTROLLER_TIMEOUT 250
81 // NOTE: Similar to xboxhw.c!XboxGetHarddiskConfigurationData(),
82 // but with extended geometry support.
84 PCM_PARTIAL_RESOURCE_LIST
85 PcGetHarddiskConfigurationData(UCHAR DriveNumber
, ULONG
* pSize
)
87 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
88 PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry
;
89 EXTENDED_GEOMETRY ExtGeometry
;
94 // Initialize returned size
98 /* Set 'Configuration Data' value */
99 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
100 sizeof(CM_DISK_GEOMETRY_DEVICE_DATA
);
101 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
102 if (PartialResourceList
== NULL
)
104 ERR("Failed to allocate resource descriptor\n");
108 memset(PartialResourceList
, 0, Size
);
109 PartialResourceList
->Version
= 1;
110 PartialResourceList
->Revision
= 1;
111 PartialResourceList
->Count
= 1;
112 PartialResourceList
->PartialDescriptors
[0].Type
=
113 CmResourceTypeDeviceSpecific
;
114 // PartialResourceList->PartialDescriptors[0].ShareDisposition =
115 // PartialResourceList->PartialDescriptors[0].Flags =
116 PartialResourceList
->PartialDescriptors
[0].u
.DeviceSpecificData
.DataSize
=
117 sizeof(CM_DISK_GEOMETRY_DEVICE_DATA
);
119 /* Get pointer to geometry data */
120 DiskGeometry
= (PVOID
)(((ULONG_PTR
)PartialResourceList
) + sizeof(CM_PARTIAL_RESOURCE_LIST
));
122 /* Get the disk geometry */
123 ExtGeometry
.Size
= sizeof(EXTENDED_GEOMETRY
);
124 if (DiskGetExtendedDriveParameters(DriveNumber
, &ExtGeometry
, ExtGeometry
.Size
))
126 DiskGeometry
->BytesPerSector
= ExtGeometry
.BytesPerSector
;
127 DiskGeometry
->NumberOfCylinders
= ExtGeometry
.Cylinders
;
128 DiskGeometry
->SectorsPerTrack
= ExtGeometry
.SectorsPerTrack
;
129 DiskGeometry
->NumberOfHeads
= ExtGeometry
.Heads
;
131 else if (MachDiskGetDriveGeometry(DriveNumber
, &Geometry
))
133 DiskGeometry
->BytesPerSector
= Geometry
.BytesPerSector
;
134 DiskGeometry
->NumberOfCylinders
= Geometry
.Cylinders
;
135 DiskGeometry
->SectorsPerTrack
= Geometry
.Sectors
;
136 DiskGeometry
->NumberOfHeads
= Geometry
.Heads
;
140 TRACE("Reading disk geometry failed\n");
141 FrLdrHeapFree(PartialResourceList
, TAG_HW_RESOURCE_LIST
);
144 TRACE("Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n",
146 DiskGeometry
->NumberOfCylinders
,
147 DiskGeometry
->NumberOfHeads
,
148 DiskGeometry
->SectorsPerTrack
,
149 DiskGeometry
->BytesPerSector
);
152 // Return configuration data
155 return PartialResourceList
;
160 DetectPnpBios(PCONFIGURATION_COMPONENT_DATA SystemKey
, ULONG
*BusNumber
)
162 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
163 PCM_PNP_BIOS_DEVICE_NODE DeviceNode
;
164 PCM_PNP_BIOS_INSTALLATION_CHECK InstData
;
165 PCONFIGURATION_COMPONENT_DATA BusKey
;
170 ULONG FoundNodeCount
;
173 ULONG PnpBufferSizeLimit
;
177 InstData
= (PCM_PNP_BIOS_INSTALLATION_CHECK
)PnpBiosSupported();
178 if (InstData
== NULL
|| strncmp((CHAR
*)InstData
->Signature
, "$PnP", 4))
180 TRACE("PnP-BIOS not supported\n");
184 TRACE("PnP-BIOS supported\n");
185 TRACE("Signature '%c%c%c%c'\n",
186 InstData
->Signature
[0], InstData
->Signature
[1],
187 InstData
->Signature
[2], InstData
->Signature
[3]);
189 x
= PnpBiosGetDeviceNodeCount(&NodeSize
, &NodeCount
);
192 TRACE("PnP-BIOS function 'Get Number of System Device Nodes' not supported\n");
196 NodeCount
&= 0xFF; // needed since some fscked up BIOSes return
197 // wrong info (e.g. Mac Virtual PC)
198 // e.g. look: http://my.execpc.com/~geezer/osd/pnp/pnp16.c
199 if (x
!= 0 || NodeSize
== 0 || NodeCount
== 0)
201 ERR("PnP-BIOS failed to enumerate device nodes\n");
204 TRACE("MaxNodeSize %u NodeCount %u\n", NodeSize
, NodeCount
);
205 TRACE("Estimated buffer size %u\n", NodeSize
* NodeCount
);
207 /* Set 'Configuration Data' value */
208 PnpBufferSizeLimit
= sizeof(CM_PNP_BIOS_INSTALLATION_CHECK
)
209 + (NodeSize
* NodeCount
);
210 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) + PnpBufferSizeLimit
;
211 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
212 if (PartialResourceList
== NULL
)
214 ERR("Failed to allocate resource descriptor\n");
217 memset(PartialResourceList
, 0, Size
);
219 /* Initialize resource descriptor */
220 PartialResourceList
->Version
= 1;
221 PartialResourceList
->Revision
= 1;
222 PartialResourceList
->Count
= 1;
223 PartialResourceList
->PartialDescriptors
[0].Type
=
224 CmResourceTypeDeviceSpecific
;
225 PartialResourceList
->PartialDescriptors
[0].ShareDisposition
=
226 CmResourceShareUndetermined
;
228 /* The buffer starts after PartialResourceList->PartialDescriptors[0] */
229 Ptr
= (char *)(PartialResourceList
+ 1);
231 /* Set installation check data */
232 memcpy (Ptr
, InstData
, sizeof(CM_PNP_BIOS_INSTALLATION_CHECK
));
233 Ptr
+= sizeof(CM_PNP_BIOS_INSTALLATION_CHECK
);
234 PnpBufferSize
= sizeof(CM_PNP_BIOS_INSTALLATION_CHECK
);
236 /* Copy device nodes */
238 for (i
= 0; i
< 0xFF; i
++)
240 NodeNumber
= (UCHAR
)i
;
242 x
= PnpBiosGetDeviceNode(&NodeNumber
, DiskReadBuffer
);
245 DeviceNode
= (PCM_PNP_BIOS_DEVICE_NODE
)DiskReadBuffer
;
247 TRACE("Node: %u Size %u (0x%x)\n",
252 if (PnpBufferSize
+ DeviceNode
->Size
> PnpBufferSizeLimit
)
254 ERR("Buffer too small! Ignoring remaining device nodes.\n");
258 memcpy(Ptr
, DeviceNode
, DeviceNode
->Size
);
260 Ptr
+= DeviceNode
->Size
;
261 PnpBufferSize
+= DeviceNode
->Size
;
264 if (FoundNodeCount
>= NodeCount
)
269 /* Set real data size */
270 PartialResourceList
->PartialDescriptors
[0].u
.DeviceSpecificData
.DataSize
=
272 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) + PnpBufferSize
;
274 TRACE("Real buffer size: %u\n", PnpBufferSize
);
275 TRACE("Resource size: %u\n", Size
);
277 /* Create component key */
278 FldrCreateComponentKey(SystemKey
,
280 MultiFunctionAdapter
,
294 InitializeSerialPort(PUCHAR Port
,
297 WRITE_PORT_UCHAR(Port
+ 3, 0x80); /* set DLAB on */
298 WRITE_PORT_UCHAR(Port
, 0x60); /* speed LO byte */
299 WRITE_PORT_UCHAR(Port
+ 1, 0); /* speed HI byte */
300 WRITE_PORT_UCHAR(Port
+ 3, LineControl
);
301 WRITE_PORT_UCHAR(Port
+ 1, 0); /* set comm and DLAB to 0 */
302 WRITE_PORT_UCHAR(Port
+ 4, 0x09); /* DR int enable */
303 READ_PORT_UCHAR(Port
+ 5); /* clear error bits */
308 DetectSerialMouse(PUCHAR Port
)
315 /* Shutdown mouse or something like that */
316 LineControl
= READ_PORT_UCHAR(Port
+ 4);
317 WRITE_PORT_UCHAR(Port
+ 4, (LineControl
& ~0x02) | 0x01);
318 StallExecutionProcessor(100000);
322 * Maybe there is no serial port although BIOS reported one (this
323 * is the case on Apple hardware), or the serial port is misbehaving,
324 * therefore we must give up after some time.
327 while (READ_PORT_UCHAR(Port
+ 5) & 0x01)
330 return MOUSE_TYPE_NONE
;
331 READ_PORT_UCHAR(Port
);
335 * Send modem control with 'Data Terminal Ready', 'Request To Send' and
336 * 'Output Line 2' message. This enables mouse to identify.
338 WRITE_PORT_UCHAR(Port
+ 4, 0x0b);
340 /* Wait 10 milliseconds for the mouse getting ready */
341 StallExecutionProcessor(10000);
343 /* Read first four bytes, which contains Microsoft Mouse signs */
345 for (i
= 0; i
< 4; i
++)
347 while (((READ_PORT_UCHAR(Port
+ 5) & 1) == 0) && (TimeOut
> 0))
349 StallExecutionProcessor(1000);
352 return MOUSE_TYPE_NONE
;
354 Buffer
[i
] = READ_PORT_UCHAR(Port
);
357 TRACE("Mouse data: %x %x %x %x\n",
358 Buffer
[0], Buffer
[1], Buffer
[2], Buffer
[3]);
360 /* Check that four bytes for signs */
361 for (i
= 0; i
< 4; ++i
)
363 if (Buffer
[i
] == 'B')
365 /* Sign for Microsoft Ballpoint */
366 // DbgPrint("Microsoft Ballpoint device detected\n");
367 // DbgPrint("THIS DEVICE IS NOT SUPPORTED, YET\n");
368 return MOUSE_TYPE_NONE
;
370 else if (Buffer
[i
] == 'M')
372 /* Sign for Microsoft Mouse protocol followed by button specifier */
376 return MOUSE_TYPE_NONE
;
379 switch (Buffer
[i
+ 1])
382 TRACE("Microsoft Mouse with 3-buttons detected\n");
383 return MOUSE_TYPE_LOGITECH
;
386 TRACE("Microsoft Wheel Mouse detected\n");
387 return MOUSE_TYPE_WHEELZ
;
391 TRACE("Microsoft Mouse with 2-buttons detected\n");
392 return MOUSE_TYPE_MICROSOFT
;
397 return MOUSE_TYPE_NONE
;
401 GetSerialMousePnpId(PUCHAR Port
, char *Buffer
)
408 WRITE_PORT_UCHAR(Port
+ 4, 0x09);
410 /* Wait 10 milliseconds for the mouse getting ready */
411 StallExecutionProcessor(10000);
413 WRITE_PORT_UCHAR(Port
+ 4, 0x0b);
415 StallExecutionProcessor(10000);
420 while (((READ_PORT_UCHAR(Port
+ 5) & 1) == 0) && (TimeOut
> 0))
422 StallExecutionProcessor(1000);
430 c
= READ_PORT_UCHAR(Port
);
431 if (c
== 0x08 || c
== 0x28)
441 while (((READ_PORT_UCHAR(Port
+ 5) & 1) == 0) && (TimeOut
> 0))
443 StallExecutionProcessor(1000);
448 c
= READ_PORT_UCHAR(Port
);
461 DetectSerialPointerPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey
,
464 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
466 CHAR Identifier
[256];
467 PCONFIGURATION_COMPONENT_DATA PeripheralKey
;
474 TRACE("DetectSerialPointerPeripheral()\n");
478 InitializeSerialPort(Base
, 2);
479 MouseType
= DetectSerialMouse(Base
);
481 if (MouseType
!= MOUSE_TYPE_NONE
)
483 Length
= GetSerialMousePnpId(Base
, Buffer
);
484 TRACE( "PnP ID length: %u\n", Length
);
488 /* Convert PnP sting to ASCII */
489 if (Buffer
[0] == 0x08)
491 for (i
= 0; i
< Length
; i
++)
496 TRACE("PnP ID string: %s\n", Buffer
);
498 /* Copy PnpId string */
499 for (i
= 0; i
< 7; i
++)
501 Identifier
[i
] = Buffer
[3 + i
];
503 memcpy(&Identifier
[7],
507 /* Skip device serial number */
509 if (Buffer
[i
] == '\\')
511 for (j
= ++i
; i
< Length
; ++i
)
513 if (Buffer
[i
] == '\\')
521 if (Buffer
[i
] == '\\')
523 for (j
= ++i
; i
< Length
; ++i
)
525 if (Buffer
[i
] == '\\')
533 /* Skip compatible PnP Id */
534 if (Buffer
[i
] == '\\')
536 for (j
= ++i
; i
< Length
; ++i
)
538 if (Buffer
[i
] == '\\')
541 if (Buffer
[j
] == '*')
547 /* Get product description */
548 if (Buffer
[i
] == '\\')
550 for (j
= ++i
; i
< Length
; ++i
)
552 if (Buffer
[i
] == ';')
559 for (k
= 0; k
< i
- j
; k
++)
561 Identifier
[k
+ 10] = Buffer
[k
+ j
];
563 Identifier
[10 + (i
- j
)] = 0;
567 TRACE("Identifier string: %s\n", Identifier
);
570 if (Length
== 0 || strlen(Identifier
) < 11)
574 case MOUSE_TYPE_LOGITECH
:
575 strcpy(Identifier
, "LOGITECH SERIAL MOUSE");
578 case MOUSE_TYPE_WHEELZ
:
579 strcpy(Identifier
, "MICROSOFT SERIAL MOUSE WITH WHEEL");
582 case MOUSE_TYPE_MICROSOFT
:
584 strcpy(Identifier
, "MICROSOFT SERIAL MOUSE");
589 /* Set 'Configuration Data' value */
590 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) -
591 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
592 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
593 if (PartialResourceList
== NULL
)
595 ERR("Failed to allocate resource descriptor\n");
598 memset(PartialResourceList
, 0, Size
);
599 PartialResourceList
->Version
= 1;
600 PartialResourceList
->Revision
= 1;
601 PartialResourceList
->Count
= 0;
603 /* Create 'PointerPeripheral' key */
604 FldrCreateComponentKey(ControllerKey
,
615 TRACE("Created key: PointerPeripheral\\0\n");
621 DetectSerialPorts(PCONFIGURATION_COMPONENT_DATA BusKey
)
623 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
624 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
625 PCM_SERIAL_DEVICE_DATA SerialDeviceData
;
626 ULONG Irq
[MAX_COM_PORTS
] = {4, 3, 4, 3};
630 ULONG ControllerNumber
= 0;
631 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
635 TRACE("DetectSerialPorts()\n");
638 * The BIOS data area 0x400 holds the address of the first valid COM port.
639 * Each COM port address is stored in a 2-byte field.
640 * Infos at: http://www.bioscentral.com/misc/bda.htm
642 BasePtr
= (PUSHORT
)0x400;
644 for (i
= 0; i
< MAX_COM_PORTS
; i
++, BasePtr
++)
646 Base
= (ULONG
) * BasePtr
;
647 if (Base
== 0 || !CpDoesPortExist((PUCHAR
)Base
))
650 TRACE("Found COM%u port at 0x%x\n", i
+ 1, Base
);
652 /* Set 'Identifier' value */
653 sprintf(Buffer
, "COM%ld", i
+ 1);
655 /* Build full device descriptor */
656 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
657 2 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
) +
658 sizeof(CM_SERIAL_DEVICE_DATA
);
659 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
660 if (PartialResourceList
== NULL
)
662 ERR("Failed to allocate resource descriptor\n");
665 memset(PartialResourceList
, 0, Size
);
667 /* Initialize resource descriptor */
668 PartialResourceList
->Version
= 1;
669 PartialResourceList
->Revision
= 1;
670 PartialResourceList
->Count
= 3;
673 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[0];
674 PartialDescriptor
->Type
= CmResourceTypePort
;
675 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
676 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
677 PartialDescriptor
->u
.Port
.Start
.LowPart
= Base
;
678 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0x0;
679 PartialDescriptor
->u
.Port
.Length
= 7;
682 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[1];
683 PartialDescriptor
->Type
= CmResourceTypeInterrupt
;
684 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
685 PartialDescriptor
->Flags
= CM_RESOURCE_INTERRUPT_LATCHED
;
686 PartialDescriptor
->u
.Interrupt
.Level
= Irq
[i
];
687 PartialDescriptor
->u
.Interrupt
.Vector
= Irq
[i
];
688 PartialDescriptor
->u
.Interrupt
.Affinity
= 0xFFFFFFFF;
690 /* Set serial data (device specific) */
691 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[2];
692 PartialDescriptor
->Type
= CmResourceTypeDeviceSpecific
;
693 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
694 PartialDescriptor
->Flags
= 0;
695 PartialDescriptor
->u
.DeviceSpecificData
.DataSize
= sizeof(CM_SERIAL_DEVICE_DATA
);
698 (PCM_SERIAL_DEVICE_DATA
)&PartialResourceList
->PartialDescriptors
[3];
699 SerialDeviceData
->BaudClock
= 1843200; /* UART Clock frequency (Hertz) */
701 /* Create controller key */
702 FldrCreateComponentKey(BusKey
,
705 Output
| Input
| ConsoleIn
| ConsoleOut
,
713 if (!Rs232PortInUse(UlongToPtr(Base
)))
715 /* Detect serial mouse */
716 DetectSerialPointerPeripheral(ControllerKey
, UlongToPtr(Base
));
724 DetectParallelPorts(PCONFIGURATION_COMPONENT_DATA BusKey
)
726 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
727 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
728 ULONG Irq
[MAX_LPT_PORTS
] = {7, 5, (ULONG
) - 1};
730 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
733 ULONG ControllerNumber
= 0;
737 TRACE("DetectParallelPorts() called\n");
740 * The BIOS data area 0x408 holds the address of the first valid LPT port.
741 * Each LPT port address is stored in a 2-byte field.
742 * Infos at: http://www.bioscentral.com/misc/bda.htm
744 BasePtr
= (PUSHORT
)0x408;
746 for (i
= 0; i
< MAX_LPT_PORTS
; i
++, BasePtr
++)
748 Base
= (ULONG
) * BasePtr
;
752 TRACE("Parallel port %u: %x\n", ControllerNumber
, Base
);
754 /* Set 'Identifier' value */
755 sprintf(Buffer
, "PARALLEL%ld", i
+ 1);
757 /* Build full device descriptor */
758 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
);
759 if (Irq
[i
] != (ULONG
) - 1)
760 Size
+= sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
762 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
763 if (PartialResourceList
== NULL
)
765 ERR("Failed to allocate resource descriptor\n");
768 memset(PartialResourceList
, 0, Size
);
770 /* Initialize resource descriptor */
771 PartialResourceList
->Version
= 1;
772 PartialResourceList
->Revision
= 1;
773 PartialResourceList
->Count
= (Irq
[i
] != (ULONG
) - 1) ? 2 : 1;
776 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[0];
777 PartialDescriptor
->Type
= CmResourceTypePort
;
778 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
779 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
780 PartialDescriptor
->u
.Port
.Start
.LowPart
= Base
;
781 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0x0;
782 PartialDescriptor
->u
.Port
.Length
= 3;
785 if (Irq
[i
] != (ULONG
) - 1)
787 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[1];
788 PartialDescriptor
->Type
= CmResourceTypeInterrupt
;
789 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
790 PartialDescriptor
->Flags
= CM_RESOURCE_INTERRUPT_LATCHED
;
791 PartialDescriptor
->u
.Interrupt
.Level
= Irq
[i
];
792 PartialDescriptor
->u
.Interrupt
.Vector
= Irq
[i
];
793 PartialDescriptor
->u
.Interrupt
.Affinity
= 0xFFFFFFFF;
796 /* Create controller key */
797 FldrCreateComponentKey(BusKey
,
811 TRACE("DetectParallelPorts() done\n");
816 DetectKeyboardDevice(VOID
)
821 BOOLEAN Result
= TRUE
;
823 /* Identify device */
824 WRITE_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
, 0xF2);
827 for (Loops
= 0; Loops
< 100; Loops
++)
829 StallExecutionProcessor(10000);
830 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
831 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) != 0)
835 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) == 0)
837 /* PC/XT keyboard or no keyboard */
841 Scancode
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
842 if (Scancode
!= 0xFA)
844 /* No ACK received */
848 StallExecutionProcessor(10000);
850 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
851 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) == 0)
853 /* Found AT keyboard */
857 Scancode
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
858 if (Scancode
!= 0xAB)
860 /* No 0xAB received */
864 StallExecutionProcessor(10000);
866 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
867 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) == 0)
869 /* No byte in buffer */
873 Scancode
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
874 if (Scancode
!= 0x41)
876 /* No 0x41 received */
880 /* Found MF-II keyboard */
885 DetectKeyboardPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey
)
887 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
888 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
889 PCM_KEYBOARD_DEVICE_DATA KeyboardData
;
890 PCONFIGURATION_COMPONENT_DATA PeripheralKey
;
893 /* HACK: don't call DetectKeyboardDevice() as it fails in Qemu 0.8.2
894 if (DetectKeyboardDevice()) */
896 /* Set 'Configuration Data' value */
897 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
898 sizeof(CM_KEYBOARD_DEVICE_DATA
);
899 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
900 if (PartialResourceList
== NULL
)
902 ERR("Failed to allocate resource descriptor\n");
906 /* Initialize resource descriptor */
907 memset(PartialResourceList
, 0, Size
);
908 PartialResourceList
->Version
= 1;
909 PartialResourceList
->Revision
= 1;
910 PartialResourceList
->Count
= 1;
912 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[0];
913 PartialDescriptor
->Type
= CmResourceTypeDeviceSpecific
;
914 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
915 PartialDescriptor
->u
.DeviceSpecificData
.DataSize
= sizeof(CM_KEYBOARD_DEVICE_DATA
);
917 KeyboardData
= (PCM_KEYBOARD_DEVICE_DATA
)(PartialDescriptor
+ 1);
918 KeyboardData
->Version
= 1;
919 KeyboardData
->Revision
= 1;
920 KeyboardData
->Type
= 4;
921 KeyboardData
->Subtype
= 0;
922 KeyboardData
->KeyboardFlags
= 0x20;
924 /* Create controller key */
925 FldrCreateComponentKey(ControllerKey
,
935 TRACE("Created key: KeyboardPeripheral\\0\n");
941 DetectKeyboardController(PCONFIGURATION_COMPONENT_DATA BusKey
)
943 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
944 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
945 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
948 /* Set 'Configuration Data' value */
949 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
950 2 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
951 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
952 if (PartialResourceList
== NULL
)
954 ERR("Failed to allocate resource descriptor\n");
958 /* Initialize resource descriptor */
959 memset(PartialResourceList
, 0, Size
);
960 PartialResourceList
->Version
= 1;
961 PartialResourceList
->Revision
= 1;
962 PartialResourceList
->Count
= 3;
965 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[0];
966 PartialDescriptor
->Type
= CmResourceTypeInterrupt
;
967 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
968 PartialDescriptor
->Flags
= CM_RESOURCE_INTERRUPT_LATCHED
;
969 PartialDescriptor
->u
.Interrupt
.Level
= 1;
970 PartialDescriptor
->u
.Interrupt
.Vector
= 1;
971 PartialDescriptor
->u
.Interrupt
.Affinity
= 0xFFFFFFFF;
973 /* Set IO Port 0x60 */
974 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[1];
975 PartialDescriptor
->Type
= CmResourceTypePort
;
976 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
977 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
978 PartialDescriptor
->u
.Port
.Start
.LowPart
= 0x60;
979 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0x0;
980 PartialDescriptor
->u
.Port
.Length
= 1;
982 /* Set IO Port 0x64 */
983 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[2];
984 PartialDescriptor
->Type
= CmResourceTypePort
;
985 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
986 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
987 PartialDescriptor
->u
.Port
.Start
.LowPart
= 0x64;
988 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0x0;
989 PartialDescriptor
->u
.Port
.Length
= 1;
991 /* Create controller key */
992 FldrCreateComponentKey(BusKey
,
1002 TRACE("Created key: KeyboardController\\0\n");
1004 DetectKeyboardPeripheral(ControllerKey
);
1009 PS2ControllerWait(VOID
)
1014 for (Timeout
= 0; Timeout
< CONTROLLER_TIMEOUT
; Timeout
++)
1016 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1017 if ((Status
& CONTROLLER_STATUS_INPUT_BUFFER_FULL
) == 0)
1020 /* Sleep for one millisecond */
1021 StallExecutionProcessor(1000);
1027 DetectPS2AuxPort(VOID
)
1030 /* Current detection is too unreliable. Just do as if
1031 * the PS/2 aux port is always present
1038 /* Put the value 0x5A in the output buffer using the
1039 * "WriteAuxiliary Device Output Buffer" command (0xD3).
1040 * Poll the Status Register for a while to see if the value really turns up
1041 * in the Data Register. If the KEYBOARD_STATUS_MOUSE_OBF bit is also set
1042 * to 1 in the Status Register, we assume this controller has an
1043 * Auxiliary Port (a.k.a. Mouse Port).
1045 PS2ControllerWait();
1046 WRITE_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_CONTROL
,
1047 CONTROLLER_COMMAND_WRITE_MOUSE_OUTPUT_BUFFER
);
1048 PS2ControllerWait();
1050 /* 0x5A is a random dummy value */
1051 WRITE_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
,
1054 for (Loops
= 0; Loops
< 10; Loops
++)
1056 StallExecutionProcessor(10000);
1057 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1058 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) != 0)
1062 READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
1064 return (Status
& CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL
);
1070 DetectPS2AuxDevice(VOID
)
1075 BOOLEAN Result
= TRUE
;
1077 PS2ControllerWait();
1078 WRITE_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_CONTROL
,
1079 CONTROLLER_COMMAND_WRITE_MOUSE
);
1080 PS2ControllerWait();
1082 /* Identify device */
1083 WRITE_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
, 0xF2);
1085 /* Wait for reply */
1086 for (Loops
= 0; Loops
< 100; Loops
++)
1088 StallExecutionProcessor(10000);
1089 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1090 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) != 0)
1094 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1095 if ((Status
& CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL
) == 0)
1098 Scancode
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
1099 if (Scancode
!= 0xFA)
1102 StallExecutionProcessor(10000);
1104 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1105 if ((Status
& CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL
) == 0)
1108 Scancode
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
1109 if (Scancode
!= 0x00)
1115 // FIXME: Missing: DetectPS2Peripheral!! (for corresponding 'PointerPeripheral')
1119 DetectPS2Mouse(PCONFIGURATION_COMPONENT_DATA BusKey
)
1121 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
1122 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
1123 PCONFIGURATION_COMPONENT_DATA PeripheralKey
;
1126 if (DetectPS2AuxPort())
1128 TRACE("Detected PS2 port\n");
1130 PartialResourceList
= FrLdrHeapAlloc(sizeof(CM_PARTIAL_RESOURCE_LIST
), TAG_HW_RESOURCE_LIST
);
1131 if (PartialResourceList
== NULL
)
1133 ERR("Failed to allocate resource descriptor\n");
1136 memset(PartialResourceList
, 0, sizeof(CM_PARTIAL_RESOURCE_LIST
));
1138 /* Initialize resource descriptor */
1139 PartialResourceList
->Version
= 1;
1140 PartialResourceList
->Revision
= 1;
1141 PartialResourceList
->Count
= 1;
1144 PartialResourceList
->PartialDescriptors
[0].Type
= CmResourceTypeInterrupt
;
1145 PartialResourceList
->PartialDescriptors
[0].ShareDisposition
= CmResourceShareUndetermined
;
1146 PartialResourceList
->PartialDescriptors
[0].Flags
= CM_RESOURCE_INTERRUPT_LATCHED
;
1147 PartialResourceList
->PartialDescriptors
[0].u
.Interrupt
.Level
= 12;
1148 PartialResourceList
->PartialDescriptors
[0].u
.Interrupt
.Vector
= 12;
1149 PartialResourceList
->PartialDescriptors
[0].u
.Interrupt
.Affinity
= 0xFFFFFFFF;
1151 /* Create controller key */
1152 FldrCreateComponentKey(BusKey
,
1159 PartialResourceList
,
1160 sizeof(CM_PARTIAL_RESOURCE_LIST
),
1162 TRACE("Created key: PointerController\\0\n");
1164 if (DetectPS2AuxDevice())
1166 TRACE("Detected PS2 mouse\n");
1168 /* Initialize resource descriptor */
1169 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) -
1170 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1171 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
1172 if (PartialResourceList
== NULL
)
1174 ERR("Failed to allocate resource descriptor\n");
1177 memset(PartialResourceList
, 0, Size
);
1178 PartialResourceList
->Version
= 1;
1179 PartialResourceList
->Revision
= 1;
1180 PartialResourceList
->Count
= 0;
1182 /* Create peripheral key */
1183 FldrCreateComponentKey(ControllerKey
,
1189 "MICROSOFT PS2 MOUSE",
1190 PartialResourceList
,
1193 TRACE("Created key: PointerPeripheral\\0\n");
1199 DetectDisplayController(PCONFIGURATION_COMPONENT_DATA BusKey
)
1202 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
1205 /* FIXME: Set 'ComponentInformation' value */
1207 VesaVersion
= BiosIsVesaSupported();
1208 if (VesaVersion
!= 0)
1210 TRACE("VESA version %c.%c\n",
1211 (VesaVersion
>> 8) + '0',
1212 (VesaVersion
& 0xFF) + '0');
1216 TRACE("VESA not supported\n");
1219 if (VesaVersion
>= 0x0200)
1221 strcpy(Buffer
, "VBE Display");
1225 strcpy(Buffer
, "VGA Display");
1228 FldrCreateComponentKey(BusKey
,
1238 TRACE("Created key: DisplayController\\0\n");
1240 /* FIXME: Add display peripheral (monitor) data */
1241 if (VesaVersion
!= 0)
1243 if (BiosIsVesaDdcSupported())
1245 TRACE("VESA/DDC supported!\n");
1246 if (BiosVesaReadEdid())
1248 TRACE("EDID data read successfully!\n");
1256 DetectBiosDisks(PCONFIGURATION_COMPONENT_DATA BusKey
);
1260 DetectIsaBios(PCONFIGURATION_COMPONENT_DATA SystemKey
, ULONG
*BusNumber
)
1262 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
1263 PCONFIGURATION_COMPONENT_DATA BusKey
;
1266 /* Set 'Configuration Data' value */
1267 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) -
1268 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1269 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
1270 if (PartialResourceList
== NULL
)
1272 ERR("Failed to allocate resource descriptor\n");
1276 /* Initialize resource descriptor */
1277 memset(PartialResourceList
, 0, Size
);
1278 PartialResourceList
->Version
= 1;
1279 PartialResourceList
->Revision
= 1;
1280 PartialResourceList
->Count
= 0;
1282 /* Create new bus key */
1283 FldrCreateComponentKey(SystemKey
,
1285 MultiFunctionAdapter
,
1290 PartialResourceList
,
1294 /* Increment bus number */
1297 /* Detect ISA/BIOS devices */
1298 DetectBiosDisks(BusKey
);
1299 DetectSerialPorts(BusKey
);
1300 DetectParallelPorts(BusKey
);
1301 DetectKeyboardController(BusKey
);
1302 DetectPS2Mouse(BusKey
);
1303 DetectDisplayController(BusKey
);
1305 /* FIXME: Detect more ISA devices */
1308 extern PCONFIGURATION_COMPONENT_DATA
1311 PCONFIGURATION_COMPONENT_DATA
1314 PCONFIGURATION_COMPONENT_DATA SystemKey
;
1315 ULONG BusNumber
= 0;
1317 TRACE("DetectHardware()\n");
1319 /* Create the 'System' key */
1320 SystemKey
= DetectSystem();
1323 DetectPciBios(SystemKey
, &BusNumber
);
1324 DetectApmBios(SystemKey
, &BusNumber
);
1325 DetectPnpBios(SystemKey
, &BusNumber
);
1326 DetectIsaBios(SystemKey
, &BusNumber
); // TODO: Detect first EISA or MCA, before ISA
1327 DetectAcpiBios(SystemKey
, &BusNumber
);
1329 TRACE("DetectHardware() Done\n");
1338 /* Select APM 1.0+ function */
1341 /* Function 05h: CPU idle */
1345 Int386(0x15, &Regs
, &Regs
);
1347 /* Check if successfull (CF set on error) */
1348 if (INT386_SUCCESS(Regs
))
1352 * No futher processing here.
1353 * Optionally implement HLT instruction handling.
1358 /******************************************************************************/
1361 PcMachInit(const char *CmdLine
)
1364 MachVtbl
.ConsPutChar
= PcConsPutChar
;
1365 MachVtbl
.ConsKbHit
= PcConsKbHit
;
1366 MachVtbl
.ConsGetCh
= PcConsGetCh
;
1367 MachVtbl
.VideoClearScreen
= PcVideoClearScreen
;
1368 MachVtbl
.VideoSetDisplayMode
= PcVideoSetDisplayMode
;
1369 MachVtbl
.VideoGetDisplaySize
= PcVideoGetDisplaySize
;
1370 MachVtbl
.VideoGetBufferSize
= PcVideoGetBufferSize
;
1371 MachVtbl
.VideoSetTextCursorPosition
= PcVideoSetTextCursorPosition
;
1372 MachVtbl
.VideoHideShowTextCursor
= PcVideoHideShowTextCursor
;
1373 MachVtbl
.VideoPutChar
= PcVideoPutChar
;
1374 MachVtbl
.VideoCopyOffScreenBufferToVRAM
= PcVideoCopyOffScreenBufferToVRAM
;
1375 MachVtbl
.VideoIsPaletteFixed
= PcVideoIsPaletteFixed
;
1376 MachVtbl
.VideoSetPaletteColor
= PcVideoSetPaletteColor
;
1377 MachVtbl
.VideoGetPaletteColor
= PcVideoGetPaletteColor
;
1378 MachVtbl
.VideoSync
= PcVideoSync
;
1379 MachVtbl
.Beep
= PcBeep
;
1380 MachVtbl
.PrepareForReactOS
= PcPrepareForReactOS
;
1381 MachVtbl
.GetMemoryMap
= PcMemGetMemoryMap
;
1382 MachVtbl
.DiskGetBootPath
= PcDiskGetBootPath
;
1383 MachVtbl
.DiskReadLogicalSectors
= PcDiskReadLogicalSectors
;
1384 MachVtbl
.DiskGetDriveGeometry
= PcDiskGetDriveGeometry
;
1385 MachVtbl
.DiskGetCacheableBlockCount
= PcDiskGetCacheableBlockCount
;
1386 MachVtbl
.GetTime
= PcGetTime
;
1387 MachVtbl
.InitializeBootDevices
= PcInitializeBootDevices
;
1388 MachVtbl
.HwDetect
= PcHwDetect
;
1389 MachVtbl
.HwIdle
= PcHwIdle
;
1393 PcPrepareForReactOS(IN BOOLEAN Setup
)
1395 /* On PC, prepare video and turn off the floppy motor */
1396 PcVideoPrepareForReactOS(Setup
);
1397 DiskStopFloppyMotor();