[FREELDR] Add Serial ports detection in DetectIsaBios() (#1829)
authorStanislav Motylkov <x86corez@gmail.com>
Fri, 16 Aug 2019 18:00:25 +0000 (21:00 +0300)
committerHermès BÉLUSCA - MAÏTO <hermes.belusca-maito@reactos.org>
Fri, 16 Aug 2019 18:00:25 +0000 (20:00 +0200)
CORE-16216

boot/freeldr/freeldr/arch/i386/machpc.c
boot/freeldr/freeldr/arch/i386/machxbox.c
boot/freeldr/freeldr/include/arch/i386/machxbox.h
boot/freeldr/freeldr/include/arch/pc/hardware.h

index ede5441..1929be4 100644 (file)
@@ -636,17 +636,32 @@ DetectSerialPointerPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey,
     }
 }
 
-static
+ULONG
+PcGetSerialPort(ULONG Index, PULONG Irq)
+{
+    static const ULONG PcIrq[MAX_COM_PORTS] = {4, 3, 4, 3};
+    PUSHORT BasePtr;
+
+    /*
+     * The BIOS data area 0x400 holds the address of the first valid COM port.
+     * Each COM port address is stored in a 2-byte field.
+     * Infos at: http://www.bioscentral.com/misc/bda.htm
+     */
+    BasePtr = (PUSHORT)0x400;
+    *Irq = PcIrq[Index];
+
+    return (ULONG) *(BasePtr + Index);
+}
+
 VOID
-DetectSerialPorts(PCONFIGURATION_COMPONENT_DATA BusKey)
+DetectSerialPorts(PCONFIGURATION_COMPONENT_DATA BusKey, GET_SERIAL_PORT MachGetSerialPort, ULONG Count)
 {
     PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
     PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
     PCM_SERIAL_DEVICE_DATA SerialDeviceData;
-    ULONG Irq[MAX_COM_PORTS] = {4, 3, 4, 3};
+    ULONG Irq;
     ULONG Base;
     CHAR Buffer[80];
-    PUSHORT BasePtr;
     ULONG ControllerNumber = 0;
     PCONFIGURATION_COMPONENT_DATA ControllerKey;
     ULONG i;
@@ -654,16 +669,9 @@ DetectSerialPorts(PCONFIGURATION_COMPONENT_DATA BusKey)
 
     TRACE("DetectSerialPorts()\n");
 
-    /*
-     * The BIOS data area 0x400 holds the address of the first valid COM port.
-     * Each COM port address is stored in a 2-byte field.
-     * Infos at: http://www.bioscentral.com/misc/bda.htm
-     */
-    BasePtr = (PUSHORT)0x400;
-
-    for (i = 0; i < MAX_COM_PORTS; i++, BasePtr++)
+    for (i = 0; i < Count; i++)
     {
-        Base = (ULONG) * BasePtr;
+        Base = MachGetSerialPort(i, &Irq);
         if ((Base == 0) || !CpDoesPortExist(UlongToPtr(Base)))
             continue;
 
@@ -703,8 +711,8 @@ DetectSerialPorts(PCONFIGURATION_COMPONENT_DATA BusKey)
         PartialDescriptor->Type = CmResourceTypeInterrupt;
         PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
         PartialDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
-        PartialDescriptor->u.Interrupt.Level = Irq[i];
-        PartialDescriptor->u.Interrupt.Vector = Irq[i];
+        PartialDescriptor->u.Interrupt.Level = Irq;
+        PartialDescriptor->u.Interrupt.Vector = Irq;
         PartialDescriptor->u.Interrupt.Affinity = 0xFFFFFFFF;
 
         /* Set serial data (device specific) */
@@ -1319,7 +1327,7 @@ DetectIsaBios(PCONFIGURATION_COMPONENT_DATA SystemKey, ULONG *BusNumber)
 
     /* Detect ISA/BIOS devices */
     DetectBiosDisks(SystemKey, BusKey);
-    DetectSerialPorts(BusKey);
+    DetectSerialPorts(BusKey, PcGetSerialPort, MAX_COM_PORTS);
     DetectParallelPorts(BusKey);
     DetectKeyboardController(BusKey);
     DetectPS2Mouse(BusKey);
index 4b96228..b3cd4f5 100644 (file)
@@ -35,6 +35,53 @@ XboxFindPciBios(PPCI_REGISTRY_INFO BusData)
     return TRUE;
 }
 
+extern
+VOID
+DetectSerialPointerPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey, PUCHAR Base);
+
+static
+ULONG
+XboxGetSerialPort(ULONG Index, PULONG Irq)
+{
+    /*
+     * Xbox may have maximum two Serial COM ports
+     * if the Super I/O chip is connected via LPC
+     */
+    static const UCHAR Device[MAX_XBOX_COM_PORTS] = {LPC_DEVICE_SERIAL_PORT_1, LPC_DEVICE_SERIAL_PORT_2};
+    ULONG ComBase = 0;
+
+    // Enter Configuration
+    WRITE_PORT_UCHAR(LPC_IO_BASE, LPC_ENTER_CONFIG_KEY);
+
+    // Select serial device
+    WRITE_PORT_UCHAR(LPC_IO_BASE, LPC_CONFIG_DEVICE_NUMBER);
+    WRITE_PORT_UCHAR(LPC_IO_BASE + 1, Device[Index]);
+
+    // Check if selected device is active
+    WRITE_PORT_UCHAR(LPC_IO_BASE, LPC_CONFIG_DEVICE_ACTIVATE);
+    if (READ_PORT_UCHAR(LPC_IO_BASE + 1) == 1)
+    {
+        // Read LSB
+        WRITE_PORT_UCHAR(LPC_IO_BASE, LPC_CONFIG_DEVICE_BASE_ADDRESS_LOW);
+        ComBase = READ_PORT_UCHAR(LPC_IO_BASE + 1);
+        // Read MSB
+        WRITE_PORT_UCHAR(LPC_IO_BASE, LPC_CONFIG_DEVICE_BASE_ADDRESS_HIGH);
+        ComBase |= (READ_PORT_UCHAR(LPC_IO_BASE + 1) << 8);
+        // Read IRQ
+        WRITE_PORT_UCHAR(LPC_IO_BASE, LPC_CONFIG_DEVICE_INTERRUPT);
+        *Irq = READ_PORT_UCHAR(LPC_IO_BASE + 1);
+    }
+
+    // Exit Configuration
+    WRITE_PORT_UCHAR(LPC_IO_BASE, LPC_EXIT_CONFIG_KEY);
+
+    return ComBase;
+}
+
+extern
+VOID
+DetectSerialPorts(PCONFIGURATION_COMPONENT_DATA BusKey, GET_SERIAL_PORT MachGetSerialPort, ULONG Count);
+
 VOID
 XboxGetExtendedBIOSData(PULONG ExtendedBIOSDataArea, PULONG ExtendedBIOSDataSize)
 {
@@ -155,6 +202,7 @@ DetectIsaBios(PCONFIGURATION_COMPONENT_DATA SystemKey, ULONG *BusNumber)
 
     /* Detect ISA/BIOS devices */
     DetectBiosDisks(SystemKey, BusKey);
+    DetectSerialPorts(BusKey, XboxGetSerialPort, MAX_XBOX_COM_PORTS);
 
     /* FIXME: Detect more ISA devices */
 }
