https://git.reactos.org/?p=reactos.git;a=commitdiff;h=ffbc81fdf2f8c203d28cb…
commit ffbc81fdf2f8c203d28cb554605a6a099a916265
Author: Dmitry Borisov <di.sean(a)protonmail.com>
AuthorDate: Tue Jul 25 22:12:08 2023 +0600
Commit: Stanislav Motylkov <x86corez(a)gmail.com>
CommitDate: Sat Aug 5 16:40:13 2023 +0300
[FREELDR] Implement bus mouse detection
This allows to automatically install the inport device driver
(it's now possible since 7d5e1591313), which can be used on 86Box.
References:
-
https://raw.githubusercontent.com/86Box/86Box/master/src/device/mouse_bus.c
-
https://bochs.sourceforge.io/cgi-bin/lxr/source/iodev/busmouse.cc
---
boot/freeldr/freeldr/arch/i386/irqsup.S | 33 +++++
boot/freeldr/freeldr/arch/i386/pc/machpc.c | 214 +++++++++++++++++++++++++++++
boot/freeldr/freeldr/pcat.cmake | 1 +
3 files changed, 248 insertions(+)
diff --git a/boot/freeldr/freeldr/arch/i386/irqsup.S
b/boot/freeldr/freeldr/arch/i386/irqsup.S
new file mode 100644
index 00000000000..7c35ef383ec
--- /dev/null
+++ b/boot/freeldr/freeldr/arch/i386/irqsup.S
@@ -0,0 +1,33 @@
+/*
+ * PROJECT: FreeLoader
+ * LICENSE: GPL-2.0-or-later (
https://spdx.org/licenses/GPL-2.0-or-later)
+ * PURPOSE: Interrupt handling
+ * COPYRIGHT: Copyright 2023 Dmitry Borisov <di.sean(a)protonmail.com>
+ */
+
+#include <asm.inc>
+
+#define PIC1_CONTROL_PORT HEX(20)
+#define PIC_EOI HEX(20)
+
+.code32
+
+PUBLIC _HwIrqHandler
+_HwIrqHandler:
+ push ax
+
+ /* Increment the interrupt count */
+ inc dword ptr ds:[_HwIrqCount]
+
+ /* Dismiss the interrupt */
+ mov al, PIC_EOI
+ out PIC1_CONTROL_PORT, al
+
+ pop ax
+ iret
+
+PUBLIC _HwIrqCount
+_HwIrqCount:
+ .long 0
+
+END
diff --git a/boot/freeldr/freeldr/arch/i386/pc/machpc.c
b/boot/freeldr/freeldr/arch/i386/pc/machpc.c
index f20fa2b9a52..4bef802f667 100644
--- a/boot/freeldr/freeldr/arch/i386/pc/machpc.c
+++ b/boot/freeldr/freeldr/arch/i386/pc/machpc.c
@@ -38,6 +38,20 @@ DBG_DEFAULT_CHANNEL(HWDETECT);
/* Mouse Systems Mouse */
#define MOUSE_TYPE_MOUSESYSTEMS 4
+#define INPORT_REGISTER_CONTROL 0x00
+#define INPORT_REGISTER_DATA 0x01
+#define INPORT_REGISTER_SIGNATURE 0x02
+
+#define INPORT_REG_MODE 0x07
+#define INPORT_RESET 0x80
+#define INPORT_MODE_BASE 0x10
+#define INPORT_TEST_IRQ 0x16
+#define INPORT_SIGNATURE 0xDE
+
+#define PIC1_CONTROL_PORT 0x20
+#define PIC1_DATA_PORT 0x21
+#define PIC2_CONTROL_PORT 0xA0
+#define PIC2_DATA_PORT 0xA1
/* PS2 stuff */
@@ -1291,6 +1305,203 @@ DetectPS2Mouse(PCONFIGURATION_COMPONENT_DATA BusKey)
}
}
+#if defined(_M_IX86)
+static VOID
+CreateBusMousePeripheralKey(
+ _Inout_ PCONFIGURATION_COMPONENT_DATA BusKey,
+ _In_ ULONG IoBase,
+ _In_ ULONG Irq)
+{
+ PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
+ PCONFIGURATION_COMPONENT_DATA ControllerKey;
+ PCONFIGURATION_COMPONENT_DATA PeripheralKey;
+ ULONG Size;
+
+ /* Set 'Configuration Data' value */
+ Size = FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST, PartialDescriptors[2]);
+ PartialResourceList = FrLdrHeapAlloc(Size, TAG_HW_RESOURCE_LIST);
+ if (PartialResourceList == NULL)
+ {
+ ERR("Failed to allocate resource descriptor\n");
+ return;
+ }
+
+ /* Initialize resource descriptor */
+ RtlZeroMemory(PartialResourceList, Size);
+ PartialResourceList->Version = 1;
+ PartialResourceList->Revision = 1;
+ PartialResourceList->Count = 2;
+
+ /* Set IO Port */
+ PartialDescriptor = &PartialResourceList->PartialDescriptors[0];
+ PartialDescriptor->Type = CmResourceTypePort;
+ PartialDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ PartialDescriptor->Flags = CM_RESOURCE_PORT_IO;
+ PartialDescriptor->u.Port.Start.LowPart = IoBase;
+ PartialDescriptor->u.Port.Start.HighPart = 0;
+ PartialDescriptor->u.Port.Length = 4;
+
+ /* Set Interrupt */
+ PartialDescriptor = &PartialResourceList->PartialDescriptors[1];
+ PartialDescriptor->Type = CmResourceTypeInterrupt;
+ PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
+ PartialDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
+ PartialDescriptor->u.Interrupt.Level = Irq;
+ PartialDescriptor->u.Interrupt.Vector = Irq;
+ PartialDescriptor->u.Interrupt.Affinity = (KAFFINITY)-1;
+
+ /* Create controller key */
+ FldrCreateComponentKey(BusKey,
+ ControllerClass,
+ PointerController,
+ Input,
+ 0,
+ 0xFFFFFFFF,
+ NULL,
+ PartialResourceList,
+ Size,
+ &ControllerKey);
+
+ /* Set 'Configuration Data' value */
+ Size = FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST, PartialDescriptors);
+ PartialResourceList = FrLdrHeapAlloc(Size, TAG_HW_RESOURCE_LIST);
+ if (PartialResourceList == NULL)
+ {
+ ERR("Failed to allocate resource descriptor\n");
+ return;
+ }
+
+ /* Initialize resource descriptor */
+ RtlZeroMemory(PartialResourceList, Size);
+ PartialResourceList->Version = 1;
+ PartialResourceList->Revision = 1;
+ PartialResourceList->Count = 0;
+
+ /* Create peripheral key */
+ FldrCreateComponentKey(ControllerKey,
+ ControllerClass,
+ PointerPeripheral,
+ Input,
+ 0,
+ 0xFFFFFFFF,
+ "MICROSOFT INPORT MOUSE",
+ PartialResourceList,
+ Size,
+ &PeripheralKey);
+}
+
+extern KIDTENTRY DECLSPEC_ALIGN(4) i386Idt[32];
+VOID __cdecl HwIrqHandler(VOID);
+extern volatile ULONG HwIrqCount;
+
+static ULONG
+DetectBusMouseTestIrq(
+ _In_ ULONG IoBase,
+ _In_ ULONG Irq)
+{
+ USHORT OldOffset, OldExtendedOffset;
+ ULONG Vector, i;
+
+ HwIrqCount = 0;
+
+ /* Reset the device */
+ WRITE_PORT_UCHAR((PUCHAR)IoBase + INPORT_REGISTER_CONTROL, INPORT_RESET);
+ WRITE_PORT_UCHAR((PUCHAR)IoBase + INPORT_REGISTER_CONTROL, INPORT_REG_MODE);
+
+ Vector = Irq + 8;
+
+ /* Save the old interrupt vector and replace it by ours */
+ OldOffset = i386Idt[Vector].Offset;
+ OldExtendedOffset = i386Idt[Vector].ExtendedOffset;
+
+ i386Idt[Vector].Offset = (ULONG)HwIrqHandler & 0xFFFF;
+ i386Idt[Vector].ExtendedOffset = (ULONG)HwIrqHandler >> 16;
+
+ /* Enable the requested IRQ on the master PIC */
+ WRITE_PORT_UCHAR((PUCHAR)PIC1_DATA_PORT, ~(1 << Irq));
+
+ _enable();
+
+ /* Configure the device to generate interrupts */
+ for (i = 0; i < 15; i++)
+ {
+ WRITE_PORT_UCHAR((PUCHAR)IoBase + INPORT_REGISTER_DATA, INPORT_MODE_BASE);
+ WRITE_PORT_UCHAR((PUCHAR)IoBase + INPORT_REGISTER_DATA, INPORT_TEST_IRQ);
+ }
+
+ /* Disable the device */
+ WRITE_PORT_UCHAR((PUCHAR)IoBase + INPORT_REGISTER_DATA, 0);
+
+ _disable();
+
+ i386Idt[Vector].Offset = OldOffset;
+ i386Idt[Vector].ExtendedOffset = OldExtendedOffset;
+
+ return (HwIrqCount != 0) ? Irq : 0;
+}
+
+static ULONG
+DetectBusMouseIrq(
+ _In_ ULONG IoBase)
+{
+ UCHAR Mask1, Mask2;
+ ULONG Irq, Result;
+
+ /* Save the current interrupt mask */
+ Mask1 = READ_PORT_UCHAR(PIC1_DATA_PORT);
+ Mask2 = READ_PORT_UCHAR(PIC2_DATA_PORT);
+
+ /* Mask the interrupts on the slave PIC */
+ WRITE_PORT_UCHAR(PIC2_DATA_PORT, 0xFF);
+
+ /* Process IRQ detection: IRQ 5, 4, 3 */
+ for (Irq = 5; Irq >= 3; Irq--)
+ {
+ Result = DetectBusMouseTestIrq(IoBase, Irq);
+ if (Result != 0)
+ break;
+ }
+
+ /* Restore the mask */
+ WRITE_PORT_UCHAR(PIC1_DATA_PORT, Mask1);
+ WRITE_PORT_UCHAR(PIC2_DATA_PORT, Mask2);
+
+ return Result;
+}
+
+static VOID
+DetectBusMouse(
+ _Inout_ PCONFIGURATION_COMPONENT_DATA BusKey)
+{
+ ULONG IoBase, Irq, Signature1, Signature2, Signature3;
+
+ /*
+ * The bus mouse lives at one of these addresses: 0x230, 0x234, 0x238, 0x23C.
+ * The 0x23C port is the most common I/O setting.
+ */
+ for (IoBase = 0x23C; IoBase >= 0x230; IoBase -= 4)
+ {
+ Signature1 = READ_PORT_UCHAR((PUCHAR)IoBase + INPORT_REGISTER_SIGNATURE);
+ Signature2 = READ_PORT_UCHAR((PUCHAR)IoBase + INPORT_REGISTER_SIGNATURE);
+ if (Signature1 == Signature2)
+ continue;
+ if (Signature1 != INPORT_SIGNATURE && Signature2 != INPORT_SIGNATURE)
+ continue;
+
+ Signature3 = READ_PORT_UCHAR((PUCHAR)IoBase + INPORT_REGISTER_SIGNATURE);
+ if (Signature1 != Signature3)
+ continue;
+
+ Irq = DetectBusMouseIrq(IoBase);
+ if (Irq == 0)
+ continue;
+
+ CreateBusMousePeripheralKey(BusKey, IoBase, Irq);
+ break;
+ }
+}
+#endif /* _M_IX86 */
// Implemented in pcvesa.c, returns the VESA version
USHORT BiosIsVesaSupported(VOID);
@@ -1393,6 +1604,9 @@ DetectIsaBios(PCONFIGURATION_COMPONENT_DATA SystemKey, ULONG
*BusNumber)
DetectParallelPorts(BusKey);
DetectKeyboardController(BusKey);
DetectPS2Mouse(BusKey);
+#if defined(_M_IX86)
+ DetectBusMouse(BusKey);
+#endif
DetectDisplayController(BusKey);
/* FIXME: Detect more ISA devices */
diff --git a/boot/freeldr/freeldr/pcat.cmake b/boot/freeldr/freeldr/pcat.cmake
index 24c8e3627f0..5ea6f9b8aa7 100644
--- a/boot/freeldr/freeldr/pcat.cmake
+++ b/boot/freeldr/freeldr/pcat.cmake
@@ -42,6 +42,7 @@ if(ARCH STREQUAL "i386")
arch/i386/drvmap.S
arch/i386/entry.S
arch/i386/int386.S
+ arch/i386/irqsup.S
arch/i386/pnpbios.S
# arch/i386/i386trap.S
arch/i386/linux.S)