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>
23 DBG_DEFAULT_CHANNEL(HWDETECT
);
26 /* Maximum number of COM and LPT ports */
27 #define MAX_COM_PORTS 4
28 #define MAX_LPT_PORTS 3
31 #define MOUSE_TYPE_NONE 0
32 /* Microsoft Mouse with 2 buttons */
33 #define MOUSE_TYPE_MICROSOFT 1
34 /* Logitech Mouse with 3 buttons */
35 #define MOUSE_TYPE_LOGITECH 2
36 /* Microsoft Wheel Mouse (aka Z Mouse) */
37 #define MOUSE_TYPE_WHEELZ 3
38 /* Mouse Systems Mouse */
39 #define MOUSE_TYPE_MOUSESYSTEMS 4
44 /* Controller registers. */
45 #define CONTROLLER_REGISTER_STATUS 0x64
46 #define CONTROLLER_REGISTER_CONTROL 0x64
47 #define CONTROLLER_REGISTER_DATA 0x60
49 /* Controller commands. */
50 #define CONTROLLER_COMMAND_READ_MODE 0x20
51 #define CONTROLLER_COMMAND_WRITE_MODE 0x60
52 #define CONTROLLER_COMMAND_GET_VERSION 0xA1
53 #define CONTROLLER_COMMAND_MOUSE_DISABLE 0xA7
54 #define CONTROLLER_COMMAND_MOUSE_ENABLE 0xA8
55 #define CONTROLLER_COMMAND_TEST_MOUSE 0xA9
56 #define CONTROLLER_COMMAND_SELF_TEST 0xAA
57 #define CONTROLLER_COMMAND_KEYBOARD_TEST 0xAB
58 #define CONTROLLER_COMMAND_KEYBOARD_DISABLE 0xAD
59 #define CONTROLLER_COMMAND_KEYBOARD_ENABLE 0xAE
60 #define CONTROLLER_COMMAND_WRITE_MOUSE_OUTPUT_BUFFER 0xD3
61 #define CONTROLLER_COMMAND_WRITE_MOUSE 0xD4
63 /* Controller status */
64 #define CONTROLLER_STATUS_OUTPUT_BUFFER_FULL 0x01
65 #define CONTROLLER_STATUS_INPUT_BUFFER_FULL 0x02
66 #define CONTROLLER_STATUS_SELF_TEST 0x04
67 #define CONTROLLER_STATUS_COMMAND 0x08
68 #define CONTROLLER_STATUS_UNLOCKED 0x10
69 #define CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL 0x20
70 #define CONTROLLER_STATUS_GENERAL_TIMEOUT 0x40
71 #define CONTROLLER_STATUS_PARITY_ERROR 0x80
72 #define AUX_STATUS_OUTPUT_BUFFER_FULL (CONTROLLER_STATUS_OUTPUT_BUFFER_FULL | \
73 CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL)
75 /* Timeout in ms for sending to keyboard controller. */
76 #define CONTROLLER_TIMEOUT 250
80 PcGetExtendedBIOSData(PULONG ExtendedBIOSDataArea
, PULONG ExtendedBIOSDataSize
)
84 /* Get address and size of the extended BIOS data area */
85 BiosRegs
.d
.eax
= 0xC100;
86 Int386(0x15, &BiosRegs
, &BiosRegs
);
87 if (INT386_SUCCESS(BiosRegs
))
89 *ExtendedBIOSDataArea
= BiosRegs
.w
.es
<< 4;
90 *ExtendedBIOSDataSize
= 1024;
94 WARN("Int 15h AH=C1h call failed\n");
95 *ExtendedBIOSDataArea
= 0;
96 *ExtendedBIOSDataSize
= 0;
100 // NOTE: Similar to machxbox.c!XboxGetHarddiskConfigurationData(),
101 // but with extended geometry support.
103 PCM_PARTIAL_RESOURCE_LIST
104 PcGetHarddiskConfigurationData(UCHAR DriveNumber
, ULONG
* pSize
)
106 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
107 PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry
;
108 EXTENDED_GEOMETRY ExtGeometry
;
113 // Initialize returned size
117 /* Set 'Configuration Data' value */
118 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
119 sizeof(CM_DISK_GEOMETRY_DEVICE_DATA
);
120 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
121 if (PartialResourceList
== NULL
)
123 ERR("Failed to allocate resource descriptor\n");
127 memset(PartialResourceList
, 0, Size
);
128 PartialResourceList
->Version
= 1;
129 PartialResourceList
->Revision
= 1;
130 PartialResourceList
->Count
= 1;
131 PartialResourceList
->PartialDescriptors
[0].Type
=
132 CmResourceTypeDeviceSpecific
;
133 // PartialResourceList->PartialDescriptors[0].ShareDisposition =
134 // PartialResourceList->PartialDescriptors[0].Flags =
135 PartialResourceList
->PartialDescriptors
[0].u
.DeviceSpecificData
.DataSize
=
136 sizeof(CM_DISK_GEOMETRY_DEVICE_DATA
);
138 /* Get pointer to geometry data */
139 DiskGeometry
= (PVOID
)(((ULONG_PTR
)PartialResourceList
) + sizeof(CM_PARTIAL_RESOURCE_LIST
));
141 /* Get the disk geometry */
142 ExtGeometry
.Size
= sizeof(EXTENDED_GEOMETRY
);
143 if (DiskGetExtendedDriveParameters(DriveNumber
, &ExtGeometry
, ExtGeometry
.Size
))
145 DiskGeometry
->BytesPerSector
= ExtGeometry
.BytesPerSector
;
146 DiskGeometry
->NumberOfCylinders
= ExtGeometry
.Cylinders
;
147 DiskGeometry
->SectorsPerTrack
= ExtGeometry
.SectorsPerTrack
;
148 DiskGeometry
->NumberOfHeads
= ExtGeometry
.Heads
;
150 else if (MachDiskGetDriveGeometry(DriveNumber
, &Geometry
))
152 DiskGeometry
->BytesPerSector
= Geometry
.BytesPerSector
;
153 DiskGeometry
->NumberOfCylinders
= Geometry
.Cylinders
;
154 DiskGeometry
->SectorsPerTrack
= Geometry
.Sectors
;
155 DiskGeometry
->NumberOfHeads
= Geometry
.Heads
;
159 TRACE("Reading disk geometry failed\n");
160 FrLdrHeapFree(PartialResourceList
, TAG_HW_RESOURCE_LIST
);
163 TRACE("Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n",
165 DiskGeometry
->NumberOfCylinders
,
166 DiskGeometry
->NumberOfHeads
,
167 DiskGeometry
->SectorsPerTrack
,
168 DiskGeometry
->BytesPerSector
);
171 // Return configuration data
174 return PartialResourceList
;
179 DetectPnpBios(PCONFIGURATION_COMPONENT_DATA SystemKey
, ULONG
*BusNumber
)
181 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
182 PCM_PNP_BIOS_DEVICE_NODE DeviceNode
;
183 PCM_PNP_BIOS_INSTALLATION_CHECK InstData
;
184 PCONFIGURATION_COMPONENT_DATA BusKey
;
189 ULONG FoundNodeCount
;
192 ULONG PnpBufferSizeLimit
;
196 InstData
= (PCM_PNP_BIOS_INSTALLATION_CHECK
)PnpBiosSupported();
197 if (InstData
== NULL
|| strncmp((CHAR
*)InstData
->Signature
, "$PnP", 4))
199 TRACE("PnP-BIOS not supported\n");
203 TRACE("PnP-BIOS supported\n");
204 TRACE("Signature '%c%c%c%c'\n",
205 InstData
->Signature
[0], InstData
->Signature
[1],
206 InstData
->Signature
[2], InstData
->Signature
[3]);
208 x
= PnpBiosGetDeviceNodeCount(&NodeSize
, &NodeCount
);
211 TRACE("PnP-BIOS function 'Get Number of System Device Nodes' not supported\n");
215 NodeCount
&= 0xFF; // needed since some fscked up BIOSes return
216 // wrong info (e.g. Mac Virtual PC)
217 // e.g. look: http://my.execpc.com/~geezer/osd/pnp/pnp16.c
218 if (x
!= 0 || NodeSize
== 0 || NodeCount
== 0)
220 ERR("PnP-BIOS failed to enumerate device nodes\n");
223 TRACE("MaxNodeSize %u NodeCount %u\n", NodeSize
, NodeCount
);
224 TRACE("Estimated buffer size %u\n", NodeSize
* NodeCount
);
226 /* Set 'Configuration Data' value */
227 PnpBufferSizeLimit
= sizeof(CM_PNP_BIOS_INSTALLATION_CHECK
)
228 + (NodeSize
* NodeCount
);
229 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) + PnpBufferSizeLimit
;
230 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
231 if (PartialResourceList
== NULL
)
233 ERR("Failed to allocate resource descriptor\n");
236 memset(PartialResourceList
, 0, Size
);
238 /* Initialize resource descriptor */
239 PartialResourceList
->Version
= 1;
240 PartialResourceList
->Revision
= 1;
241 PartialResourceList
->Count
= 1;
242 PartialResourceList
->PartialDescriptors
[0].Type
=
243 CmResourceTypeDeviceSpecific
;
244 PartialResourceList
->PartialDescriptors
[0].ShareDisposition
=
245 CmResourceShareUndetermined
;
247 /* The buffer starts after PartialResourceList->PartialDescriptors[0] */
248 Ptr
= (char *)(PartialResourceList
+ 1);
250 /* Set installation check data */
251 memcpy (Ptr
, InstData
, sizeof(CM_PNP_BIOS_INSTALLATION_CHECK
));
252 Ptr
+= sizeof(CM_PNP_BIOS_INSTALLATION_CHECK
);
253 PnpBufferSize
= sizeof(CM_PNP_BIOS_INSTALLATION_CHECK
);
255 /* Copy device nodes */
257 for (i
= 0; i
< 0xFF; i
++)
259 NodeNumber
= (UCHAR
)i
;
261 x
= PnpBiosGetDeviceNode(&NodeNumber
, DiskReadBuffer
);
264 DeviceNode
= (PCM_PNP_BIOS_DEVICE_NODE
)DiskReadBuffer
;
266 TRACE("Node: %u Size %u (0x%x)\n",
271 if (PnpBufferSize
+ DeviceNode
->Size
> PnpBufferSizeLimit
)
273 ERR("Buffer too small! Ignoring remaining device nodes.\n");
277 memcpy(Ptr
, DeviceNode
, DeviceNode
->Size
);
279 Ptr
+= DeviceNode
->Size
;
280 PnpBufferSize
+= DeviceNode
->Size
;
283 if (FoundNodeCount
>= NodeCount
)
288 /* Set real data size */
289 PartialResourceList
->PartialDescriptors
[0].u
.DeviceSpecificData
.DataSize
=
291 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) + PnpBufferSize
;
293 TRACE("Real buffer size: %u\n", PnpBufferSize
);
294 TRACE("Resource size: %u\n", Size
);
296 /* Create component key */
297 FldrCreateComponentKey(SystemKey
,
299 MultiFunctionAdapter
,
313 InitializeSerialPort(PUCHAR Port
,
316 WRITE_PORT_UCHAR(Port
+ 3, 0x80); /* set DLAB on */
317 WRITE_PORT_UCHAR(Port
, 0x60); /* speed LO byte */
318 WRITE_PORT_UCHAR(Port
+ 1, 0); /* speed HI byte */
319 WRITE_PORT_UCHAR(Port
+ 3, LineControl
);
320 WRITE_PORT_UCHAR(Port
+ 1, 0); /* set comm and DLAB to 0 */
321 WRITE_PORT_UCHAR(Port
+ 4, 0x09); /* DR int enable */
322 READ_PORT_UCHAR(Port
+ 5); /* clear error bits */
327 DetectSerialMouse(PUCHAR Port
)
334 /* Shutdown mouse or something like that */
335 LineControl
= READ_PORT_UCHAR(Port
+ 4);
336 WRITE_PORT_UCHAR(Port
+ 4, (LineControl
& ~0x02) | 0x01);
337 StallExecutionProcessor(100000);
341 * Maybe there is no serial port although BIOS reported one (this
342 * is the case on Apple hardware), or the serial port is misbehaving,
343 * therefore we must give up after some time.
346 while (READ_PORT_UCHAR(Port
+ 5) & 0x01)
349 return MOUSE_TYPE_NONE
;
350 READ_PORT_UCHAR(Port
);
354 * Send modem control with 'Data Terminal Ready', 'Request To Send' and
355 * 'Output Line 2' message. This enables mouse to identify.
357 WRITE_PORT_UCHAR(Port
+ 4, 0x0b);
359 /* Wait 10 milliseconds for the mouse getting ready */
360 StallExecutionProcessor(10000);
362 /* Read first four bytes, which contains Microsoft Mouse signs */
364 for (i
= 0; i
< 4; i
++)
366 while ((READ_PORT_UCHAR(Port
+ 5) & 1) == 0)
368 StallExecutionProcessor(100);
371 return MOUSE_TYPE_NONE
;
373 Buffer
[i
] = READ_PORT_UCHAR(Port
);
376 TRACE("Mouse data: %x %x %x %x\n",
377 Buffer
[0], Buffer
[1], Buffer
[2], Buffer
[3]);
379 /* Check that four bytes for signs */
380 for (i
= 0; i
< 4; ++i
)
382 if (Buffer
[i
] == 'B')
384 /* Sign for Microsoft Ballpoint */
385 // DbgPrint("Microsoft Ballpoint device detected\n");
386 // DbgPrint("THIS DEVICE IS NOT SUPPORTED, YET\n");
387 return MOUSE_TYPE_NONE
;
389 else if (Buffer
[i
] == 'M')
391 /* Sign for Microsoft Mouse protocol followed by button specifier */
395 return MOUSE_TYPE_NONE
;
398 switch (Buffer
[i
+ 1])
401 TRACE("Microsoft Mouse with 3-buttons detected\n");
402 return MOUSE_TYPE_LOGITECH
;
405 TRACE("Microsoft Wheel Mouse detected\n");
406 return MOUSE_TYPE_WHEELZ
;
410 TRACE("Microsoft Mouse with 2-buttons detected\n");
411 return MOUSE_TYPE_MICROSOFT
;
416 return MOUSE_TYPE_NONE
;
420 GetSerialMousePnpId(PUCHAR Port
, char *Buffer
)
427 WRITE_PORT_UCHAR(Port
+ 4, 0x09);
429 /* Wait 10 milliseconds for the mouse getting ready */
430 StallExecutionProcessor(10000);
432 WRITE_PORT_UCHAR(Port
+ 4, 0x0b);
434 StallExecutionProcessor(10000);
439 while (((READ_PORT_UCHAR(Port
+ 5) & 1) == 0) && (TimeOut
> 0))
441 StallExecutionProcessor(1000);
449 c
= READ_PORT_UCHAR(Port
);
450 if (c
== 0x08 || c
== 0x28)
460 while (((READ_PORT_UCHAR(Port
+ 5) & 1) == 0) && (TimeOut
> 0))
462 StallExecutionProcessor(1000);
467 c
= READ_PORT_UCHAR(Port
);
480 DetectSerialPointerPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey
,
483 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
485 CHAR Identifier
[256];
486 PCONFIGURATION_COMPONENT_DATA PeripheralKey
;
493 TRACE("DetectSerialPointerPeripheral()\n");
497 InitializeSerialPort(Base
, 2);
498 MouseType
= DetectSerialMouse(Base
);
500 if (MouseType
!= MOUSE_TYPE_NONE
)
502 Length
= GetSerialMousePnpId(Base
, Buffer
);
503 TRACE( "PnP ID length: %u\n", Length
);
507 /* Convert PnP sting to ASCII */
508 if (Buffer
[0] == 0x08)
510 for (i
= 0; i
< Length
; i
++)
515 TRACE("PnP ID string: %s\n", Buffer
);
517 /* Copy PnpId string */
518 for (i
= 0; i
< 7; i
++)
520 Identifier
[i
] = Buffer
[3 + i
];
522 memcpy(&Identifier
[7],
526 /* Skip device serial number */
528 if (Buffer
[i
] == '\\')
530 for (j
= ++i
; i
< Length
; ++i
)
532 if (Buffer
[i
] == '\\')
540 if (Buffer
[i
] == '\\')
542 for (j
= ++i
; i
< Length
; ++i
)
544 if (Buffer
[i
] == '\\')
552 /* Skip compatible PnP Id */
553 if (Buffer
[i
] == '\\')
555 for (j
= ++i
; i
< Length
; ++i
)
557 if (Buffer
[i
] == '\\')
560 if (Buffer
[j
] == '*')
566 /* Get product description */
567 if (Buffer
[i
] == '\\')
569 for (j
= ++i
; i
< Length
; ++i
)
571 if (Buffer
[i
] == ';')
578 for (k
= 0; k
< i
- j
; k
++)
580 Identifier
[k
+ 10] = Buffer
[k
+ j
];
582 Identifier
[10 + (i
- j
)] = 0;
586 TRACE("Identifier string: %s\n", Identifier
);
589 if (Length
== 0 || strlen(Identifier
) < 11)
593 case MOUSE_TYPE_LOGITECH
:
594 strcpy(Identifier
, "LOGITECH SERIAL MOUSE");
597 case MOUSE_TYPE_WHEELZ
:
598 strcpy(Identifier
, "MICROSOFT SERIAL MOUSE WITH WHEEL");
601 case MOUSE_TYPE_MICROSOFT
:
603 strcpy(Identifier
, "MICROSOFT SERIAL MOUSE");
608 /* Set 'Configuration Data' value */
609 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) -
610 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
611 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
612 if (PartialResourceList
== NULL
)
614 ERR("Failed to allocate resource descriptor\n");
617 memset(PartialResourceList
, 0, Size
);
618 PartialResourceList
->Version
= 1;
619 PartialResourceList
->Revision
= 1;
620 PartialResourceList
->Count
= 0;
622 /* Create 'PointerPeripheral' key */
623 FldrCreateComponentKey(ControllerKey
,
634 TRACE("Created key: PointerPeripheral\\0\n");
639 PcGetSerialPort(ULONG Index
, PULONG Irq
)
641 static const ULONG PcIrq
[MAX_COM_PORTS
] = {4, 3, 4, 3};
645 * The BIOS data area 0x400 holds the address of the first valid COM port.
646 * Each COM port address is stored in a 2-byte field.
647 * Infos at: http://www.bioscentral.com/misc/bda.htm
649 BasePtr
= (PUSHORT
)0x400;
652 return (ULONG
) *(BasePtr
+ Index
);
656 DetectSerialPorts(PCONFIGURATION_COMPONENT_DATA BusKey
, GET_SERIAL_PORT MachGetSerialPort
, ULONG Count
)
658 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
659 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
660 PCM_SERIAL_DEVICE_DATA SerialDeviceData
;
664 ULONG ControllerNumber
= 0;
665 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
669 TRACE("DetectSerialPorts()\n");
671 for (i
= 0; i
< Count
; i
++)
673 Base
= MachGetSerialPort(i
, &Irq
);
674 if ((Base
== 0) || !CpDoesPortExist(UlongToPtr(Base
)))
677 TRACE("Found COM%u port at 0x%x\n", i
+ 1, Base
);
679 /* Set 'Identifier' value */
680 sprintf(Buffer
, "COM%ld", i
+ 1);
682 /* Build full device descriptor */
683 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
684 2 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
) +
685 sizeof(CM_SERIAL_DEVICE_DATA
);
686 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
687 if (PartialResourceList
== NULL
)
689 ERR("Failed to allocate resource descriptor\n");
692 memset(PartialResourceList
, 0, Size
);
694 /* Initialize resource descriptor */
695 PartialResourceList
->Version
= 1;
696 PartialResourceList
->Revision
= 1;
697 PartialResourceList
->Count
= 3;
700 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[0];
701 PartialDescriptor
->Type
= CmResourceTypePort
;
702 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
703 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
704 PartialDescriptor
->u
.Port
.Start
.LowPart
= Base
;
705 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0x0;
706 PartialDescriptor
->u
.Port
.Length
= 7;
709 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[1];
710 PartialDescriptor
->Type
= CmResourceTypeInterrupt
;
711 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
712 PartialDescriptor
->Flags
= CM_RESOURCE_INTERRUPT_LATCHED
;
713 PartialDescriptor
->u
.Interrupt
.Level
= Irq
;
714 PartialDescriptor
->u
.Interrupt
.Vector
= Irq
;
715 PartialDescriptor
->u
.Interrupt
.Affinity
= 0xFFFFFFFF;
717 /* Set serial data (device specific) */
718 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[2];
719 PartialDescriptor
->Type
= CmResourceTypeDeviceSpecific
;
720 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
721 PartialDescriptor
->Flags
= 0;
722 PartialDescriptor
->u
.DeviceSpecificData
.DataSize
= sizeof(CM_SERIAL_DEVICE_DATA
);
725 (PCM_SERIAL_DEVICE_DATA
)&PartialResourceList
->PartialDescriptors
[3];
726 SerialDeviceData
->BaudClock
= 1843200; /* UART Clock frequency (Hertz) */
728 /* Create controller key */
729 FldrCreateComponentKey(BusKey
,
732 Output
| Input
| ConsoleIn
| ConsoleOut
,
740 if (!Rs232PortInUse(UlongToPtr(Base
)))
742 /* Detect serial mouse */
743 DetectSerialPointerPeripheral(ControllerKey
, UlongToPtr(Base
));
751 DetectParallelPorts(PCONFIGURATION_COMPONENT_DATA BusKey
)
753 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
754 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
755 ULONG Irq
[MAX_LPT_PORTS
] = {7, 5, (ULONG
) - 1};
757 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
760 ULONG ControllerNumber
= 0;
764 TRACE("DetectParallelPorts() called\n");
767 * The BIOS data area 0x408 holds the address of the first valid LPT port.
768 * Each LPT port address is stored in a 2-byte field.
769 * Infos at: http://www.bioscentral.com/misc/bda.htm
771 BasePtr
= (PUSHORT
)0x408;
773 for (i
= 0; i
< MAX_LPT_PORTS
; i
++, BasePtr
++)
775 Base
= (ULONG
) * BasePtr
;
779 TRACE("Parallel port %u: %x\n", ControllerNumber
, Base
);
781 /* Set 'Identifier' value */
782 sprintf(Buffer
, "PARALLEL%ld", i
+ 1);
784 /* Build full device descriptor */
785 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
);
786 if (Irq
[i
] != (ULONG
) - 1)
787 Size
+= sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
789 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
790 if (PartialResourceList
== NULL
)
792 ERR("Failed to allocate resource descriptor\n");
795 memset(PartialResourceList
, 0, Size
);
797 /* Initialize resource descriptor */
798 PartialResourceList
->Version
= 1;
799 PartialResourceList
->Revision
= 1;
800 PartialResourceList
->Count
= (Irq
[i
] != (ULONG
) - 1) ? 2 : 1;
803 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[0];
804 PartialDescriptor
->Type
= CmResourceTypePort
;
805 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
806 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
807 PartialDescriptor
->u
.Port
.Start
.LowPart
= Base
;
808 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0x0;
809 PartialDescriptor
->u
.Port
.Length
= 3;
812 if (Irq
[i
] != (ULONG
) - 1)
814 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[1];
815 PartialDescriptor
->Type
= CmResourceTypeInterrupt
;
816 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
817 PartialDescriptor
->Flags
= CM_RESOURCE_INTERRUPT_LATCHED
;
818 PartialDescriptor
->u
.Interrupt
.Level
= Irq
[i
];
819 PartialDescriptor
->u
.Interrupt
.Vector
= Irq
[i
];
820 PartialDescriptor
->u
.Interrupt
.Affinity
= 0xFFFFFFFF;
823 /* Create controller key */
824 FldrCreateComponentKey(BusKey
,
838 TRACE("DetectParallelPorts() done\n");
843 DetectKeyboardDevice(VOID
)
848 BOOLEAN Result
= TRUE
;
850 /* Identify device */
851 WRITE_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
, 0xF2);
854 for (Loops
= 0; Loops
< 100; Loops
++)
856 StallExecutionProcessor(10000);
857 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
858 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) != 0)
862 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) == 0)
864 /* PC/XT keyboard or no keyboard */
868 Scancode
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
869 if (Scancode
!= 0xFA)
871 /* No ACK received */
875 StallExecutionProcessor(10000);
877 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
878 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) == 0)
880 /* Found AT keyboard */
884 Scancode
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
885 if (Scancode
!= 0xAB)
887 /* No 0xAB received */
891 StallExecutionProcessor(10000);
893 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
894 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) == 0)
896 /* No byte in buffer */
900 Scancode
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
901 if (Scancode
!= 0x41)
903 /* No 0x41 received */
907 /* Found MF-II keyboard */
912 DetectKeyboardPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey
)
914 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
915 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
916 PCM_KEYBOARD_DEVICE_DATA KeyboardData
;
917 PCONFIGURATION_COMPONENT_DATA PeripheralKey
;
920 /* HACK: don't call DetectKeyboardDevice() as it fails in Qemu 0.8.2
921 if (DetectKeyboardDevice()) */
923 /* Set 'Configuration Data' value */
924 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
925 sizeof(CM_KEYBOARD_DEVICE_DATA
);
926 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
927 if (PartialResourceList
== NULL
)
929 ERR("Failed to allocate resource descriptor\n");
933 /* Initialize resource descriptor */
934 memset(PartialResourceList
, 0, Size
);
935 PartialResourceList
->Version
= 1;
936 PartialResourceList
->Revision
= 1;
937 PartialResourceList
->Count
= 1;
939 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[0];
940 PartialDescriptor
->Type
= CmResourceTypeDeviceSpecific
;
941 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
942 PartialDescriptor
->u
.DeviceSpecificData
.DataSize
= sizeof(CM_KEYBOARD_DEVICE_DATA
);
944 KeyboardData
= (PCM_KEYBOARD_DEVICE_DATA
)(PartialDescriptor
+ 1);
945 KeyboardData
->Version
= 1;
946 KeyboardData
->Revision
= 1;
947 KeyboardData
->Type
= 4;
948 KeyboardData
->Subtype
= 0;
949 KeyboardData
->KeyboardFlags
= 0x20;
951 /* Create controller key */
952 FldrCreateComponentKey(ControllerKey
,
962 TRACE("Created key: KeyboardPeripheral\\0\n");
968 DetectKeyboardController(PCONFIGURATION_COMPONENT_DATA BusKey
)
970 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
971 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
972 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
975 /* Set 'Configuration Data' value */
976 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
977 2 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
978 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
979 if (PartialResourceList
== NULL
)
981 ERR("Failed to allocate resource descriptor\n");
985 /* Initialize resource descriptor */
986 memset(PartialResourceList
, 0, Size
);
987 PartialResourceList
->Version
= 1;
988 PartialResourceList
->Revision
= 1;
989 PartialResourceList
->Count
= 3;
992 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[0];
993 PartialDescriptor
->Type
= CmResourceTypeInterrupt
;
994 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
995 PartialDescriptor
->Flags
= CM_RESOURCE_INTERRUPT_LATCHED
;
996 PartialDescriptor
->u
.Interrupt
.Level
= 1;
997 PartialDescriptor
->u
.Interrupt
.Vector
= 1;
998 PartialDescriptor
->u
.Interrupt
.Affinity
= 0xFFFFFFFF;
1000 /* Set IO Port 0x60 */
1001 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[1];
1002 PartialDescriptor
->Type
= CmResourceTypePort
;
1003 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
1004 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
1005 PartialDescriptor
->u
.Port
.Start
.LowPart
= 0x60;
1006 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0x0;
1007 PartialDescriptor
->u
.Port
.Length
= 1;
1009 /* Set IO Port 0x64 */
1010 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[2];
1011 PartialDescriptor
->Type
= CmResourceTypePort
;
1012 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
1013 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
1014 PartialDescriptor
->u
.Port
.Start
.LowPart
= 0x64;
1015 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0x0;
1016 PartialDescriptor
->u
.Port
.Length
= 1;
1018 /* Create controller key */
1019 FldrCreateComponentKey(BusKey
,
1026 PartialResourceList
,
1029 TRACE("Created key: KeyboardController\\0\n");
1031 DetectKeyboardPeripheral(ControllerKey
);
1036 PS2ControllerWait(VOID
)
1041 for (Timeout
= 0; Timeout
< CONTROLLER_TIMEOUT
; Timeout
++)
1043 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1044 if ((Status
& CONTROLLER_STATUS_INPUT_BUFFER_FULL
) == 0)
1047 /* Sleep for one millisecond */
1048 StallExecutionProcessor(1000);
1054 DetectPS2AuxPort(VOID
)
1057 /* Current detection is too unreliable. Just do as if
1058 * the PS/2 aux port is always present
1065 /* Put the value 0x5A in the output buffer using the
1066 * "WriteAuxiliary Device Output Buffer" command (0xD3).
1067 * Poll the Status Register for a while to see if the value really turns up
1068 * in the Data Register. If the KEYBOARD_STATUS_MOUSE_OBF bit is also set
1069 * to 1 in the Status Register, we assume this controller has an
1070 * Auxiliary Port (a.k.a. Mouse Port).
1072 PS2ControllerWait();
1073 WRITE_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_CONTROL
,
1074 CONTROLLER_COMMAND_WRITE_MOUSE_OUTPUT_BUFFER
);
1075 PS2ControllerWait();
1077 /* 0x5A is a random dummy value */
1078 WRITE_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
,
1081 for (Loops
= 0; Loops
< 10; Loops
++)
1083 StallExecutionProcessor(10000);
1084 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1085 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) != 0)
1089 READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
1091 return (Status
& CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL
);
1097 DetectPS2AuxDevice(VOID
)
1102 BOOLEAN Result
= TRUE
;
1104 PS2ControllerWait();
1105 WRITE_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_CONTROL
,
1106 CONTROLLER_COMMAND_WRITE_MOUSE
);
1107 PS2ControllerWait();
1109 /* Identify device */
1110 WRITE_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
, 0xF2);
1112 /* Wait for reply */
1113 for (Loops
= 0; Loops
< 100; Loops
++)
1115 StallExecutionProcessor(10000);
1116 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1117 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) != 0)
1121 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1122 if ((Status
& CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL
) == 0)
1125 Scancode
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
1126 if (Scancode
!= 0xFA)
1129 StallExecutionProcessor(10000);
1131 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1132 if ((Status
& CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL
) == 0)
1135 Scancode
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
1136 if (Scancode
!= 0x00)
1142 // FIXME: Missing: DetectPS2Peripheral!! (for corresponding 'PointerPeripheral')
1146 DetectPS2Mouse(PCONFIGURATION_COMPONENT_DATA BusKey
)
1148 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
1149 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
1150 PCONFIGURATION_COMPONENT_DATA PeripheralKey
;
1153 if (DetectPS2AuxPort())
1155 TRACE("Detected PS2 port\n");
1157 PartialResourceList
= FrLdrHeapAlloc(sizeof(CM_PARTIAL_RESOURCE_LIST
), TAG_HW_RESOURCE_LIST
);
1158 if (PartialResourceList
== NULL
)
1160 ERR("Failed to allocate resource descriptor\n");
1163 memset(PartialResourceList
, 0, sizeof(CM_PARTIAL_RESOURCE_LIST
));
1165 /* Initialize resource descriptor */
1166 PartialResourceList
->Version
= 1;
1167 PartialResourceList
->Revision
= 1;
1168 PartialResourceList
->Count
= 1;
1171 PartialResourceList
->PartialDescriptors
[0].Type
= CmResourceTypeInterrupt
;
1172 PartialResourceList
->PartialDescriptors
[0].ShareDisposition
= CmResourceShareUndetermined
;
1173 PartialResourceList
->PartialDescriptors
[0].Flags
= CM_RESOURCE_INTERRUPT_LATCHED
;
1174 PartialResourceList
->PartialDescriptors
[0].u
.Interrupt
.Level
= 12;
1175 PartialResourceList
->PartialDescriptors
[0].u
.Interrupt
.Vector
= 12;
1176 PartialResourceList
->PartialDescriptors
[0].u
.Interrupt
.Affinity
= 0xFFFFFFFF;
1178 /* Create controller key */
1179 FldrCreateComponentKey(BusKey
,
1186 PartialResourceList
,
1187 sizeof(CM_PARTIAL_RESOURCE_LIST
),
1189 TRACE("Created key: PointerController\\0\n");
1191 if (DetectPS2AuxDevice())
1193 TRACE("Detected PS2 mouse\n");
1195 /* Initialize resource descriptor */
1196 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) -
1197 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1198 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
1199 if (PartialResourceList
== NULL
)
1201 ERR("Failed to allocate resource descriptor\n");
1204 memset(PartialResourceList
, 0, Size
);
1205 PartialResourceList
->Version
= 1;
1206 PartialResourceList
->Revision
= 1;
1207 PartialResourceList
->Count
= 0;
1209 /* Create peripheral key */
1210 FldrCreateComponentKey(ControllerKey
,
1216 "MICROSOFT PS2 MOUSE",
1217 PartialResourceList
,
1220 TRACE("Created key: PointerPeripheral\\0\n");
1226 // Implemented in i386vid.c, returns the VESA version
1227 USHORT
BiosIsVesaSupported(VOID
);
1228 BOOLEAN
BiosIsVesaDdcSupported(VOID
);
1229 BOOLEAN
BiosVesaReadEdid(VOID
);
1232 DetectDisplayController(PCONFIGURATION_COMPONENT_DATA BusKey
)
1235 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
1238 /* FIXME: Set 'ComponentInformation' value */
1240 VesaVersion
= BiosIsVesaSupported();
1241 if (VesaVersion
!= 0)
1243 TRACE("VESA version %c.%c\n",
1244 (VesaVersion
>> 8) + '0',
1245 (VesaVersion
& 0xFF) + '0');
1249 TRACE("VESA not supported\n");
1252 if (VesaVersion
>= 0x0200)
1254 strcpy(Buffer
, "VBE Display");
1258 strcpy(Buffer
, "VGA Display");
1261 FldrCreateComponentKey(BusKey
,
1271 TRACE("Created key: DisplayController\\0\n");
1273 /* FIXME: Add display peripheral (monitor) data */
1274 if (VesaVersion
!= 0)
1276 if (BiosIsVesaDdcSupported())
1278 TRACE("VESA/DDC supported!\n");
1279 if (BiosVesaReadEdid())
1281 TRACE("EDID data read successfully!\n");
1290 DetectIsaBios(PCONFIGURATION_COMPONENT_DATA SystemKey
, ULONG
*BusNumber
)
1292 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
1293 PCONFIGURATION_COMPONENT_DATA BusKey
;
1296 /* Set 'Configuration Data' value */
1297 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) -
1298 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1299 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
1300 if (PartialResourceList
== NULL
)
1302 ERR("Failed to allocate resource descriptor\n");
1306 /* Initialize resource descriptor */
1307 memset(PartialResourceList
, 0, Size
);
1308 PartialResourceList
->Version
= 1;
1309 PartialResourceList
->Revision
= 1;
1310 PartialResourceList
->Count
= 0;
1312 /* Create new bus key */
1313 FldrCreateComponentKey(SystemKey
,
1315 MultiFunctionAdapter
,
1320 PartialResourceList
,
1324 /* Increment bus number */
1327 /* Detect ISA/BIOS devices */
1328 DetectBiosDisks(SystemKey
, BusKey
);
1329 DetectSerialPorts(BusKey
, PcGetSerialPort
, MAX_COM_PORTS
);
1330 DetectParallelPorts(BusKey
);
1331 DetectKeyboardController(BusKey
);
1332 DetectPS2Mouse(BusKey
);
1333 DetectDisplayController(BusKey
);
1335 /* FIXME: Detect more ISA devices */
1340 PcGetFloppyCount(VOID
)
1344 WRITE_PORT_UCHAR((PUCHAR
)0x70, 0x10);
1345 Data
= READ_PORT_UCHAR((PUCHAR
)0x71);
1347 return ((Data
& 0xF0) ? 1 : 0) + ((Data
& 0x0F) ? 1 : 0);
1350 PCONFIGURATION_COMPONENT_DATA
1353 PCONFIGURATION_COMPONENT_DATA SystemKey
;
1354 ULONG BusNumber
= 0;
1356 TRACE("DetectHardware()\n");
1358 /* Create the 'System' key */
1359 FldrCreateSystemKey(&SystemKey
);
1360 // TODO: Discover and set the machine type as the Component->Identifier
1362 GetHarddiskConfigurationData
= PcGetHarddiskConfigurationData
;
1363 FindPciBios
= PcFindPciBios
;
1366 DetectPciBios(SystemKey
, &BusNumber
);
1367 DetectApmBios(SystemKey
, &BusNumber
);
1368 DetectPnpBios(SystemKey
, &BusNumber
);
1369 DetectIsaBios(SystemKey
, &BusNumber
); // TODO: Detect first EISA or MCA, before ISA
1370 DetectAcpiBios(SystemKey
, &BusNumber
);
1372 // TODO: Collect the ROM blocks from 0xC0000 to 0xF0000 and append their
1373 // CM_ROM_BLOCK data into the 'System' key's configuration data.
1375 TRACE("DetectHardware() Done\n");
1384 /* Select APM 1.0+ function */
1387 /* Function 05h: CPU idle */
1391 Int386(0x15, &Regs
, &Regs
);
1393 /* Check if successfull (CF set on error) */
1394 if (INT386_SUCCESS(Regs
))
1398 * No futher processing here.
1399 * Optionally implement HLT instruction handling.
1404 /******************************************************************************/
1407 PcMachInit(const char *CmdLine
)
1410 MachVtbl
.ConsPutChar
= PcConsPutChar
;
1411 MachVtbl
.ConsKbHit
= PcConsKbHit
;
1412 MachVtbl
.ConsGetCh
= PcConsGetCh
;
1413 MachVtbl
.VideoClearScreen
= PcVideoClearScreen
;
1414 MachVtbl
.VideoSetDisplayMode
= PcVideoSetDisplayMode
;
1415 MachVtbl
.VideoGetDisplaySize
= PcVideoGetDisplaySize
;
1416 MachVtbl
.VideoGetBufferSize
= PcVideoGetBufferSize
;
1417 MachVtbl
.VideoGetFontsFromFirmware
= PcVideoGetFontsFromFirmware
;
1418 MachVtbl
.VideoSetTextCursorPosition
= PcVideoSetTextCursorPosition
;
1419 MachVtbl
.VideoHideShowTextCursor
= PcVideoHideShowTextCursor
;
1420 MachVtbl
.VideoPutChar
= PcVideoPutChar
;
1421 MachVtbl
.VideoCopyOffScreenBufferToVRAM
= PcVideoCopyOffScreenBufferToVRAM
;
1422 MachVtbl
.VideoIsPaletteFixed
= PcVideoIsPaletteFixed
;
1423 MachVtbl
.VideoSetPaletteColor
= PcVideoSetPaletteColor
;
1424 MachVtbl
.VideoGetPaletteColor
= PcVideoGetPaletteColor
;
1425 MachVtbl
.VideoSync
= PcVideoSync
;
1426 MachVtbl
.Beep
= PcBeep
;
1427 MachVtbl
.PrepareForReactOS
= PcPrepareForReactOS
;
1428 MachVtbl
.GetMemoryMap
= PcMemGetMemoryMap
;
1429 MachVtbl
.GetExtendedBIOSData
= PcGetExtendedBIOSData
;
1430 MachVtbl
.GetFloppyCount
= PcGetFloppyCount
;
1431 MachVtbl
.DiskReadLogicalSectors
= PcDiskReadLogicalSectors
;
1432 MachVtbl
.DiskGetDriveGeometry
= PcDiskGetDriveGeometry
;
1433 MachVtbl
.DiskGetCacheableBlockCount
= PcDiskGetCacheableBlockCount
;
1434 MachVtbl
.GetTime
= PcGetTime
;
1435 MachVtbl
.InitializeBootDevices
= PcInitializeBootDevices
;
1436 MachVtbl
.HwDetect
= PcHwDetect
;
1437 MachVtbl
.HwIdle
= PcHwIdle
;
1441 PcPrepareForReactOS(VOID
)
1443 /* On PC, prepare video and turn off the floppy motor */
1444 PcVideoPrepareForReactOS();
1445 DiskStopFloppyMotor();