index d1c42a4..f481bbd 100644 (file)
 #include "mm.h"
 #endif
 
+#define MAX_XBOX_COM_PORTS    2
+
+#define LPC_IO_BASE             0x2E
+#define LPC_ENTER_CONFIG_KEY    0x55
+#define LPC_EXIT_CONFIG_KEY     0xAA
+
+#define LPC_DEVICE_SERIAL_PORT_1    0x4
+#define LPC_DEVICE_SERIAL_PORT_2    0x5
+
+#define LPC_CONFIG_DEVICE_NUMBER                0x07
+#define LPC_CONFIG_DEVICE_ACTIVATE              0x30
+#define LPC_CONFIG_DEVICE_BASE_ADDRESS_HIGH     0x60
+#define LPC_CONFIG_DEVICE_BASE_ADDRESS_LOW      0x61
+#define LPC_CONFIG_DEVICE_INTERRUPT             0x70
+
 extern UCHAR XboxFont8x16[256 * 16];
 
 VOID XboxMachInit(const char *CmdLine);
index bc6aad1..56e6028 100644 (file)
@@ -44,6 +44,10 @@ BOOLEAN
 
 extern FIND_PCI_BIOS FindPciBios;
 
+typedef
+ULONG
+(*GET_SERIAL_PORT)(ULONG Index, PULONG Irq);
+
 VOID
 DetectBiosDisks(PCONFIGURATION_COMPONENT_DATA SystemKey,
                 PCONFIGURATION_COMPONENT_DATA BusKey);