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>
24 DBG_DEFAULT_CHANNEL(HWDETECT
);
27 /* Maximum number of COM and LPT ports */
28 #define MAX_COM_PORTS 4
29 #define MAX_LPT_PORTS 3
32 #define MOUSE_TYPE_NONE 0
33 /* Microsoft Mouse with 2 buttons */
34 #define MOUSE_TYPE_MICROSOFT 1
35 /* Logitech Mouse with 3 buttons */
36 #define MOUSE_TYPE_LOGITECH 2
37 /* Microsoft Wheel Mouse (aka Z Mouse) */
38 #define MOUSE_TYPE_WHEELZ 3
39 /* Mouse Systems Mouse */
40 #define MOUSE_TYPE_MOUSESYSTEMS 4
45 /* Controller registers. */
46 #define CONTROLLER_REGISTER_STATUS 0x64
47 #define CONTROLLER_REGISTER_CONTROL 0x64
48 #define CONTROLLER_REGISTER_DATA 0x60
50 /* Controller commands. */
51 #define CONTROLLER_COMMAND_READ_MODE 0x20
52 #define CONTROLLER_COMMAND_WRITE_MODE 0x60
53 #define CONTROLLER_COMMAND_GET_VERSION 0xA1
54 #define CONTROLLER_COMMAND_MOUSE_DISABLE 0xA7
55 #define CONTROLLER_COMMAND_MOUSE_ENABLE 0xA8
56 #define CONTROLLER_COMMAND_TEST_MOUSE 0xA9
57 #define CONTROLLER_COMMAND_SELF_TEST 0xAA
58 #define CONTROLLER_COMMAND_KEYBOARD_TEST 0xAB
59 #define CONTROLLER_COMMAND_KEYBOARD_DISABLE 0xAD
60 #define CONTROLLER_COMMAND_KEYBOARD_ENABLE 0xAE
61 #define CONTROLLER_COMMAND_WRITE_MOUSE_OUTPUT_BUFFER 0xD3
62 #define CONTROLLER_COMMAND_WRITE_MOUSE 0xD4
64 /* Controller status */
65 #define CONTROLLER_STATUS_OUTPUT_BUFFER_FULL 0x01
66 #define CONTROLLER_STATUS_INPUT_BUFFER_FULL 0x02
67 #define CONTROLLER_STATUS_SELF_TEST 0x04
68 #define CONTROLLER_STATUS_COMMAND 0x08
69 #define CONTROLLER_STATUS_UNLOCKED 0x10
70 #define CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL 0x20
71 #define CONTROLLER_STATUS_GENERAL_TIMEOUT 0x40
72 #define CONTROLLER_STATUS_PARITY_ERROR 0x80
73 #define AUX_STATUS_OUTPUT_BUFFER_FULL (CONTROLLER_STATUS_OUTPUT_BUFFER_FULL | \
74 CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL)
76 /* Timeout in ms for sending to keyboard controller. */
77 #define CONTROLLER_TIMEOUT 250
80 // NOTE: Similar to machxbox.c!XboxGetHarddiskConfigurationData(),
81 // but with extended geometry support.
83 PCM_PARTIAL_RESOURCE_LIST
84 PcGetHarddiskConfigurationData(UCHAR DriveNumber
, ULONG
* pSize
)
86 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
87 PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry
;
88 EXTENDED_GEOMETRY ExtGeometry
;
93 // Initialize returned size
97 /* Set 'Configuration Data' value */
98 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
99 sizeof(CM_DISK_GEOMETRY_DEVICE_DATA
);
100 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
101 if (PartialResourceList
== NULL
)
103 ERR("Failed to allocate resource descriptor\n");
107 memset(PartialResourceList
, 0, Size
);
108 PartialResourceList
->Version
= 1;
109 PartialResourceList
->Revision
= 1;
110 PartialResourceList
->Count
= 1;
111 PartialResourceList
->PartialDescriptors
[0].Type
=
112 CmResourceTypeDeviceSpecific
;
113 // PartialResourceList->PartialDescriptors[0].ShareDisposition =
114 // PartialResourceList->PartialDescriptors[0].Flags =
115 PartialResourceList
->PartialDescriptors
[0].u
.DeviceSpecificData
.DataSize
=
116 sizeof(CM_DISK_GEOMETRY_DEVICE_DATA
);
118 /* Get pointer to geometry data */
119 DiskGeometry
= (PVOID
)(((ULONG_PTR
)PartialResourceList
) + sizeof(CM_PARTIAL_RESOURCE_LIST
));
121 /* Get the disk geometry */
122 ExtGeometry
.Size
= sizeof(EXTENDED_GEOMETRY
);
123 if (DiskGetExtendedDriveParameters(DriveNumber
, &ExtGeometry
, ExtGeometry
.Size
))
125 DiskGeometry
->BytesPerSector
= ExtGeometry
.BytesPerSector
;
126 DiskGeometry
->NumberOfCylinders
= ExtGeometry
.Cylinders
;
127 DiskGeometry
->SectorsPerTrack
= ExtGeometry
.SectorsPerTrack
;
128 DiskGeometry
->NumberOfHeads
= ExtGeometry
.Heads
;
130 else if (MachDiskGetDriveGeometry(DriveNumber
, &Geometry
))
132 DiskGeometry
->BytesPerSector
= Geometry
.BytesPerSector
;
133 DiskGeometry
->NumberOfCylinders
= Geometry
.Cylinders
;
134 DiskGeometry
->SectorsPerTrack
= Geometry
.Sectors
;
135 DiskGeometry
->NumberOfHeads
= Geometry
.Heads
;
139 TRACE("Reading disk geometry failed\n");
140 FrLdrHeapFree(PartialResourceList
, TAG_HW_RESOURCE_LIST
);
143 TRACE("Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n",
145 DiskGeometry
->NumberOfCylinders
,
146 DiskGeometry
->NumberOfHeads
,
147 DiskGeometry
->SectorsPerTrack
,
148 DiskGeometry
->BytesPerSector
);
151 // Return configuration data
154 return PartialResourceList
;
159 DetectPnpBios(PCONFIGURATION_COMPONENT_DATA SystemKey
, ULONG
*BusNumber
)
161 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
162 PCM_PNP_BIOS_DEVICE_NODE DeviceNode
;
163 PCM_PNP_BIOS_INSTALLATION_CHECK InstData
;
164 PCONFIGURATION_COMPONENT_DATA BusKey
;
169 ULONG FoundNodeCount
;
172 ULONG PnpBufferSizeLimit
;
176 InstData
= (PCM_PNP_BIOS_INSTALLATION_CHECK
)PnpBiosSupported();
177 if (InstData
== NULL
|| strncmp((CHAR
*)InstData
->Signature
, "$PnP", 4))
179 TRACE("PnP-BIOS not supported\n");
183 TRACE("PnP-BIOS supported\n");
184 TRACE("Signature '%c%c%c%c'\n",
185 InstData
->Signature
[0], InstData
->Signature
[1],
186 InstData
->Signature
[2], InstData
->Signature
[3]);
188 x
= PnpBiosGetDeviceNodeCount(&NodeSize
, &NodeCount
);
191 TRACE("PnP-BIOS function 'Get Number of System Device Nodes' not supported\n");
195 NodeCount
&= 0xFF; // needed since some fscked up BIOSes return
196 // wrong info (e.g. Mac Virtual PC)
197 // e.g. look: http://my.execpc.com/~geezer/osd/pnp/pnp16.c
198 if (x
!= 0 || NodeSize
== 0 || NodeCount
== 0)
200 ERR("PnP-BIOS failed to enumerate device nodes\n");
203 TRACE("MaxNodeSize %u NodeCount %u\n", NodeSize
, NodeCount
);
204 TRACE("Estimated buffer size %u\n", NodeSize
* NodeCount
);
206 /* Set 'Configuration Data' value */
207 PnpBufferSizeLimit
= sizeof(CM_PNP_BIOS_INSTALLATION_CHECK
)
208 + (NodeSize
* NodeCount
);
209 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) + PnpBufferSizeLimit
;
210 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
211 if (PartialResourceList
== NULL
)
213 ERR("Failed to allocate resource descriptor\n");
216 memset(PartialResourceList
, 0, Size
);
218 /* Initialize resource descriptor */
219 PartialResourceList
->Version
= 1;
220 PartialResourceList
->Revision
= 1;
221 PartialResourceList
->Count
= 1;
222 PartialResourceList
->PartialDescriptors
[0].Type
=
223 CmResourceTypeDeviceSpecific
;
224 PartialResourceList
->PartialDescriptors
[0].ShareDisposition
=
225 CmResourceShareUndetermined
;
227 /* The buffer starts after PartialResourceList->PartialDescriptors[0] */
228 Ptr
= (char *)(PartialResourceList
+ 1);
230 /* Set installation check data */
231 memcpy (Ptr
, InstData
, sizeof(CM_PNP_BIOS_INSTALLATION_CHECK
));
232 Ptr
+= sizeof(CM_PNP_BIOS_INSTALLATION_CHECK
);
233 PnpBufferSize
= sizeof(CM_PNP_BIOS_INSTALLATION_CHECK
);
235 /* Copy device nodes */
237 for (i
= 0; i
< 0xFF; i
++)
239 NodeNumber
= (UCHAR
)i
;
241 x
= PnpBiosGetDeviceNode(&NodeNumber
, DiskReadBuffer
);
244 DeviceNode
= (PCM_PNP_BIOS_DEVICE_NODE
)DiskReadBuffer
;
246 TRACE("Node: %u Size %u (0x%x)\n",
251 if (PnpBufferSize
+ DeviceNode
->Size
> PnpBufferSizeLimit
)
253 ERR("Buffer too small! Ignoring remaining device nodes.\n");
257 memcpy(Ptr
, DeviceNode
, DeviceNode
->Size
);
259 Ptr
+= DeviceNode
->Size
;
260 PnpBufferSize
+= DeviceNode
->Size
;
263 if (FoundNodeCount
>= NodeCount
)
268 /* Set real data size */
269 PartialResourceList
->PartialDescriptors
[0].u
.DeviceSpecificData
.DataSize
=
271 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) + PnpBufferSize
;
273 TRACE("Real buffer size: %u\n", PnpBufferSize
);
274 TRACE("Resource size: %u\n", Size
);
276 /* Create component key */
277 FldrCreateComponentKey(SystemKey
,
279 MultiFunctionAdapter
,
293 InitializeSerialPort(PUCHAR Port
,
296 WRITE_PORT_UCHAR(Port
+ 3, 0x80); /* set DLAB on */
297 WRITE_PORT_UCHAR(Port
, 0x60); /* speed LO byte */
298 WRITE_PORT_UCHAR(Port
+ 1, 0); /* speed HI byte */
299 WRITE_PORT_UCHAR(Port
+ 3, LineControl
);
300 WRITE_PORT_UCHAR(Port
+ 1, 0); /* set comm and DLAB to 0 */
301 WRITE_PORT_UCHAR(Port
+ 4, 0x09); /* DR int enable */
302 READ_PORT_UCHAR(Port
+ 5); /* clear error bits */
307 DetectSerialMouse(PUCHAR Port
)
314 /* Shutdown mouse or something like that */
315 LineControl
= READ_PORT_UCHAR(Port
+ 4);
316 WRITE_PORT_UCHAR(Port
+ 4, (LineControl
& ~0x02) | 0x01);
317 StallExecutionProcessor(100000);
321 * Maybe there is no serial port although BIOS reported one (this
322 * is the case on Apple hardware), or the serial port is misbehaving,
323 * therefore we must give up after some time.
326 while (READ_PORT_UCHAR(Port
+ 5) & 0x01)
329 return MOUSE_TYPE_NONE
;
330 READ_PORT_UCHAR(Port
);
334 * Send modem control with 'Data Terminal Ready', 'Request To Send' and
335 * 'Output Line 2' message. This enables mouse to identify.
337 WRITE_PORT_UCHAR(Port
+ 4, 0x0b);
339 /* Wait 10 milliseconds for the mouse getting ready */
340 StallExecutionProcessor(10000);
342 /* Read first four bytes, which contains Microsoft Mouse signs */
344 for (i
= 0; i
< 4; i
++)
346 while ((READ_PORT_UCHAR(Port
+ 5) & 1) == 0)
348 StallExecutionProcessor(100);
351 return MOUSE_TYPE_NONE
;
353 Buffer
[i
] = READ_PORT_UCHAR(Port
);
356 TRACE("Mouse data: %x %x %x %x\n",
357 Buffer
[0], Buffer
[1], Buffer
[2], Buffer
[3]);
359 /* Check that four bytes for signs */
360 for (i
= 0; i
< 4; ++i
)
362 if (Buffer
[i
] == 'B')
364 /* Sign for Microsoft Ballpoint */
365 // DbgPrint("Microsoft Ballpoint device detected\n");
366 // DbgPrint("THIS DEVICE IS NOT SUPPORTED, YET\n");
367 return MOUSE_TYPE_NONE
;
369 else if (Buffer
[i
] == 'M')
371 /* Sign for Microsoft Mouse protocol followed by button specifier */
375 return MOUSE_TYPE_NONE
;
378 switch (Buffer
[i
+ 1])
381 TRACE("Microsoft Mouse with 3-buttons detected\n");
382 return MOUSE_TYPE_LOGITECH
;
385 TRACE("Microsoft Wheel Mouse detected\n");
386 return MOUSE_TYPE_WHEELZ
;
390 TRACE("Microsoft Mouse with 2-buttons detected\n");
391 return MOUSE_TYPE_MICROSOFT
;
396 return MOUSE_TYPE_NONE
;
400 GetSerialMousePnpId(PUCHAR Port
, char *Buffer
)
407 WRITE_PORT_UCHAR(Port
+ 4, 0x09);
409 /* Wait 10 milliseconds for the mouse getting ready */
410 StallExecutionProcessor(10000);
412 WRITE_PORT_UCHAR(Port
+ 4, 0x0b);
414 StallExecutionProcessor(10000);
419 while (((READ_PORT_UCHAR(Port
+ 5) & 1) == 0) && (TimeOut
> 0))
421 StallExecutionProcessor(1000);
429 c
= READ_PORT_UCHAR(Port
);
430 if (c
== 0x08 || c
== 0x28)
440 while (((READ_PORT_UCHAR(Port
+ 5) & 1) == 0) && (TimeOut
> 0))
442 StallExecutionProcessor(1000);
447 c
= READ_PORT_UCHAR(Port
);
460 DetectSerialPointerPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey
,
463 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
465 CHAR Identifier
[256];
466 PCONFIGURATION_COMPONENT_DATA PeripheralKey
;
473 TRACE("DetectSerialPointerPeripheral()\n");
477 InitializeSerialPort(Base
, 2);
478 MouseType
= DetectSerialMouse(Base
);
480 if (MouseType
!= MOUSE_TYPE_NONE
)
482 Length
= GetSerialMousePnpId(Base
, Buffer
);
483 TRACE( "PnP ID length: %u\n", Length
);
487 /* Convert PnP sting to ASCII */
488 if (Buffer
[0] == 0x08)
490 for (i
= 0; i
< Length
; i
++)
495 TRACE("PnP ID string: %s\n", Buffer
);
497 /* Copy PnpId string */
498 for (i
= 0; i
< 7; i
++)
500 Identifier
[i
] = Buffer
[3 + i
];
502 memcpy(&Identifier
[7],
506 /* Skip device serial number */
508 if (Buffer
[i
] == '\\')
510 for (j
= ++i
; i
< Length
; ++i
)
512 if (Buffer
[i
] == '\\')
520 if (Buffer
[i
] == '\\')
522 for (j
= ++i
; i
< Length
; ++i
)
524 if (Buffer
[i
] == '\\')
532 /* Skip compatible PnP Id */
533 if (Buffer
[i
] == '\\')
535 for (j
= ++i
; i
< Length
; ++i
)
537 if (Buffer
[i
] == '\\')
540 if (Buffer
[j
] == '*')
546 /* Get product description */
547 if (Buffer
[i
] == '\\')
549 for (j
= ++i
; i
< Length
; ++i
)
551 if (Buffer
[i
] == ';')
558 for (k
= 0; k
< i
- j
; k
++)
560 Identifier
[k
+ 10] = Buffer
[k
+ j
];
562 Identifier
[10 + (i
- j
)] = 0;
566 TRACE("Identifier string: %s\n", Identifier
);
569 if (Length
== 0 || strlen(Identifier
) < 11)
573 case MOUSE_TYPE_LOGITECH
:
574 strcpy(Identifier
, "LOGITECH SERIAL MOUSE");
577 case MOUSE_TYPE_WHEELZ
:
578 strcpy(Identifier
, "MICROSOFT SERIAL MOUSE WITH WHEEL");
581 case MOUSE_TYPE_MICROSOFT
:
583 strcpy(Identifier
, "MICROSOFT SERIAL MOUSE");
588 /* Set 'Configuration Data' value */
589 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) -
590 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
591 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
592 if (PartialResourceList
== NULL
)
594 ERR("Failed to allocate resource descriptor\n");
597 memset(PartialResourceList
, 0, Size
);
598 PartialResourceList
->Version
= 1;
599 PartialResourceList
->Revision
= 1;
600 PartialResourceList
->Count
= 0;
602 /* Create 'PointerPeripheral' key */
603 FldrCreateComponentKey(ControllerKey
,
614 TRACE("Created key: PointerPeripheral\\0\n");
620 DetectSerialPorts(PCONFIGURATION_COMPONENT_DATA BusKey
)
622 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
623 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
624 PCM_SERIAL_DEVICE_DATA SerialDeviceData
;
625 ULONG Irq
[MAX_COM_PORTS
] = {4, 3, 4, 3};
629 ULONG ControllerNumber
= 0;
630 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
634 TRACE("DetectSerialPorts()\n");
637 * The BIOS data area 0x400 holds the address of the first valid COM port.
638 * Each COM port address is stored in a 2-byte field.
639 * Infos at: http://www.bioscentral.com/misc/bda.htm
641 BasePtr
= (PUSHORT
)0x400;
643 for (i
= 0; i
< MAX_COM_PORTS
; i
++, BasePtr
++)
645 Base
= (ULONG
) * BasePtr
;
646 if ((Base
== 0) || !CpDoesPortExist(UlongToPtr(Base
)))
649 TRACE("Found COM%u port at 0x%x\n", i
+ 1, Base
);
651 /* Set 'Identifier' value */
652 sprintf(Buffer
, "COM%ld", i
+ 1);
654 /* Build full device descriptor */
655 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
656 2 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
) +
657 sizeof(CM_SERIAL_DEVICE_DATA
);
658 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
659 if (PartialResourceList
== NULL
)
661 ERR("Failed to allocate resource descriptor\n");
664 memset(PartialResourceList
, 0, Size
);
666 /* Initialize resource descriptor */
667 PartialResourceList
->Version
= 1;
668 PartialResourceList
->Revision
= 1;
669 PartialResourceList
->Count
= 3;
672 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[0];
673 PartialDescriptor
->Type
= CmResourceTypePort
;
674 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
675 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
676 PartialDescriptor
->u
.Port
.Start
.LowPart
= Base
;
677 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0x0;
678 PartialDescriptor
->u
.Port
.Length
= 7;
681 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[1];
682 PartialDescriptor
->Type
= CmResourceTypeInterrupt
;
683 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
684 PartialDescriptor
->Flags
= CM_RESOURCE_INTERRUPT_LATCHED
;
685 PartialDescriptor
->u
.Interrupt
.Level
= Irq
[i
];
686 PartialDescriptor
->u
.Interrupt
.Vector
= Irq
[i
];
687 PartialDescriptor
->u
.Interrupt
.Affinity
= 0xFFFFFFFF;
689 /* Set serial data (device specific) */
690 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[2];
691 PartialDescriptor
->Type
= CmResourceTypeDeviceSpecific
;
692 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
693 PartialDescriptor
->Flags
= 0;
694 PartialDescriptor
->u
.DeviceSpecificData
.DataSize
= sizeof(CM_SERIAL_DEVICE_DATA
);
697 (PCM_SERIAL_DEVICE_DATA
)&PartialResourceList
->PartialDescriptors
[3];
698 SerialDeviceData
->BaudClock
= 1843200; /* UART Clock frequency (Hertz) */
700 /* Create controller key */
701 FldrCreateComponentKey(BusKey
,
704 Output
| Input
| ConsoleIn
| ConsoleOut
,
712 if (!Rs232PortInUse(UlongToPtr(Base
)))
714 /* Detect serial mouse */
715 DetectSerialPointerPeripheral(ControllerKey
, UlongToPtr(Base
));
723 DetectParallelPorts(PCONFIGURATION_COMPONENT_DATA BusKey
)
725 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
726 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
727 ULONG Irq
[MAX_LPT_PORTS
] = {7, 5, (ULONG
) - 1};
729 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
732 ULONG ControllerNumber
= 0;
736 TRACE("DetectParallelPorts() called\n");
739 * The BIOS data area 0x408 holds the address of the first valid LPT port.
740 * Each LPT port address is stored in a 2-byte field.
741 * Infos at: http://www.bioscentral.com/misc/bda.htm
743 BasePtr
= (PUSHORT
)0x408;
745 for (i
= 0; i
< MAX_LPT_PORTS
; i
++, BasePtr
++)
747 Base
= (ULONG
) * BasePtr
;
751 TRACE("Parallel port %u: %x\n", ControllerNumber
, Base
);
753 /* Set 'Identifier' value */
754 sprintf(Buffer
, "PARALLEL%ld", i
+ 1);
756 /* Build full device descriptor */
757 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
);
758 if (Irq
[i
] != (ULONG
) - 1)
759 Size
+= sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
761 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
762 if (PartialResourceList
== NULL
)
764 ERR("Failed to allocate resource descriptor\n");
767 memset(PartialResourceList
, 0, Size
);
769 /* Initialize resource descriptor */
770 PartialResourceList
->Version
= 1;
771 PartialResourceList
->Revision
= 1;
772 PartialResourceList
->Count
= (Irq
[i
] != (ULONG
) - 1) ? 2 : 1;
775 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[0];
776 PartialDescriptor
->Type
= CmResourceTypePort
;
777 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
778 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
779 PartialDescriptor
->u
.Port
.Start
.LowPart
= Base
;
780 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0x0;
781 PartialDescriptor
->u
.Port
.Length
= 3;
784 if (Irq
[i
] != (ULONG
) - 1)
786 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[1];
787 PartialDescriptor
->Type
= CmResourceTypeInterrupt
;
788 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
789 PartialDescriptor
->Flags
= CM_RESOURCE_INTERRUPT_LATCHED
;
790 PartialDescriptor
->u
.Interrupt
.Level
= Irq
[i
];
791 PartialDescriptor
->u
.Interrupt
.Vector
= Irq
[i
];
792 PartialDescriptor
->u
.Interrupt
.Affinity
= 0xFFFFFFFF;
795 /* Create controller key */
796 FldrCreateComponentKey(BusKey
,
810 TRACE("DetectParallelPorts() done\n");
815 DetectKeyboardDevice(VOID
)
820 BOOLEAN Result
= TRUE
;
822 /* Identify device */
823 WRITE_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
, 0xF2);
826 for (Loops
= 0; Loops
< 100; Loops
++)
828 StallExecutionProcessor(10000);
829 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
830 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) != 0)
834 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) == 0)
836 /* PC/XT keyboard or no keyboard */
840 Scancode
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
841 if (Scancode
!= 0xFA)
843 /* No ACK received */
847 StallExecutionProcessor(10000);
849 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
850 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) == 0)
852 /* Found AT keyboard */
856 Scancode
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
857 if (Scancode
!= 0xAB)
859 /* No 0xAB received */
863 StallExecutionProcessor(10000);
865 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
866 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) == 0)
868 /* No byte in buffer */
872 Scancode
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
873 if (Scancode
!= 0x41)
875 /* No 0x41 received */
879 /* Found MF-II keyboard */
884 DetectKeyboardPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey
)
886 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
887 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
888 PCM_KEYBOARD_DEVICE_DATA KeyboardData
;
889 PCONFIGURATION_COMPONENT_DATA PeripheralKey
;
892 /* HACK: don't call DetectKeyboardDevice() as it fails in Qemu 0.8.2
893 if (DetectKeyboardDevice()) */
895 /* Set 'Configuration Data' value */
896 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
897 sizeof(CM_KEYBOARD_DEVICE_DATA
);
898 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
899 if (PartialResourceList
== NULL
)
901 ERR("Failed to allocate resource descriptor\n");
905 /* Initialize resource descriptor */
906 memset(PartialResourceList
, 0, Size
);
907 PartialResourceList
->Version
= 1;
908 PartialResourceList
->Revision
= 1;
909 PartialResourceList
->Count
= 1;
911 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[0];
912 PartialDescriptor
->Type
= CmResourceTypeDeviceSpecific
;
913 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
914 PartialDescriptor
->u
.DeviceSpecificData
.DataSize
= sizeof(CM_KEYBOARD_DEVICE_DATA
);
916 KeyboardData
= (PCM_KEYBOARD_DEVICE_DATA
)(PartialDescriptor
+ 1);
917 KeyboardData
->Version
= 1;
918 KeyboardData
->Revision
= 1;
919 KeyboardData
->Type
= 4;
920 KeyboardData
->Subtype
= 0;
921 KeyboardData
->KeyboardFlags
= 0x20;
923 /* Create controller key */
924 FldrCreateComponentKey(ControllerKey
,
934 TRACE("Created key: KeyboardPeripheral\\0\n");
940 DetectKeyboardController(PCONFIGURATION_COMPONENT_DATA BusKey
)
942 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
943 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
944 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
947 /* Set 'Configuration Data' value */
948 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
949 2 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
950 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
951 if (PartialResourceList
== NULL
)
953 ERR("Failed to allocate resource descriptor\n");
957 /* Initialize resource descriptor */
958 memset(PartialResourceList
, 0, Size
);
959 PartialResourceList
->Version
= 1;
960 PartialResourceList
->Revision
= 1;
961 PartialResourceList
->Count
= 3;
964 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[0];
965 PartialDescriptor
->Type
= CmResourceTypeInterrupt
;
966 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
967 PartialDescriptor
->Flags
= CM_RESOURCE_INTERRUPT_LATCHED
;
968 PartialDescriptor
->u
.Interrupt
.Level
= 1;
969 PartialDescriptor
->u
.Interrupt
.Vector
= 1;
970 PartialDescriptor
->u
.Interrupt
.Affinity
= 0xFFFFFFFF;
972 /* Set IO Port 0x60 */
973 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[1];
974 PartialDescriptor
->Type
= CmResourceTypePort
;
975 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
976 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
977 PartialDescriptor
->u
.Port
.Start
.LowPart
= 0x60;
978 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0x0;
979 PartialDescriptor
->u
.Port
.Length
= 1;
981 /* Set IO Port 0x64 */
982 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[2];
983 PartialDescriptor
->Type
= CmResourceTypePort
;
984 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
985 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
986 PartialDescriptor
->u
.Port
.Start
.LowPart
= 0x64;
987 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0x0;
988 PartialDescriptor
->u
.Port
.Length
= 1;
990 /* Create controller key */
991 FldrCreateComponentKey(BusKey
,
1001 TRACE("Created key: KeyboardController\\0\n");
1003 DetectKeyboardPeripheral(ControllerKey
);
1008 PS2ControllerWait(VOID
)
1013 for (Timeout
= 0; Timeout
< CONTROLLER_TIMEOUT
; Timeout
++)
1015 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1016 if ((Status
& CONTROLLER_STATUS_INPUT_BUFFER_FULL
) == 0)
1019 /* Sleep for one millisecond */
1020 StallExecutionProcessor(1000);
1026 DetectPS2AuxPort(VOID
)
1029 /* Current detection is too unreliable. Just do as if
1030 * the PS/2 aux port is always present
1037 /* Put the value 0x5A in the output buffer using the
1038 * "WriteAuxiliary Device Output Buffer" command (0xD3).
1039 * Poll the Status Register for a while to see if the value really turns up
1040 * in the Data Register. If the KEYBOARD_STATUS_MOUSE_OBF bit is also set
1041 * to 1 in the Status Register, we assume this controller has an
1042 * Auxiliary Port (a.k.a. Mouse Port).
1044 PS2ControllerWait();
1045 WRITE_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_CONTROL
,
1046 CONTROLLER_COMMAND_WRITE_MOUSE_OUTPUT_BUFFER
);
1047 PS2ControllerWait();
1049 /* 0x5A is a random dummy value */
1050 WRITE_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
,
1053 for (Loops
= 0; Loops
< 10; Loops
++)
1055 StallExecutionProcessor(10000);
1056 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1057 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) != 0)
1061 READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
1063 return (Status
& CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL
);
1069 DetectPS2AuxDevice(VOID
)
1074 BOOLEAN Result
= TRUE
;
1076 PS2ControllerWait();
1077 WRITE_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_CONTROL
,
1078 CONTROLLER_COMMAND_WRITE_MOUSE
);
1079 PS2ControllerWait();
1081 /* Identify device */
1082 WRITE_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
, 0xF2);
1084 /* Wait for reply */
1085 for (Loops
= 0; Loops
< 100; Loops
++)
1087 StallExecutionProcessor(10000);
1088 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1089 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) != 0)
1093 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1094 if ((Status
& CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL
) == 0)
1097 Scancode
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
1098 if (Scancode
!= 0xFA)
1101 StallExecutionProcessor(10000);
1103 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1104 if ((Status
& CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL
) == 0)
1107 Scancode
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
1108 if (Scancode
!= 0x00)
1114 // FIXME: Missing: DetectPS2Peripheral!! (for corresponding 'PointerPeripheral')
1118 DetectPS2Mouse(PCONFIGURATION_COMPONENT_DATA BusKey
)
1120 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
1121 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
1122 PCONFIGURATION_COMPONENT_DATA PeripheralKey
;
1125 if (DetectPS2AuxPort())
1127 TRACE("Detected PS2 port\n");
1129 PartialResourceList
= FrLdrHeapAlloc(sizeof(CM_PARTIAL_RESOURCE_LIST
), TAG_HW_RESOURCE_LIST
);
1130 if (PartialResourceList
== NULL
)
1132 ERR("Failed to allocate resource descriptor\n");
1135 memset(PartialResourceList
, 0, sizeof(CM_PARTIAL_RESOURCE_LIST
));
1137 /* Initialize resource descriptor */
1138 PartialResourceList
->Version
= 1;
1139 PartialResourceList
->Revision
= 1;
1140 PartialResourceList
->Count
= 1;
1143 PartialResourceList
->PartialDescriptors
[0].Type
= CmResourceTypeInterrupt
;
1144 PartialResourceList
->PartialDescriptors
[0].ShareDisposition
= CmResourceShareUndetermined
;
1145 PartialResourceList
->PartialDescriptors
[0].Flags
= CM_RESOURCE_INTERRUPT_LATCHED
;
1146 PartialResourceList
->PartialDescriptors
[0].u
.Interrupt
.Level
= 12;
1147 PartialResourceList
->PartialDescriptors
[0].u
.Interrupt
.Vector
= 12;
1148 PartialResourceList
->PartialDescriptors
[0].u
.Interrupt
.Affinity
= 0xFFFFFFFF;
1150 /* Create controller key */
1151 FldrCreateComponentKey(BusKey
,
1158 PartialResourceList
,
1159 sizeof(CM_PARTIAL_RESOURCE_LIST
),
1161 TRACE("Created key: PointerController\\0\n");
1163 if (DetectPS2AuxDevice())
1165 TRACE("Detected PS2 mouse\n");
1167 /* Initialize resource descriptor */
1168 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) -
1169 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1170 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
1171 if (PartialResourceList
== NULL
)
1173 ERR("Failed to allocate resource descriptor\n");
1176 memset(PartialResourceList
, 0, Size
);
1177 PartialResourceList
->Version
= 1;
1178 PartialResourceList
->Revision
= 1;
1179 PartialResourceList
->Count
= 0;
1181 /* Create peripheral key */
1182 FldrCreateComponentKey(ControllerKey
,
1188 "MICROSOFT PS2 MOUSE",
1189 PartialResourceList
,
1192 TRACE("Created key: PointerPeripheral\\0\n");
1198 DetectDisplayController(PCONFIGURATION_COMPONENT_DATA BusKey
)
1201 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
1204 /* FIXME: Set 'ComponentInformation' value */
1206 VesaVersion
= BiosIsVesaSupported();
1207 if (VesaVersion
!= 0)
1209 TRACE("VESA version %c.%c\n",
1210 (VesaVersion
>> 8) + '0',
1211 (VesaVersion
& 0xFF) + '0');
1215 TRACE("VESA not supported\n");
1218 if (VesaVersion
>= 0x0200)
1220 strcpy(Buffer
, "VBE Display");
1224 strcpy(Buffer
, "VGA Display");
1227 FldrCreateComponentKey(BusKey
,
1237 TRACE("Created key: DisplayController\\0\n");
1239 /* FIXME: Add display peripheral (monitor) data */
1240 if (VesaVersion
!= 0)
1242 if (BiosIsVesaDdcSupported())
1244 TRACE("VESA/DDC supported!\n");
1245 if (BiosVesaReadEdid())
1247 TRACE("EDID data read successfully!\n");
1256 DetectIsaBios(PCONFIGURATION_COMPONENT_DATA SystemKey
, ULONG
*BusNumber
)
1258 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
1259 PCONFIGURATION_COMPONENT_DATA BusKey
;
1262 /* Set 'Configuration Data' value */
1263 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) -
1264 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1265 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
1266 if (PartialResourceList
== NULL
)
1268 ERR("Failed to allocate resource descriptor\n");
1272 /* Initialize resource descriptor */
1273 memset(PartialResourceList
, 0, Size
);
1274 PartialResourceList
->Version
= 1;
1275 PartialResourceList
->Revision
= 1;
1276 PartialResourceList
->Count
= 0;
1278 /* Create new bus key */
1279 FldrCreateComponentKey(SystemKey
,
1281 MultiFunctionAdapter
,
1286 PartialResourceList
,
1290 /* Increment bus number */
1293 /* Detect ISA/BIOS devices */
1294 DetectBiosDisks(SystemKey
, BusKey
);
1295 DetectSerialPorts(BusKey
);
1296 DetectParallelPorts(BusKey
);
1297 DetectKeyboardController(BusKey
);
1298 DetectPS2Mouse(BusKey
);
1299 DetectDisplayController(BusKey
);
1301 /* FIXME: Detect more ISA devices */
1306 PcGetFloppyCount(VOID
)
1310 WRITE_PORT_UCHAR((PUCHAR
)0x70, 0x10);
1311 Data
= READ_PORT_UCHAR((PUCHAR
)0x71);
1313 return ((Data
& 0xF0) ? 1 : 0) + ((Data
& 0x0F) ? 1 : 0);
1316 PCONFIGURATION_COMPONENT_DATA
1319 PCONFIGURATION_COMPONENT_DATA SystemKey
;
1320 ULONG BusNumber
= 0;
1322 TRACE("DetectHardware()\n");
1324 /* Create the 'System' key */
1325 FldrCreateSystemKey(&SystemKey
);
1326 // TODO: Discover and set the machine type as the Component->Identifier
1328 GetHarddiskConfigurationData
= PcGetHarddiskConfigurationData
;
1331 DetectPciBios(SystemKey
, &BusNumber
);
1332 DetectApmBios(SystemKey
, &BusNumber
);
1333 DetectPnpBios(SystemKey
, &BusNumber
);
1334 DetectIsaBios(SystemKey
, &BusNumber
); // TODO: Detect first EISA or MCA, before ISA
1335 DetectAcpiBios(SystemKey
, &BusNumber
);
1337 // TODO: Collect the ROM blocks from 0xC0000 to 0xF0000 and append their
1338 // CM_ROM_BLOCK data into the 'System' key's configuration data.
1340 TRACE("DetectHardware() Done\n");
1349 /* Select APM 1.0+ function */
1352 /* Function 05h: CPU idle */
1356 Int386(0x15, &Regs
, &Regs
);
1358 /* Check if successfull (CF set on error) */
1359 if (INT386_SUCCESS(Regs
))
1363 * No futher processing here.
1364 * Optionally implement HLT instruction handling.
1369 /******************************************************************************/
1372 PcMachInit(const char *CmdLine
)
1375 MachVtbl
.ConsPutChar
= PcConsPutChar
;
1376 MachVtbl
.ConsKbHit
= PcConsKbHit
;
1377 MachVtbl
.ConsGetCh
= PcConsGetCh
;
1378 MachVtbl
.VideoClearScreen
= PcVideoClearScreen
;
1379 MachVtbl
.VideoSetDisplayMode
= PcVideoSetDisplayMode
;
1380 MachVtbl
.VideoGetDisplaySize
= PcVideoGetDisplaySize
;
1381 MachVtbl
.VideoGetBufferSize
= PcVideoGetBufferSize
;
1382 MachVtbl
.VideoSetTextCursorPosition
= PcVideoSetTextCursorPosition
;
1383 MachVtbl
.VideoHideShowTextCursor
= PcVideoHideShowTextCursor
;
1384 MachVtbl
.VideoPutChar
= PcVideoPutChar
;
1385 MachVtbl
.VideoCopyOffScreenBufferToVRAM
= PcVideoCopyOffScreenBufferToVRAM
;
1386 MachVtbl
.VideoIsPaletteFixed
= PcVideoIsPaletteFixed
;
1387 MachVtbl
.VideoSetPaletteColor
= PcVideoSetPaletteColor
;
1388 MachVtbl
.VideoGetPaletteColor
= PcVideoGetPaletteColor
;
1389 MachVtbl
.VideoSync
= PcVideoSync
;
1390 MachVtbl
.Beep
= PcBeep
;
1391 MachVtbl
.PrepareForReactOS
= PcPrepareForReactOS
;
1392 MachVtbl
.GetMemoryMap
= PcMemGetMemoryMap
;
1393 MachVtbl
.GetFloppyCount
= PcGetFloppyCount
;
1394 MachVtbl
.DiskGetBootPath
= PcDiskGetBootPath
;
1395 MachVtbl
.DiskReadLogicalSectors
= PcDiskReadLogicalSectors
;
1396 MachVtbl
.DiskGetDriveGeometry
= PcDiskGetDriveGeometry
;
1397 MachVtbl
.DiskGetCacheableBlockCount
= PcDiskGetCacheableBlockCount
;
1398 MachVtbl
.GetTime
= PcGetTime
;
1399 MachVtbl
.InitializeBootDevices
= PcInitializeBootDevices
;
1400 MachVtbl
.HwDetect
= PcHwDetect
;
1401 MachVtbl
.HwIdle
= PcHwIdle
;
1403 // DiskGetPartitionEntry = DiskGetMbrPartitionEntry; // Default
1407 PcPrepareForReactOS(VOID
)
1409 /* On PC, prepare video and turn off the floppy motor */
1410 PcVideoPrepareForReactOS();
1411 DiskStopFloppyMotor();