[HALPC98] Add Hardware Abstraction Layer for NEC PC-98 series (#3002)
authorDmitry Borisov <di.sean@protonmail.com>
Sat, 25 Jul 2020 13:31:02 +0000 (19:31 +0600)
committerGitHub <noreply@github.com>
Sat, 25 Jul 2020 13:31:02 +0000 (15:31 +0200)
37 files changed:
boot/bootdata/txtsetup.sif
hal/halx86/CMakeLists.txt
hal/halx86/generic.cmake
hal/halx86/generic/bios.c
hal/halx86/generic/cmos.c
hal/halx86/generic/dma.c
hal/halx86/generic/misc.c
hal/halx86/generic/nmi.c [new file with mode: 0644]
hal/halx86/generic/timer.c
hal/halx86/generic/usage.c
hal/halx86/include/bus.h
hal/halx86/include/hal.h
hal/halx86/include/halhw.h
hal/halx86/include/halp.h
hal/halx86/legacy/halpcat.c
hal/halx86/minihal/CMakeLists.txt
hal/halx86/pc98.cmake [new file with mode: 0644]
hal/halx86/pc98/beep.c [new file with mode: 0644]
hal/halx86/pc98/clock.c [new file with mode: 0644]
hal/halx86/pc98/cmos.c [new file with mode: 0644]
hal/halx86/pc98/delay.c [new file with mode: 0644]
hal/halx86/pc98/halpc98.rc [new file with mode: 0644]
hal/halx86/pc98/irql.c [new file with mode: 0644]
hal/halx86/pc98/pic.c [new file with mode: 0644]
hal/halx86/pc98/profil.c [new file with mode: 0644]
hal/halx86/pc98/reboot.c [new file with mode: 0644]
hal/halx86/pic.cmake
hal/halx86/up/halinit_up.c
hal/halx86/up/irql.c [new file with mode: 0644]
hal/halx86/up/pic.c
hal/halx86/xbox.cmake
hal/halx86/xbox/halinit_xbox.c
media/inf/hal.inf
sdk/include/reactos/drivers/pc98/cpu.h
sdk/include/reactos/drivers/pc98/pic.h [new file with mode: 0644]
sdk/include/reactos/drivers/pc98/rtc.h [new file with mode: 0644]
sdk/include/reactos/drivers/pc98/sysport.h

index f8a8084..807c8a7 100644 (file)
@@ -226,6 +226,7 @@ pci_up = "Standard PC Uniprocessor"
 acpi_up = "ACPI PC Uniprocessor"
 ;acpi_mp = "ACPI PC Multiprocessor"
 xbox = "Original Xbox (x86 based)"
+pc98_up = "Uniprocessor NEC PC-98"
 
 [Computer.NTamd64]
 x64_up = "Standard x64 Uniprocessor"
@@ -237,6 +238,7 @@ pci_up = "PC UP"
 acpi_up = "ACPI UP"
 ;acpi_mp = "ACPI MP"
 xbox = "Xbox"
+pc98_up = "NEC PC-98 UP"
 
 [Map.Computer.NTamd64]
 x64_up = "ACPI UP"
@@ -261,6 +263,10 @@ halacpi.dll  = 1,,,,,,,2,,,hal.dll,1,2
 ntoskrnl.exe = 1,,,,,,,2,,,,1,2
 halxbox.dll  = 1,,,,,,,2,,,hal.dll,1,2
 
+[Files.pc98_up]
+ntoskrnl.exe = 1,,,,,,,2,,,,1,2
+halpc98.dll  = 1,,,,,,,2,,,hal.dll,1,2
+
 [Files.x64_up]
 ntoskrnl.exe = 1,,,,,,,2,,,,1,2
 hal.dll      = 1,,,,,,,2,,,,1,2
index 4dabc83..c7f1bda 100644 (file)
@@ -32,6 +32,14 @@ function(add_hal _halname)
         target_link_libraries(${_halname} ${_haldata_LIBS})
     endif()
 
+    if(${_halname} STREQUAL "halpc98")
+        target_compile_definitions(lib_hal_pc98 PRIVATE SARCH_PC98)
+    endif()
+
+    if(${_halname} STREQUAL "halxbox")
+        target_compile_definitions(lib_hal_xbox PRIVATE SARCH_XBOX)
+    endif()
+
     if(${_halname} STREQUAL "hal")
         target_link_libraries(${_halname} libcntpr arbiter)
     else()
@@ -61,14 +69,19 @@ if(ARCH STREQUAL "i386")
     include(up.cmake)
     include(pic.cmake)
     include(xbox.cmake)
+    include(pc98.cmake)
     add_subdirectory(minihal)
 
+    remove_definitions(-DSARCH_XBOX)
+    remove_definitions(-DSARCH_PC98)
+
     # hal
     add_hal(hal SOURCES up/halup.rc COMPONENTS generic legacy up pic)
     add_hal(halacpi SOURCES acpi/halacpi.rc COMPONENTS generic acpi up pic)
     add_hal(halapic SOURCES acpi/halacpi.rc COMPONENTS generic legacy up apic)
     add_hal(halaacpi SOURCES acpi/halacpi.rc COMPONENTS generic acpi up apic)
     add_hal(halxbox SOURCES xbox/halxbox.rc COMPONENTS xbox up)
+    add_hal(halpc98 SOURCES pc98/halpc98.rc COMPONENTS pc98 up)
 
     #add_hal(halmps SOURCES up/halup.rc COMPONENTS generic legacy smp pic)
     #add_hal(halmacpi SOURCES acpi/halacpi.rc COMPONENTS generic acpi smp pic)
index 143f6d1..19eb850 100644 (file)
@@ -8,6 +8,7 @@ list(APPEND HAL_GENERIC_SOURCE
     generic/halinit.c
     generic/memory.c
     generic/misc.c
+    generic/nmi.c
     generic/pic.c
     generic/reboot.c
     generic/sysinfo.c
index 2fe73aa..aac2502 100644 (file)
@@ -1,7 +1,6 @@
 /*
  * PROJECT:         ReactOS Hardware Abstraction Layer (HAL)
  * LICENSE:         BSD - See COPYING.ARM in the top level directory
- * FILE:            hal/halx86/generic/bios.c
  * PURPOSE:         BIOS Access Routines
  * PROGRAMMERS:     ReactOS Portable Systems Group
  *                  Alex Ionescu (alex.ionescu@reactos.org)
@@ -10,8 +9,10 @@
 /* INCLUDES *******************************************************************/
 
 #include <hal.h>
+
 #define NDEBUG
 #include <debug.h>
+
 #include <setjmp.h>
 
 void __cdecl HalpTrap0D();
@@ -645,7 +646,8 @@ BOOLEAN
 NTAPI
 HalpBiosDisplayReset(VOID)
 {
-#ifdef SARCH_XBOX
+#if defined(SARCH_XBOX) || defined(SARCH_PC98)
+    /* There is no VGA BIOS on these machine types */
     return FALSE;
 #else
     ULONG Flags;
index 689883b..2703c6a 100644 (file)
@@ -1,7 +1,6 @@
 /*
  * PROJECT:         ReactOS HAL
  * LICENSE:         GPL - See COPYING in the top level directory
- * FILE:            hal/halx86/generic/cmos.c
  * PURPOSE:         CMOS Access Routines (Real Time Clock and LastKnownGood)
  * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
  *                  Eric Kohl
@@ -10,6 +9,7 @@
 /* INCLUDES ******************************************************************/
 
 #include <hal.h>
+
 #define NDEBUG
 #include <debug.h>
 
@@ -23,6 +23,7 @@ UCHAR HalpCmosCenturyOffset;
 
 /* PRIVATE FUNCTIONS *********************************************************/
 
+_Requires_lock_held_(HalpSystemHardwareLock)
 UCHAR
 NTAPI
 HalpReadCmos(IN UCHAR Reg)
@@ -34,6 +35,7 @@ HalpReadCmos(IN UCHAR Reg)
     return READ_PORT_UCHAR(CMOS_DATA_PORT);
 }
 
+_Requires_lock_held_(HalpSystemHardwareLock)
 VOID
 NTAPI
 HalpWriteCmos(IN UCHAR Reg,
@@ -48,10 +50,11 @@ HalpWriteCmos(IN UCHAR Reg,
 
 ULONG
 NTAPI
-HalpGetCmosData(IN ULONG BusNumber,
-                IN ULONG SlotNumber,
-                IN PVOID Buffer,
-                IN ULONG Length)
+HalpGetCmosData(
+    _In_ ULONG BusNumber,
+    _In_ ULONG SlotNumber,
+    _Out_writes_bytes_(Length) PVOID Buffer,
+    _In_ ULONG Length)
 {
     PUCHAR Ptr = (PUCHAR)Buffer;
     ULONG Address = SlotNumber;
@@ -173,9 +176,10 @@ HalpInitializeCmos(VOID)
  */
 ARC_STATUS
 NTAPI
-HalGetEnvironmentVariable(IN PCH Name,
-                          IN USHORT ValueLength,
-                          IN PCH Value)
+HalGetEnvironmentVariable(
+    _In_ PCH Name,
+    _In_ USHORT ValueLength,
+    _Out_writes_z_(ValueLength) PCH Value)
 {
     UCHAR Val;
 
index 39c2efe..d8a8a69 100644 (file)
@@ -133,6 +133,24 @@ static DMA_OPERATIONS HalpDmaOperations = {
 
 /* FUNCTIONS *****************************************************************/
 
+#if defined(SARCH_PC98)
+/*
+ * Disable I/O for safety.
+ * FIXME: Add support for PC-98 DMA controllers.
+ */
+#undef WRITE_PORT_UCHAR
+#undef READ_PORT_UCHAR
+
+#define WRITE_PORT_UCHAR(Port, Data) \
+    do { \
+        UNIMPLEMENTED; \
+        (Port); \
+        (Data); \
+    } while (0)
+
+#define READ_PORT_UCHAR(Port) 0x00
+#endif
+
 #ifndef _MINIHAL_
 INIT_FUNCTION
 VOID
index 7e1eb37..67b8bcf 100644 (file)
@@ -1,15 +1,13 @@
 /*
  * PROJECT:         ReactOS Hardware Abstraction Layer (HAL)
  * LICENSE:         BSD - See COPYING.ARM in the top level directory
- * FILE:            hal/halx86/generic/misc.c
- * PURPOSE:         NMI, I/O Mapping and x86 Subs
+ * PURPOSE:         I/O Mapping and x86 Subs
  * PROGRAMMERS:     ReactOS Portable Systems Group
  */
 
 /* INCLUDES *******************************************************************/
 
 #include <hal.h>
-#include <drivers/bootvid/display.h>
 
 #define NDEBUG
 #include <debug.h>
@@ -21,8 +19,6 @@
 
 /* GLOBALS  *******************************************************************/
 
-BOOLEAN HalpNMIInProgress;
-
 UCHAR HalpSerialLen;
 CHAR HalpSerialNumber[31];
 
@@ -148,7 +144,7 @@ HalpOpenRegistryKey(IN PHANDLE KeyHandle,
     /* We're done */
     return Status;
 }
-#endif
+#endif /* !_MINIHAL_ */
 
 VOID
 NTAPI
@@ -223,108 +219,6 @@ HalpFlushTLB(VOID)
 
 /* FUNCTIONS *****************************************************************/
 
-/*
- * @implemented
- */
-VOID
-NTAPI
-HalHandleNMI(IN PVOID NmiInfo)
-{
-#ifndef _MINIHAL_
-    SYSTEM_CONTROL_PORT_B_REGISTER SystemControl;
-
-    //
-    // Don't recurse
-    //
-    if (HalpNMIInProgress++) ERROR_DBGBREAK();
-
-    //
-    // Read the system control register B
-    //
-    SystemControl.Bits = __inbyte(SYSTEM_CONTROL_PORT_B);
-
-    //
-    // Switch to boot video
-    //
-    if (InbvIsBootDriverInstalled())
-    {
-        //
-        // Acquire ownership
-        //
-        InbvAcquireDisplayOwnership();
-        InbvResetDisplay();
-
-        //
-        // Fill the screen
-        //
-        InbvSolidColorFill(0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1, BV_COLOR_RED);
-        InbvSetScrollRegion(0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1);
-
-        //
-        // Enable text
-        //
-        InbvSetTextColor(BV_COLOR_WHITE);
-        InbvInstallDisplayStringFilter(NULL);
-        InbvEnableDisplayString(TRUE);
-    }
-
-    //
-    // Display NMI failure string
-    //
-    InbvDisplayString("\r\n*** Hardware Malfunction\r\n\r\n");
-    InbvDisplayString("Call your hardware vendor for support\r\n\r\n");
-
-    //
-    // Check for parity error
-    //
-    if (SystemControl.ParityCheck)
-    {
-        //
-        // Display message
-        //
-        InbvDisplayString("NMI: Parity Check / Memory Parity Error\r\n");
-    }
-
-    //
-    // Check for I/O failure
-    //
-    if (SystemControl.ChannelCheck)
-    {
-        //
-        // Display message
-        //
-        InbvDisplayString("NMI: Channel Check / IOCHK\r\n");
-    }
-
-    //
-    // Check for EISA systems
-    //
-    if (HalpBusType == MACHINE_TYPE_EISA)
-    {
-        //
-        // FIXME: Not supported
-        //
-        UNIMPLEMENTED;
-    }
-
-    //
-    // Halt the system
-    //
-    InbvDisplayString("\r\n*** The system has halted ***\r\n");
-
-
-    //
-    // Enter the debugger if possible
-    //
-    KiBugCheckData[0] = (ULONG_PTR)KeServiceDescriptorTable; /* NMI Corruption? */
-    //if (!(KdDebuggerNotPresent) && (KdDebuggerEnabled)) KeEnterKernelDebugger();
-#endif
-    //
-    // Freeze the system
-    //
-    while (TRUE);
-}
-
 /*
  * @implemented
  */
@@ -407,5 +301,4 @@ KeReleaseSpinLock(PKSPIN_LOCK SpinLock,
     KfReleaseSpinLock(SpinLock, NewIrql);
 }
 
-#endif
-
+#endif /* _M_IX86 */
diff --git a/hal/halx86/generic/nmi.c b/hal/halx86/generic/nmi.c
new file mode 100644 (file)
index 0000000..3da64f1
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * PROJECT:         ReactOS Hardware Abstraction Layer
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
+ * PURPOSE:         NMI handling
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <hal.h>
+#include <drivers/bootvid/display.h>
+
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS  *******************************************************************/
+
+BOOLEAN HalpNMIInProgress;
+
+/* FUNCTIONS *****************************************************************/
+
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+HalHandleNMI(
+    IN PVOID NmiInfo)
+{
+    UNREFERENCED_PARAMETER(NmiInfo);
+#ifndef _MINIHAL_
+    SYSTEM_CONTROL_PORT_B_REGISTER SystemControl;
+
+    /* Don't recurse */
+    if (HalpNMIInProgress++)
+        ERROR_DBGBREAK();
+
+    /* Get NMI reason from hardware */
+#if defined(SARCH_PC98)
+    SystemControl.Bits = __inbyte(PPI_IO_i_PORT_B);
+#else
+    SystemControl.Bits = __inbyte(SYSTEM_CONTROL_PORT_B);
+#endif
+
+    /* Switch to boot video */
+    if (InbvIsBootDriverInstalled())
+    {
+        /* Acquire ownership */
+        InbvAcquireDisplayOwnership();
+        InbvResetDisplay();
+
+        /* Fill the screen */
+        InbvSolidColorFill(0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1, BV_COLOR_RED);
+        InbvSetScrollRegion(0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1);
+
+        /* Enable text */
+        InbvSetTextColor(BV_COLOR_WHITE);
+        InbvInstallDisplayStringFilter(NULL);
+        InbvEnableDisplayString(TRUE);
+    }
+
+    /* Display NMI failure string */
+    InbvDisplayString("\r\n*** Hardware Malfunction\r\n\r\n");
+    InbvDisplayString("Call your hardware vendor for support\r\n\r\n");
+
+#if defined(SARCH_PC98)
+    /* Check for parity error */
+    if (SystemControl.MemoryParityCheck)
+    {
+        InbvDisplayString("NMI: Parity Check / Memory Parity Error\r\n");
+    }
+    if (SystemControl.ExtendedMemoryParityCheck)
+    {
+        InbvDisplayString("NMI: Parity Check / Extended Memory Parity Error\r\n");
+    }
+#else
+    /* Check for parity error */
+    if (SystemControl.ParityCheck)
+    {
+        InbvDisplayString("NMI: Parity Check / Memory Parity Error\r\n");
+    }
+
+    /* Check for I/O failure */
+    if (SystemControl.ChannelCheck)
+    {
+        InbvDisplayString("NMI: Channel Check / IOCHK\r\n");
+    }
+#endif
+
+    /* Check for EISA systems */
+    if (HalpBusType == MACHINE_TYPE_EISA)
+    {
+        /* FIXME: Not supported */
+        UNIMPLEMENTED;
+    }
+
+    /* Halt the system */
+    InbvDisplayString("\r\n*** The system has halted ***\r\n");
+
+    /* Enter the debugger if possible */
+    KiBugCheckData[0] = (ULONG_PTR)KeServiceDescriptorTable; /* NMI Corruption? */
+    //if (!(KdDebuggerNotPresent) && (KdDebuggerEnabled)) KeEnterKernelDebugger();
+#endif /* !_MINIHAL_ */
+
+    /* Freeze the system */
+    while (TRUE)
+        NOTHING;
+}
index c9fe80c..3d5b1b0 100644 (file)
@@ -1,7 +1,6 @@
 /*
  * PROJECT:         ReactOS HAL
  * LICENSE:         GPL - See COPYING in the top level directory
- * FILE:            hal/halx86/generic/timer.c
  * PURPOSE:         HAL Timer Routines
  * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
  *                  Timo Kreuzer (timo.kreuzer@reactos.org)
@@ -101,6 +100,10 @@ HalpInitializeClock(VOID)
 
     DPRINT("HalpInitializeClock()\n");
 
+#if defined(SARCH_PC98)
+    HalpInitializeClockPc98();
+#endif
+
     /* Get increment and rollover for the largest time clock ms possible */
     Increment = HalpRolloverTable[HalpLargestClockMS - 1].Increment;
     RollOver = (USHORT)HalpRolloverTable[HalpLargestClockMS - 1].RollOver;
@@ -129,7 +132,7 @@ HalpClockInterruptHandler(IN PKTRAP_FRAME TrapFrame)
     KiEnterInterruptTrap(TrapFrame);
 
     /* Start the interrupt */
-    if (HalBeginSystemInterrupt(CLOCK2_LEVEL, PRIMARY_VECTOR_BASE, &Irql))
+    if (HalBeginSystemInterrupt(CLOCK2_LEVEL, PRIMARY_VECTOR_BASE + PIC_TIMER_IRQ, &Irql))
     {
         /* Update the performance counter */
         HalpPerfCounter.QuadPart += HalpCurrentRollOver;
@@ -170,13 +173,20 @@ HalpProfileInterruptHandler(IN PKTRAP_FRAME TrapFrame)
     KiEnterInterruptTrap(TrapFrame);
 
     /* Start the interrupt */
-    if (HalBeginSystemInterrupt(PROFILE_LEVEL, PRIMARY_VECTOR_BASE + 8, &Irql))
+    if (HalBeginSystemInterrupt(PROFILE_LEVEL, PRIMARY_VECTOR_BASE + PIC_RTC_IRQ, &Irql))
     {
+#if defined(SARCH_PC98)
+        /* Clear the interrupt flag */
+        HalpAcquireCmosSpinLock();
+        (VOID)__inbyte(RTC_IO_i_INTERRUPT_RESET);
+        HalpReleaseCmosSpinLock();
+#else
         /* Spin until the interrupt pending bit is clear */
         HalpAcquireCmosSpinLock();
         while (HalpReadCmos(RTC_REGISTER_C) & RTC_REG_C_IRQ)
-            ;
+            NOTHING;
         HalpReleaseCmosSpinLock();
+#endif
 
         /* If profiling is enabled, call the kernel function */
         if (!HalpProfilingStopped)
@@ -192,9 +202,9 @@ HalpProfileInterruptHandler(IN PKTRAP_FRAME TrapFrame)
     /* Spurious, just end the interrupt */
     KiEoiHelper(TrapFrame);
 }
-#endif
+#endif /* !_MINIHAL_ */
 
-#endif
+#endif /* _M_IX86 */
 
 /* PUBLIC FUNCTIONS ***********************************************************/
 
index 5f94fee..78ad3c6 100644 (file)
@@ -1,7 +1,6 @@
 /*
  * PROJECT:         ReactOS HAL
  * LICENSE:         GPL - See COPYING in the top level directory
- * FILE:            hal/halx86/generic/usage.c
  * PURPOSE:         HAL Resource Report Routines
  * PROGRAMMERS:     Stefan Ginsberg (stefan.ginsberg@reactos.org)
  */
@@ -9,6 +8,7 @@
 /* INCLUDES *******************************************************************/
 
 #include <hal.h>
+
 #define NDEBUG
 #include <debug.h>
 
@@ -82,6 +82,60 @@ ADDRESS_USAGE HalpDefaultIoSpace =
 {
     NULL, CmResourceTypePort, IDT_INTERNAL,
     {
+#if defined(SARCH_PC98)
+        /* PIC 1 */
+        {0x00,  1},
+        {0x02,  1},
+        /* PIC 2 */
+        {0x08,  1},
+        {0x0A,  1},
+        /* DMA */
+        {0x01,  1},
+        {0x03,  1},
+        {0x05,  1},
+        {0x07,  1},
+        {0x09,  1},
+        {0x0B,  1},
+        {0x0D,  1},
+        {0x0F,  1},
+        {0x11,  1},
+        {0x13,  1},
+        {0x15,  1},
+        {0x17,  1},
+        {0x19,  1},
+        {0x1B,  1},
+        {0x1D,  1},
+        {0x1F,  1},
+        {0x21,  1},
+        {0x23,  1},
+        {0x25,  1},
+        {0x27,  1},
+        {0x29,  1},
+        {0x2B,  1},
+        {0x2D,  1},
+        {0xE05, 1},
+        {0xE07, 1},
+        {0xE09, 1},
+        {0xE0B, 1},
+        /* RTC */
+        {0x20,  1},
+        {0x22,  1},
+        {0x128, 1},
+        /* System Control */
+        {0x33,  1},
+        {0x37,  1},
+        /* PIT */
+        {0x71,  1},
+        {0x73,  1},
+        {0x75,  1},
+        {0x77,  1},
+        {0x3FD9,1},
+        {0x3FDB,1},
+        {0x3FDD,1},
+        {0x3FDF,1},
+        /* x87 Coprocessor */
+        {0xF8,  8},
+#else
         {0x00,  0x20}, /* DMA 1 */
         {0xC0,  0x20}, /* DMA 2 */
         {0x80,  0x10}, /* DMA EPAR */
@@ -92,6 +146,7 @@ ADDRESS_USAGE HalpDefaultIoSpace =
         {0x92,  0x1},  /* System Control Port A */
         {0x70,  0x2},  /* CMOS  */
         {0xF0,  0x10}, /* x87 Coprocessor */
+#endif
         {0xCF8, 0x8},  /* PCI 0 */
         {0,0},
     }
@@ -523,7 +578,7 @@ HalpReportResourceUsage(IN PUNICODE_STRING HalName,
     /* Get the machine's serial number */
     HalpReportSerialNumber();
 }
-#endif
+#endif /* !_MINIHAL_ */
 
 INIT_FUNCTION
 VOID
@@ -614,7 +669,6 @@ HalpGetNMICrashFlag(VOID)
         ZwClose(Handle);
     }
 }
-#endif
+#endif  /* !_MINIHAL_ */
 
 /* EOF */
-
index def39eb..d7af1ea 100644 (file)
@@ -411,10 +411,10 @@ HalpGetSystemInterruptVector_Acpi(
 ULONG
 NTAPI
 HalpGetCmosData(
-    IN ULONG BusNumber,
-    IN ULONG SlotNumber,
-    IN PVOID Buffer,
-    IN ULONG Length
+    _In_ ULONG BusNumber,
+    _In_ ULONG SlotNumber,
+    _Out_writes_bytes_(Length) PVOID Buffer,
+    _In_ ULONG Length
 );
 
 ULONG
index 7f632f3..8606519 100644 (file)
 #include "bus.h"
 #include "halirq.h"
 #include "haldma.h"
+#if defined(SARCH_PC98)
+#include <drivers/pc98/cpu.h>
+#include <drivers/pc98/pic.h>
+#include <drivers/pc98/pit.h>
+#include <drivers/pc98/rtc.h>
+#include <drivers/pc98/sysport.h>
+#include <drivers/pc98/video.h>
+#else
 #include "halhw.h"
+#endif
 #include "halp.h"
 #include "mps.h"
 #include "halacpi.h"
index 6da1372..cf75684 100644 (file)
@@ -32,7 +32,7 @@
 //
 // Video Modes for INT10h AH=00 (in AL)
 //
-#define GRAPHICS_MODE_12 0x12           /* 80x30        8x16  640x480   16/256K */
+#define GRAPHICS_MODE_12 0x12           /* 80x30  8x16  640x480  16/256K */
 
 #if defined(SARCH_XBOX)
 //
@@ -152,6 +152,10 @@ typedef union _SYSTEM_CONTROL_PORT_B_REGISTER
 #define PIC2_CONTROL_PORT      0xA0
 #define PIC2_DATA_PORT         0xA1
 
+#define PIC_TIMER_IRQ      0
+#define PIC_CASCADE_IRQ    2
+#define PIC_RTC_IRQ        8
+
 //
 // Definitions for ICW/OCW Bits
 //
@@ -304,19 +308,16 @@ typedef union _I8259_OCW3
 
 typedef union _I8259_ISR
 {
-    union
+    struct
     {
-        struct
-        {
-            UCHAR Irq0:1;
-            UCHAR Irq1:1;
-            UCHAR Irq2:1;
-            UCHAR Irq3:1;
-            UCHAR Irq4:1;
-            UCHAR Irq5:1;
-            UCHAR Irq6:1;
-            UCHAR Irq7:1;
-        };
+        UCHAR Irq0:1;
+        UCHAR Irq1:1;
+        UCHAR Irq2:1;
+        UCHAR Irq3:1;
+        UCHAR Irq4:1;
+        UCHAR Irq5:1;
+        UCHAR Irq6:1;
+        UCHAR Irq7:1;
     };
     UCHAR Bits;
 } I8259_ISR, *PI8259_ISR;
@@ -362,15 +363,12 @@ typedef union _EISA_ELCR
     USHORT Bits;
 } EISA_ELCR, *PEISA_ELCR;
 
-typedef struct _PIC_MASK
+typedef union _PIC_MASK
 {
-    union
+    struct
     {
-        struct
-        {
-            UCHAR Master;
-            UCHAR Slave;
-        };
-        USHORT Both;
+        UCHAR Master;
+        UCHAR Slave;
     };
+    USHORT Both;
 } PIC_MASK, *PPIC_MASK;
index cb6f6e5..1ab7874 100644 (file)
@@ -378,12 +378,14 @@ HalpInitializeCmos(
     VOID
 );
 
+_Requires_lock_held_(HalpSystemHardwareLock)
 UCHAR
 NTAPI
 HalpReadCmos(
     IN UCHAR Reg
 );
 
+_Requires_lock_held_(HalpSystemHardwareLock)
 VOID
 NTAPI
 HalpWriteCmos(
@@ -394,12 +396,14 @@ HalpWriteCmos(
 //
 // Spinlock for protecting CMOS access
 //
+_Acquires_lock_(HalpSystemHardwareLock)
 VOID
 NTAPI
 HalpAcquireCmosSpinLock(
     VOID
 );
 
+_Releases_lock_(HalpSystemHardwareLock)
 VOID
 NTAPI
 HalpReleaseCmosSpinLock(
@@ -516,6 +520,30 @@ HalpInitProcessor(
     IN PLOADER_PARAMETER_BLOCK LoaderBlock
 );
 
+#if defined(SARCH_PC98)
+BOOLEAN
+NTAPI
+HalpDismissIrq08(
+    _In_ KIRQL Irql,
+    _In_ ULONG Irq,
+    _Out_ PKIRQL OldIrql
+);
+
+BOOLEAN
+NTAPI
+HalpDismissIrq08Level(
+    _In_ KIRQL Irql,
+    _In_ ULONG Irq,
+    _Out_ PKIRQL OldIrql
+);
+
+VOID
+NTAPI
+HalpInitializeClockPc98(VOID);
+
+extern ULONG PIT_FREQUENCY;
+#endif /* SARCH_PC98 */
+
 #ifdef _M_AMD64
 
 VOID
index c660296..4b6033e 100644 (file)
@@ -1,7 +1,6 @@
 /*
  * PROJECT:         ReactOS HAL
  * LICENSE:         BSD - See COPYING.ARM in the top level directory
- * FILE:            hal/halx86/legacy/halpcat.c
  * PURPOSE:         HAL Legacy Support Code
  * PROGRAMMERS:     ReactOS Portable Systems Group
  */
@@ -9,6 +8,7 @@
 /* INCLUDES *******************************************************************/
 
 #include <hal.h>
+
 #define NDEBUG
 #include <debug.h>
 
@@ -28,6 +28,9 @@ BOOLEAN HalDisableFirmwareMapper = FALSE;
 #if defined(SARCH_XBOX)
 PWCHAR HalHardwareIdString = L"xbox";
 PWCHAR HalName = L"Xbox HAL";
+#elif defined(SARCH_PC98)
+PWCHAR HalHardwareIdString = L"pc98_up";
+PWCHAR HalName = L"NEC PC-98 Compatible NESA/C-Bus HAL";
 #else
 PWCHAR HalHardwareIdString = L"e_isa_up";
 PWCHAR HalName = L"PC Compatible Eisa/Isa HAL";
@@ -51,7 +54,7 @@ HalpBuildAddressMap(VOID)
 {
     /* FIXME: Inherit ROM blocks from the registry */
     //HalpInheritROMBlocks();
-    
+
     /* FIXME: Add the ROM blocks to our ranges */
     //HalpAddROMRanges();
 }
index 84bdf8f..47708f9 100644 (file)
@@ -7,16 +7,12 @@ list(APPEND MINI_HAL_SOURCE
     ../legacy/bus/pcibus.c
     ../legacy/bus/sysbus.c
     ../legacy/bussupp.c
-    ../generic/beep.c
     ../generic/bios.c
-    ../generic/clock.c
-    ../generic/cmos.c
     ../generic/dma.c
     ../generic/display.c
     ../generic/drive.c
     ../generic/misc.c
-    ../generic/profil.c
-    ../generic/reboot.c
+    ../generic/nmi.c
     ../generic/spinlock.c
     ../generic/sysinfo.c
     ../generic/timer.c
@@ -26,6 +22,29 @@ list(APPEND MINI_HAL_SOURCE
     ../up/processor.c
     ../include/hal.h)
 
+if(SARCH STREQUAL "xbox")
+    list(APPEND MINI_HAL_SOURCE
+        ../generic/beep.c
+        ../generic/cmos.c
+        ../generic/profil.c
+        ../xbox/clock.c
+        ../xbox/reboot.c)
+elseif(SARCH STREQUAL "pc98")
+    list(APPEND MINI_HAL_SOURCE
+        ../pc98/beep.c
+        ../pc98/clock.c
+        ../pc98/cmos.c
+        ../pc98/profil.c
+        ../pc98/reboot.c)
+else()
+    list(APPEND MINI_HAL_SOURCE
+        ../generic/beep.c
+        ../generic/clock.c
+        ../generic/cmos.c
+        ../generic/profil.c
+        ../generic/reboot.c)
+endif()
+
 add_asm_files(mini_hal_asm ../generic/systimer.S)
 add_library(mini_hal ${MINI_HAL_SOURCE} ${mini_hal_asm})
 target_compile_definitions(mini_hal PRIVATE _BLDR_ _MINIHAL_)
diff --git a/hal/halx86/pc98.cmake b/hal/halx86/pc98.cmake
new file mode 100644 (file)
index 0000000..fd51a98
--- /dev/null
@@ -0,0 +1,57 @@
+
+# Generic
+list(APPEND HAL_PC98_SOURCE
+    pc98/beep.c
+    pc98/clock.c
+    pc98/cmos.c
+    pc98/delay.c
+    pc98/pic.c
+    pc98/profil.c
+    pc98/reboot.c
+    generic/bios.c
+    generic/display.c
+    generic/dma.c
+    generic/drive.c
+    generic/halinit.c
+    generic/memory.c
+    generic/misc.c
+    generic/nmi.c
+    generic/portio.c
+    generic/sysinfo.c
+    generic/usage.c)
+
+list(APPEND HAL_PC98_ASM_SOURCE
+    generic/v86.S)
+
+# PIC
+list(APPEND HAL_PC98_SOURCE
+    pc98/irql.c
+    generic/timer.c
+    up/halinit_up.c
+    up/pic.c)
+
+list(APPEND HAL_PC98_ASM_SOURCE
+    generic/trap.S
+    up/pic.S)
+
+# Legacy
+list(APPEND HAL_PC98_SOURCE
+    legacy/bus/bushndlr.c
+    legacy/bus/cmosbus.c
+    legacy/bus/isabus.c
+    legacy/bus/pcibus.c
+    ${CMAKE_CURRENT_BINARY_DIR}/pci_classes.c
+    ${CMAKE_CURRENT_BINARY_DIR}/pci_vendors.c
+    legacy/bus/sysbus.c
+    legacy/bussupp.c
+    legacy/halpnpdd.c
+    legacy/halpcat.c)
+
+add_asm_files(lib_hal_pc98_asm ${HAL_PC98_ASM_SOURCE})
+add_object_library(lib_hal_pc98 ${HAL_PC98_SOURCE} ${lib_hal_pc98_asm})
+add_dependencies(lib_hal_pc98 bugcodes xdk asm)
+#add_pch(lib_hal_pc98 pc98/halpc98.h)
+
+if(MSVC)
+    target_link_libraries(lib_hal_pc98)
+endif()
diff --git a/hal/halx86/pc98/beep.c b/hal/halx86/pc98/beep.c
new file mode 100644 (file)
index 0000000..2d21e2d
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * PROJECT:     NEC PC-98 series HAL
+ * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
+ * PURPOSE:     Speaker support (beeping)
+ * COPYRIGHT:   Copyright 2020 Dmitry Borisov (di.sean@protonmail.com)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <hal.h>
+
+#define NDEBUG
+#include <debug.h>
+
+/* FUNCTIONS *****************************************************************/
+
+BOOLEAN
+NTAPI
+HalMakeBeep(
+    _In_ ULONG Frequency)
+{
+    TIMER_CONTROL_PORT_REGISTER TimerControl;
+    ULONG Divider;
+    BOOLEAN Success = FALSE;
+
+    HalpAcquireCmosSpinLock();
+
+    __outbyte(PPI_IO_o_CONTROL, PPI_TIMER_1_UNGATE_TO_SPEAKER);
+
+    if (Frequency)
+    {
+        Divider = PIT_FREQUENCY / Frequency;
+
+        if (Divider <= 0x10000)
+        {
+            TimerControl.BcdMode = FALSE;
+            TimerControl.OperatingMode = PitOperatingMode3;
+            TimerControl.Channel = PitChannel1;
+            TimerControl.AccessMode = PitAccessModeLowHigh;
+            __outbyte(TIMER_CONTROL_PORT, TimerControl.Bits);
+            __outbyte(TIMER_CHANNEL1_DATA_PORT, FIRSTBYTE(Divider));
+            __outbyte(TIMER_CHANNEL1_DATA_PORT, SECONDBYTE(Divider));
+
+            __outbyte(PPI_IO_o_CONTROL, PPI_TIMER_1_GATE_TO_SPEAKER);
+
+            Success = TRUE;
+        }
+    }
+
+    HalpReleaseCmosSpinLock();
+
+    return Success;
+}
diff --git a/hal/halx86/pc98/clock.c b/hal/halx86/pc98/clock.c
new file mode 100644 (file)
index 0000000..3b6c304
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * PROJECT:     NEC PC-98 series HAL
+ * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
+ * PURPOSE:     PIT rollover tables
+ * COPYRIGHT:   Copyright 2020 Dmitry Borisov (di.sean@protonmail.com)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <hal.h>
+
+/* GLOBALS *******************************************************************/
+
+#define LPT_STATUS         0x42
+#define SYSTEM_CLOCK_8_MHZ 0x20
+
+ULONG PIT_FREQUENCY;
+HALP_ROLLOVER HalpRolloverTable[15];
+
+/* Accuracy is 97.5% */
+static const HALP_ROLLOVER RolloverTable1[15] =
+{
+    {1996, 9996}, /* 1 ms */
+    {3993, 19997},
+    {5990, 29998},
+    {7987, 39999},
+    {9984, 50000},
+    {11980, 59996},
+    {13977, 69997},
+    {15974, 79998},
+    {17971, 89999},
+    {19968, 100000},
+    {21964, 109996},
+    {23961, 119997},
+    {25958, 129998},
+    {27955, 139999},
+    {29951, 149995} /* 15 ms */
+};
+static const HALP_ROLLOVER RolloverTable2[15] =
+{
+    {2463, 10022}, /* 1 ms */
+    {4912, 19987},
+    {7376, 30013},
+    {9825, 39978},
+    {12288, 50000},
+    {14751, 60022},
+    {17200, 69987},
+    {19664, 80013},
+    {22113, 89978},
+    {24576, 100000},
+    {27039, 110022},
+    {29488, 119987},
+    {31952, 130013},
+    {34401, 139978},
+    {36864, 150000} /* 15 ms */
+};
+
+/* PRIVATE FUNCTIONS *********************************************************/
+
+VOID
+NTAPI
+HalpInitializeClockPc98(VOID)
+{
+    /* Obtain system clock value from the parallel port */
+    if (__inbyte(LPT_STATUS) & SYSTEM_CLOCK_8_MHZ)
+    {
+        PIT_FREQUENCY = TIMER_FREQUENCY_1;
+        RtlCopyMemory(HalpRolloverTable, RolloverTable1, sizeof(HALP_ROLLOVER) * 15);
+    }
+    else
+    {
+        PIT_FREQUENCY = TIMER_FREQUENCY_2;
+        RtlCopyMemory(HalpRolloverTable, RolloverTable2, sizeof(HALP_ROLLOVER) * 15);
+    }
+}
diff --git a/hal/halx86/pc98/cmos.c b/hal/halx86/pc98/cmos.c
new file mode 100644 (file)
index 0000000..99dd761
--- /dev/null
@@ -0,0 +1,322 @@
+/*
+ * PROJECT:     NEC PC-98 series HAL
+ * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
+ * PURPOSE:     RTC and NVRAM access routines
+ * COPYRIGHT:   Copyright 2020 Dmitry Borisov (di.sean@protonmail.com)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <hal.h>
+
+#define NDEBUG
+#include <debug.h>
+
+#if defined(ALLOC_PRAGMA) && !defined(_MINIHAL_)
+#pragma alloc_text(INIT, HalpInitializeCmos)
+#endif
+
+/* GLOBALS *******************************************************************/
+
+/*
+ * The PC-98 hardware maps data from the NVRAM directly into the text video
+ * memory address space. Every fourth byte is a "writable data".
+ *
+ * |0x2FE2|0x2FE3|0x2FE4|0x2FE5|0x2FE6|0x2FE7| .... |0x2FFD|0x2FFE|
+ * |  D   |      |      |      |   D  |      | .... |      |   D  |
+ *
+ * Most of these bits of the NVRAM are already used. There are some reserved
+ * bits in the 0x3FE6 and 0x3FFE that we can use.
+ */
+#define NVRAM_START         0x3FE2
+#define NVRAM_SIZE          0x1C
+#define NVRAM_UNUSED_REG    0x14
+#define NVRAM_UNUSED_BIT    0x80
+
+static ULONG_PTR MappedNvram;
+
+/* PRIVATE FUNCTIONS *********************************************************/
+
+/* Avoid double calls */
+#undef BCD_INT
+static UCHAR
+BCD_INT(
+    _In_ UCHAR Bcd)
+{
+    return ((Bcd & 0xF0) >> 4) * 10 + (Bcd & 0x0F);
+}
+
+static UCHAR
+NTAPI
+HalpReadNvram(
+    _In_ UCHAR Register)
+{
+    return READ_REGISTER_UCHAR((PUCHAR)(MappedNvram + Register));
+}
+
+_Requires_lock_held_(HalpSystemHardwareLock)
+static VOID
+NTAPI
+HalpWriteNvram(
+    _In_ UCHAR Register,
+    _In_ UCHAR Value)
+{
+    __outbyte(GDC1_IO_o_MODE_FLIPFLOP1, GDC1_NVRAM_UNPROTECT);
+    WRITE_REGISTER_UCHAR((PUCHAR)(MappedNvram + Register), Value);
+    __outbyte(GDC1_IO_o_MODE_FLIPFLOP1, GDC1_NVRAM_PROTECT);
+}
+
+_Requires_lock_held_(HalpSystemHardwareLock)
+static UCHAR
+NTAPI
+HalpRtcReadByte(VOID)
+{
+    UCHAR i;
+    UCHAR Byte = 0;
+
+    /* Read byte from single wire bus */
+    for (i = 0; i < 8; i++)
+    {
+        Byte |= (__inbyte(PPI_IO_i_PORT_B) & 1) << i;
+
+        __outbyte(RTC_IO_o_DATA, RTC_CLOCK | RTC_CMD_SERIAL_TRANSFER_MODE);
+        KeStallExecutionProcessor(1);
+
+        __outbyte(RTC_IO_o_DATA, RTC_CMD_SERIAL_TRANSFER_MODE);
+        KeStallExecutionProcessor(1);
+    }
+
+    return Byte;
+}
+
+_Requires_lock_held_(HalpSystemHardwareLock)
+static VOID
+NTAPI
+HalpRtcWriteBit(
+    _In_ UCHAR Bit)
+{
+    Bit = (Bit & 1) << 5;
+
+    __outbyte(RTC_IO_o_DATA, Bit | RTC_CMD_SERIAL_TRANSFER_MODE);
+    KeStallExecutionProcessor(1);
+
+    __outbyte(RTC_IO_o_DATA, Bit | RTC_CLOCK | RTC_CMD_SERIAL_TRANSFER_MODE);
+    KeStallExecutionProcessor(1);
+}
+
+_Requires_lock_held_(HalpSystemHardwareLock)
+static VOID
+NTAPI
+HalpRtcWriteCommand(
+    _In_ UCHAR Command)
+{
+    UCHAR i;
+
+    for (i = 0; i < 4; i++)
+        HalpRtcWriteBit(Command >> i);
+
+    __outbyte(RTC_IO_o_DATA, RTC_STROBE | RTC_CMD_SERIAL_TRANSFER_MODE);
+    KeStallExecutionProcessor(1);
+
+    __outbyte(RTC_IO_o_DATA, RTC_CMD_SERIAL_TRANSFER_MODE);
+    KeStallExecutionProcessor(1);
+}
+
+UCHAR
+NTAPI
+HalpReadCmos(
+    _In_ UCHAR Reg)
+{
+    /* Not supported by hardware */
+    return 0;
+}
+
+VOID
+NTAPI
+HalpWriteCmos(
+    _In_ UCHAR Reg,
+    _In_ UCHAR Value)
+{
+    /* Not supported by hardware */
+    NOTHING;
+}
+
+ULONG
+NTAPI
+HalpGetCmosData(
+    _In_ ULONG BusNumber,
+    _In_ ULONG SlotNumber,
+    _Out_writes_bytes_(Length) PVOID Buffer,
+    _In_ ULONG Length)
+{
+    /* Not supported by hardware */
+    return 0;
+}
+
+ULONG
+NTAPI
+HalpSetCmosData(
+    _In_ ULONG BusNumber,
+    _In_ ULONG SlotNumber,
+    _In_reads_bytes_(Length) PVOID Buffer,
+    _In_ ULONG Length)
+{
+    /* Not supported by hardware */
+    return 0;
+}
+
+INIT_FUNCTION
+VOID
+NTAPI
+HalpInitializeCmos(VOID)
+{
+    PHYSICAL_ADDRESS PhysicalAddress;
+
+    /* TODO: Detect TVRAM address */
+    if (TRUE)
+        PhysicalAddress.QuadPart = VRAM_NORMAL_TEXT + NVRAM_START;
+    else
+        PhysicalAddress.QuadPart = VRAM_HI_RESO_TEXT + NVRAM_START;
+    MappedNvram = (ULONG_PTR)HalpMapPhysicalMemory64(PhysicalAddress, BYTES_TO_PAGES(NVRAM_SIZE));
+}
+
+/* PUBLIC FUNCTIONS **********************************************************/
+
+ARC_STATUS
+NTAPI
+HalGetEnvironmentVariable(
+    _In_ PCH Name,
+    _In_ USHORT ValueLength,
+    _Out_writes_z_(ValueLength) PCH Value)
+{
+    UCHAR Val;
+
+    /* Only variable supported on x86 */
+    if (_stricmp(Name, "LastKnownGood"))
+        return ENOENT;
+
+    if (!MappedNvram)
+        return ENOENT;
+
+    HalpAcquireCmosSpinLock();
+
+    Val = HalpReadNvram(NVRAM_UNUSED_REG) & NVRAM_UNUSED_BIT;
+
+    HalpReleaseCmosSpinLock();
+
+    /* Check the flag */
+    if (Val)
+        strncpy(Value, "FALSE", ValueLength);
+    else
+        strncpy(Value, "TRUE", ValueLength);
+
+    return ESUCCESS;
+}
+
+ARC_STATUS
+NTAPI
+HalSetEnvironmentVariable(
+    _In_ PCH Name,
+    _In_ PCH Value)
+{
+    UCHAR Val;
+
+    /* Only variable supported on x86 */
+    if (_stricmp(Name, "LastKnownGood"))
+        return ENOMEM;
+
+    if (!MappedNvram)
+        return ENOMEM;
+
+    /* Check if this is true or false */
+    if (!_stricmp(Value, "TRUE"))
+    {
+        HalpAcquireCmosSpinLock();
+
+        Val = HalpReadNvram(NVRAM_UNUSED_REG) | NVRAM_UNUSED_BIT;
+    }
+    else if (!_stricmp(Value, "FALSE"))
+    {
+        HalpAcquireCmosSpinLock();
+
+        Val = HalpReadNvram(NVRAM_UNUSED_REG) & ~NVRAM_UNUSED_BIT;
+    }
+    else
+    {
+        /* Fail */
+        return ENOMEM;
+    }
+
+    HalpWriteNvram(NVRAM_UNUSED_REG, Val);
+
+    HalpReleaseCmosSpinLock();
+
+    return ESUCCESS;
+}
+
+BOOLEAN
+NTAPI
+HalQueryRealTimeClock(
+    _Out_ PTIME_FIELDS Time)
+{
+    UCHAR Temp;
+
+    HalpAcquireCmosSpinLock();
+
+    HalpRtcWriteCommand(RTC_CMD_TIME_READ);
+    HalpRtcWriteCommand(RTC_CMD_REGISTER_SHIFT);
+    KeStallExecutionProcessor(19);
+
+    /* Set the time data */
+    Time->Second = BCD_INT(HalpRtcReadByte());
+    Time->Minute = BCD_INT(HalpRtcReadByte());
+    Time->Hour = BCD_INT(HalpRtcReadByte());
+    Time->Day = BCD_INT(HalpRtcReadByte());
+    Temp = HalpRtcReadByte();
+    Time->Weekday = Temp & 0x0F;
+    Time->Month = Temp >> 4;
+    Time->Year = BCD_INT(HalpRtcReadByte());
+    Time->Milliseconds = 0;
+
+    Time->Year += (Time->Year >= 80) ? 1900 : 2000;
+
+    HalpRtcWriteCommand(RTC_CMD_REGISTER_HOLD);
+
+    HalpReleaseCmosSpinLock();
+
+    return TRUE;
+}
+
+BOOLEAN
+NTAPI
+HalSetRealTimeClock(
+    _In_ PTIME_FIELDS Time)
+{
+    UCHAR i, j;
+    UCHAR SysTime[6];
+
+    HalpAcquireCmosSpinLock();
+
+    HalpRtcWriteCommand(RTC_CMD_REGISTER_SHIFT);
+
+    SysTime[0] = INT_BCD(Time->Second);
+    SysTime[1] = INT_BCD(Time->Minute);
+    SysTime[2] = INT_BCD(Time->Hour);
+    SysTime[3] = INT_BCD(Time->Day);
+    SysTime[4] = (Time->Month << 4) | (Time->Weekday & 0x0F);
+    SysTime[5] = INT_BCD(Time->Year % 100);
+
+    /* Write time fields to RTC */
+    for (i = 0; i < 6; i++)
+    {
+        for (j = 0; j < 8; j++)
+            HalpRtcWriteBit(SysTime[i] >> j);
+    }
+
+    HalpRtcWriteCommand(RTC_CMD_TIME_SET_COUNTER_HOLD);
+    HalpRtcWriteCommand(RTC_CMD_REGISTER_HOLD);
+
+    HalpReleaseCmosSpinLock();
+
+    return TRUE;
+}
diff --git a/hal/halx86/pc98/delay.c b/hal/halx86/pc98/delay.c
new file mode 100644 (file)
index 0000000..37ab577
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * PROJECT:     NEC PC-98 series HAL
+ * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
+ * PURPOSE:     Delay routines
+ * COPYRIGHT:   Copyright 2020 Dmitry Borisov (di.sean@protonmail.com)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <hal.h>
+
+#define NDEBUG
+#include <debug.h>
+
+/* PRIVATE FUNCTIONS *********************************************************/
+
+VOID
+NTAPI
+HalpCalibrateStallExecution(VOID)
+{
+    /* FIXME */
+    NOTHING;
+}
+
+/* PUBLIC FUNCTIONS **********************************************************/
+
+#ifndef _MINIHAL_
+VOID
+NTAPI
+KeStallExecutionProcessor(
+    _In_ ULONG MicroSeconds)
+{
+    while (MicroSeconds--)
+    {
+        /* FIXME: Use stall factor */
+        WRITE_PORT_UCHAR((PUCHAR)CPU_IO_o_ARTIC_DELAY, 0);
+    }
+}
+#endif
diff --git a/hal/halx86/pc98/halpc98.rc b/hal/halx86/pc98/halpc98.rc
new file mode 100644 (file)
index 0000000..ea88398
--- /dev/null
@@ -0,0 +1,9 @@
+#define REACTOS_VERSION_DLL
+#if defined(CONFIG_SMP)
+// #define REACTOS_STR_FILE_DESCRIPTION  "NEC PC-98 series Multiprocessor Hardware Abstraction Layer"
+#else
+#define REACTOS_STR_FILE_DESCRIPTION  "NEC PC-98 series Uniprocessor Hardware Abstraction Layer"
+#endif
+#define REACTOS_STR_INTERNAL_NAME     "halpc98"
+#define REACTOS_STR_ORIGINAL_FILENAME "halpc98.dll"
+#include <reactos/version.rc>
diff --git a/hal/halx86/pc98/irql.c b/hal/halx86/pc98/irql.c
new file mode 100644 (file)
index 0000000..f14aa73
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * PROJECT:     NEC PC-98 series HAL
+ * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
+ * PURPOSE:     IRQL mapping
+ * COPYRIGHT:   Copyright 2020 Dmitry Borisov (di.sean@protonmail.com)
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <hal.h>
+
+/* GLOBALS ********************************************************************/
+
+/* This table contains the static x86 PIC mapping between IRQLs and IRQs */
+ULONG KiI8259MaskTable[32] =
+{
+    /*
+     * See comments of the PC/AT version.
+     */
+    0b00000000000000000000000000000000, /* IRQL 0 */
+    0b00000000000000000000000000000000, /* IRQL 1 */
+    0b00000000000000000000000000000000, /* IRQL 2 */
+    0b00000000000000000000000000000000, /* IRQL 3 */
+    0b11111111100000000000000000000000, /* IRQL 4 */
+    0b11111111110000000000000000000000, /* IRQL 5 */
+    0b11111111111000000000000000000000, /* IRQL 6 */
+    0b11111111111100000000000000000000, /* IRQL 7 */
+    0b11111111111110000000000000000000, /* IRQL 8 */
+    0b11111111111111000000000000000000, /* IRQL 9 */
+    0b11111111111111100000000000000000, /* IRQL 10 */
+    0b11111111111111110000000000000000, /* IRQL 11 */
+
+    /*
+     * Okay, now we're finally starting to mask off IRQs on the slave PIC, from
+     * IRQ15 to IRQ8. Note that the output of INT of RTC is connected to the IR7.
+     * We need to keep this IRQ unmasked, so we can ensure profiling the whole system.
+     */
+    0b11111111111111110000000000000000, /* IRQL 12 */
+    0b11111111111111110100000000000000, /* IRQL 13 */
+    0b11111111111111110110000000000000, /* IRQL 14 */
+    0b11111111111111110111000000000000, /* IRQL 15 */
+    0b11111111111111110111100000000000, /* IRQL 16 */
+    0b11111111111111110111110000000000, /* IRQL 17 */
+    0b11111111111111110111111000000000, /* IRQL 18 */
+    0b11111111111111110111111000000000, /* IRQL 19 */
+
+    /*
+     * Now we mask off the IRQs on the master. Since IRQL 19 we have 0 "droplet".
+     * It's the cascade IRQ that we use to bridge the slave PIC with the master PIC.
+     */
+    0b11111111111111110111111100000000, /* IRQL 20 */
+    0b11111111111111110111111101000000, /* IRQL 21 */
+    0b11111111111111110111111101100000, /* IRQL 22 */
+    0b11111111111111110111111101110000, /* IRQL 23 */
+    0b11111111111111110111111101111000, /* IRQL 24 */
+    0b11111111111111110111111101111100, /* IRQL 25 */
+    0b11111111111111110111111101111110, /* IRQL 26 */
+    0b11111111111111111111111101111110, /* IRQL 27 */
+
+    /*
+     * See comments of the PC/AT version.
+     */
+    0b11111111111111111111111101111111, /* IRQL 28 */
+    0b11111111111111111111111101111111, /* IRQL 29 */
+    0b11111111111111111111111101111111, /* IRQL 30 */
+    0b11111111111111111111111101111111  /* IRQL 31 */
+};
+
+/* This table indicates which IRQs, if pending, can preempt a given IRQL level */
+ULONG FindHigherIrqlMask[32] =
+{
+    /*
+     * See comments of the PC/AT version.
+     */
+    0b11111111111111111111111111111110, /* IRQL 0 */
+    0b11111111111111111111111111111100, /* IRQL 1 */
+    0b11111111111111111111111111111000, /* IRQL 2 */
+    0b11111111111111111111111111110000, /* IRQL 3 */
+    0b00000111111111111111111111110000, /* IRQL 4 */
+    0b00000011111111111111111111110000, /* IRQL 5 */
+    0b00000001111111111111111111110000, /* IRQL 6 */
+    0b00000000111111111111111111110000, /* IRQL 7 */
+    0b00000000011111111111111111110000, /* IRQL 8 */
+    0b00000000001111111111111111110000, /* IRQL 9 */
+    0b00000000000111111111111111110000, /* IRQL 10 */
+
+    /*
+     * Now we start progressivly limiting which slave PIC interrupts have the
+     * right to preempt us at each level. The RTC timer used for profiling,
+     * so it will always preempt until we reach PROFILE_LEVEL.
+     */
+    0b00000000000011111111111111110000, /* IRQL 11 */
+    0b00000000000011111111111111110000, /* IRQL 12 */
+    0b00000000000010111111111111110000, /* IRQL 13 */
+    0b00000000000010011111111111110000, /* IRQL 14 */
+    0b00000000000010001111111111110000, /* IRQL 15 */
+    0b00000000000010000111111111110000, /* IRQL 16 */
+    0b00000000000010000011111111110000, /* IRQL 17 */
+    0b00000000000010000001111111110000, /* IRQL 18 */
+    0b00000000000010000001111111110000, /* IRQL 19 */
+
+    /*
+     * Now with IRQs on the master PIC.
+     */
+    0b00000000000010000000011111110000, /* IRQL 20 */
+    0b00000000000010000000001111110000, /* IRQL 21 */
+    0b00000000000010000000000111110000, /* IRQL 22 */
+    0b00000000000010000000000011110000, /* IRQL 23 */
+    0b00000000000010000000000001110000, /* IRQL 24 */
+    0b00000000000010000000000000110000, /* IRQL 25 */
+    0b00000000000010000000000000010000, /* IRQL 26 */
+
+    /*
+     * See comments of the PC/AT version.
+     */
+    0b00000000000000000000000000010000, /* IRQL 27 */
+    0b00000000000000000000000000000000, /* IRQL 28 */
+    0b00000000000000000000000000000000, /* IRQL 29 */
+    0b00000000000000000000000000000000, /* IRQL 30 */
+    0b00000000000000000000000000000000  /* IRQL 31 */
+};
diff --git a/hal/halx86/pc98/pic.c b/hal/halx86/pc98/pic.c
new file mode 100644 (file)
index 0000000..1455953
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * PROJECT:     NEC PC-98 series HAL
+ * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
+ * PURPOSE:     PIC initialization
+ * COPYRIGHT:   Copyright 2020 Dmitry Borisov (di.sean@protonmail.com)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <hal.h>
+
+/* PRIVATE FUNCTIONS *********************************************************/
+
+static VOID
+HalpIoWait(VOID)
+{
+    UCHAR i;
+
+    /*
+     * Give the old PICs enough time to react to commands.
+     * (KeStallExecutionProcessor is not available at this stage)
+     */
+    for (i = 0; i < 6; i++)
+        __outbyte(CPU_IO_o_ARTIC_DELAY, 0);
+}
+
+VOID
+NTAPI
+HalpInitializeLegacyPICs(VOID)
+{
+    I8259_ICW1 Icw1;
+    I8259_ICW2 Icw2;
+    I8259_ICW3 Icw3;
+    I8259_ICW4 Icw4;
+
+    ASSERT(!(__readeflags() & EFLAGS_INTERRUPT_MASK));
+
+    /* Initialize ICW1 for master, interval 8, edge-triggered mode with ICW4 */
+    Icw1.NeedIcw4 = TRUE;
+    Icw1.OperatingMode = Cascade;
+    Icw1.Interval = Interval8;
+    Icw1.InterruptMode = EdgeTriggered;
+    Icw1.Init = TRUE;
+    Icw1.InterruptVectorAddress = 0;
+    __outbyte(PIC1_CONTROL_PORT, Icw1.Bits);
+    HalpIoWait();
+
+    /* ICW2 - interrupt vector offset */
+    Icw2.Bits = PRIMARY_VECTOR_BASE;
+    __outbyte(PIC1_DATA_PORT, Icw2.Bits);
+    HalpIoWait();
+
+    /* Connect slave to cascade IRQ */
+    Icw3.Bits = 0;
+    Icw3.SlaveIrq7 = TRUE;
+    __outbyte(PIC1_DATA_PORT, Icw3.Bits);
+    HalpIoWait();
+
+    /* Enable 8086 mode, non-automatic EOI, buffered mode, special fully nested mode */
+    Icw4.SystemMode = New8086Mode;
+    Icw4.EoiMode = NormalEoi;
+    Icw4.BufferedMode = BufferedMaster;
+    Icw4.SpecialFullyNestedMode = TRUE;
+    Icw4.Reserved = 0;
+    __outbyte(PIC1_DATA_PORT, Icw4.Bits);
+    HalpIoWait();
+
+    /* Mask all interrupts */
+    __outbyte(PIC1_DATA_PORT, 0xFF);
+    HalpIoWait();
+
+    /* Initialize ICW1 for slave, interval 8, edge-triggered mode with ICW4 */
+    Icw1.NeedIcw4 = TRUE;
+    Icw1.InterruptMode = EdgeTriggered;
+    Icw1.OperatingMode = Cascade;
+    Icw1.Interval = Interval8;
+    Icw1.Init = TRUE;
+    Icw1.InterruptVectorAddress = 0; /* This is only used in MCS80/85 mode */
+    __outbyte(PIC2_CONTROL_PORT, Icw1.Bits);
+    HalpIoWait();
+
+    /* Set interrupt vector base */
+    Icw2.Bits = PRIMARY_VECTOR_BASE + 8;
+    __outbyte(PIC2_DATA_PORT, Icw2.Bits);
+    HalpIoWait();
+
+    /* Slave ID */
+    Icw3.Bits = 0;
+    Icw3.SlaveId = PIC_CASCADE_IRQ;
+    __outbyte(PIC2_DATA_PORT, Icw3.Bits);
+    HalpIoWait();
+
+    /* Enable 8086 mode, non-automatic EOI, buffered mode, non special fully nested mode */
+    Icw4.SystemMode = New8086Mode;
+    Icw4.EoiMode = NormalEoi;
+    Icw4.BufferedMode = BufferedSlave;
+    Icw4.SpecialFullyNestedMode = FALSE;
+    Icw4.Reserved = 0;
+    __outbyte(PIC2_DATA_PORT, Icw4.Bits);
+    HalpIoWait();
+
+    /* Mask all interrupts */
+    __outbyte(PIC2_DATA_PORT, 0xFF);
+    HalpIoWait();
+}
diff --git a/hal/halx86/pc98/profil.c b/hal/halx86/pc98/profil.c
new file mode 100644 (file)
index 0000000..6f0ab45
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * PROJECT:     NEC PC-98 series HAL
+ * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
+ * PURPOSE:     System Profiling
+ * COPYRIGHT:   Copyright 2020 Dmitry Borisov (di.sean@protonmail.com)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <hal.h>
+
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS *******************************************************************/
+
+BOOLEAN HalpProfilingStopped = TRUE;
+UCHAR HalpProfileRate = 3;
+
+/* FUNCTIONS *****************************************************************/
+
+VOID
+NTAPI
+HalStopProfileInterrupt(
+    _In_ KPROFILE_SOURCE ProfileSource)
+{
+    UNREFERENCED_PARAMETER(ProfileSource);
+
+    HalpAcquireCmosSpinLock();
+
+    /* Clear the interrupt flag */
+    (VOID)__inbyte(RTC_IO_i_INTERRUPT_RESET);
+
+    HalpProfilingStopped = TRUE;
+
+    HalpReleaseCmosSpinLock();
+}
+
+VOID
+NTAPI
+HalStartProfileInterrupt(
+    _In_ KPROFILE_SOURCE ProfileSource)
+{
+    UNREFERENCED_PARAMETER(ProfileSource);
+
+    HalpProfilingStopped = FALSE;
+
+    HalpAcquireCmosSpinLock();
+
+    /* Configure the clock divisor for generating periodic interrupts */
+    __outbyte(RTC_IO_o_INT_CLOCK_DIVISOR, HalpProfileRate | 0x80);
+
+    HalpReleaseCmosSpinLock();
+}
+
+ULONG_PTR
+NTAPI
+HalSetProfileInterval(
+    _In_ ULONG_PTR Interval)
+{
+    /*
+     * FIXME:
+     * 1) What is the maximum and minimum interrupt frequency for the RTC?
+     * 2) Find the maximum possible clock divisor value.
+     */
+    UNIMPLEMENTED;
+
+    /* Update interval */
+    if (!HalpProfilingStopped)
+       HalStartProfileInterrupt(0);
+
+    /* For now... */
+    return Interval;
+}
diff --git a/hal/halx86/pc98/reboot.c b/hal/halx86/pc98/reboot.c
new file mode 100644 (file)
index 0000000..d26fef2
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * PROJECT:     NEC PC-98 series HAL
+ * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
+ * PURPOSE:     Reboot routine
+ * COPYRIGHT:   Copyright 2020 Dmitry Borisov (di.sean@protonmail.com)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <hal.h>
+
+#define NDEBUG
+#include <debug.h>
+
+/* PRIVATE FUNCTIONS *********************************************************/
+
+static VOID
+DECLSPEC_NORETURN
+NTAPI
+HalpFreezeSystem(VOID)
+{
+    HaliHaltSystem();
+
+    while (TRUE)
+        NOTHING;
+}
+
+VOID
+NTAPI
+HalpReboot(VOID)
+{
+    /* Disable interrupts */
+    _disable();
+
+    /* Flush write buffers */
+    KeFlushWriteBuffer();
+
+    /* Send the reset command */
+    WRITE_PORT_UCHAR((PUCHAR)PPI_IO_o_CONTROL, PPI_SHUTDOWN_0_ENABLE);
+    WRITE_PORT_UCHAR((PUCHAR)PPI_IO_o_CONTROL, PPI_SHUTDOWN_1_ENABLE);
+    WRITE_PORT_UCHAR((PUCHAR)CPU_IO_o_RESET, 0);
+
+    /* Halt the CPU */
+    __halt();
+}
+
+/* PUBLIC FUNCTIONS **********************************************************/
+
+VOID
+NTAPI
+HalReturnToFirmware(
+    _In_ FIRMWARE_REENTRY Action)
+{
+    switch (Action)
+    {
+        case HalPowerDownRoutine:
+            HalpFreezeSystem();
+
+        case HalHaltRoutine:
+        case HalRebootRoutine:
+#ifndef _MINIHAL_
+            /* Acquire the display */
+            InbvAcquireDisplayOwnership();
+#endif
+
+            /* Call the internal reboot function */
+            HalpReboot();
+
+        /* Anything else */
+        default:
+            /* Print message and break */
+            DbgPrint("HalReturnToFirmware called!\n");
+            DbgBreakPoint();
+    }
+}
index 40312d2..bd5f15f 100644 (file)
@@ -9,6 +9,7 @@ list(APPEND HAL_PIC_SOURCE
     generic/profil.c
     generic/timer.c
     up/halinit_up.c
+    up/irql.c
     up/pic.c)
 
 add_asm_files(lib_hal_pic_asm ${HAL_PIC_ASM_SOURCE})
index db65cd4..69c6cce 100644 (file)
@@ -1,16 +1,14 @@
 /*
- * COPYRIGHT:     See COPYING in the top level directory
- * PROJECT:       ReactOS kernel
- * FILE:          hal/halx86/up/halinit_up.c
- * PURPOSE:       Initialize the x86 hal
- * PROGRAMMER:    David Welch (welch@cwcom.net)
- * UPDATE HISTORY:
- *              11/06/98: Created
+ * PROJECT:     ReactOS Hardware Abstraction Layer
+ * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
+ * PURPOSE:     Initialize the x86 HAL
+ * COPYRIGHT:   Copyright 1998 David Welch (welch@cwcom.net)
  */
 
 /* INCLUDES *****************************************************************/
 
 #include <hal.h>
+
 #define NDEBUG
 #include <debug.h>
 
@@ -27,7 +25,7 @@ HalpInitProcessor(
     IN PLOADER_PARAMETER_BLOCK LoaderBlock)
 {
     /* Set default IDR */
-    KeGetPcr()->IDR = 0xFFFFFFFB;
+    KeGetPcr()->IDR = 0xFFFFFFFF & ~(1 << PIC_CASCADE_IRQ);
 }
 
 VOID
@@ -39,18 +37,18 @@ HalpInitPhase0(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
 VOID
 HalpInitPhase1(VOID)
 {
-        /* Enable IRQ 0 */
+        /* Enable timer interrupt handler */
         HalpEnableInterruptHandler(IDT_DEVICE,
                                    0,
-                                   PRIMARY_VECTOR_BASE,
+                                   PRIMARY_VECTOR_BASE + PIC_TIMER_IRQ,
                                    CLOCK2_LEVEL,
                                    HalpClockInterrupt,
                                    Latched);
 
-        /* Enable IRQ 8 */
+        /* Enable RTC interrupt handler */
         HalpEnableInterruptHandler(IDT_DEVICE,
                                    0,
-                                   PRIMARY_VECTOR_BASE + 8,
+                                   PRIMARY_VECTOR_BASE + PIC_RTC_IRQ,
                                    PROFILE_LEVEL,
                                    HalpProfileInterrupt,
                                    Latched);
diff --git a/hal/halx86/up/irql.c b/hal/halx86/up/irql.c
new file mode 100644 (file)
index 0000000..fee6008
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * PROJECT:         ReactOS Hardware Abstraction Layer
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
+ * PURPOSE:         IRQL mapping
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <hal.h>
+
+/* GLOBALS ********************************************************************/
+
+/* This table contains the static x86 PIC mapping between IRQLs and IRQs */
+ULONG KiI8259MaskTable[32] =
+{
+    /*
+     * It Device IRQLs only start at 4 or higher, so these are just software
+     * IRQLs that don't really change anything on the hardware
+     */
+    0b00000000000000000000000000000000, /* IRQL 0 */
+    0b00000000000000000000000000000000, /* IRQL 1 */
+    0b00000000000000000000000000000000, /* IRQL 2 */
+    0b00000000000000000000000000000000, /* IRQL 3 */
+
+    /*
+     * These next IRQLs are actually useless from the PIC perspective, because
+     * with only 2 PICs, the mask you can send them is only 8 bits each, for 16
+     * bits total, so these IRQLs are masking off a phantom PIC.
+     */
+    0b11111111100000000000000000000000, /* IRQL 4 */
+    0b11111111110000000000000000000000, /* IRQL 5 */
+    0b11111111111000000000000000000000, /* IRQL 6 */
+    0b11111111111100000000000000000000, /* IRQL 7 */
+    0b11111111111110000000000000000000, /* IRQL 8 */
+    0b11111111111111000000000000000000, /* IRQL 9 */
+    0b11111111111111100000000000000000, /* IRQL 10 */
+    0b11111111111111110000000000000000, /* IRQL 11 */
+
+    /*
+     * Okay, now we're finally starting to mask off IRQs on the slave PIC, from
+     * IRQ15 to IRQ8. This means the higher-level IRQs get less priority in the
+     * IRQL sense.
+     */
+    0b11111111111111111000000000000000, /* IRQL 12 */
+    0b11111111111111111100000000000000, /* IRQL 13 */
+    0b11111111111111111110000000000000, /* IRQL 14 */
+    0b11111111111111111111000000000000, /* IRQL 15 */
+    0b11111111111111111111100000000000, /* IRQL 16 */
+    0b11111111111111111111110000000000, /* IRQL 17 */
+    0b11111111111111111111111000000000, /* IRQL 18 */
+    0b11111111111111111111111000000000, /* IRQL 19 */
+
+    /*
+     * Now we mask off the IRQs on the master. Notice the 0 "droplet"? You might
+     * have also seen that IRQL 18 and 19 are essentially equal as far as the
+     * PIC is concerned. That bit is actually IRQ8, which happens to be the RTC.
+     * The RTC will keep firing as long as we don't reach PROFILE_LEVEL which
+     * actually kills it. The RTC clock (unlike the system clock) is used by the
+     * profiling APIs in the HAL, so that explains the logic.
+     */
+    0b11111111111111111111111010000000, /* IRQL 20 */
+    0b11111111111111111111111011000000, /* IRQL 21 */
+    0b11111111111111111111111011100000, /* IRQL 22 */
+    0b11111111111111111111111011110000, /* IRQL 23 */
+    0b11111111111111111111111011111000, /* IRQL 24 */
+    0b11111111111111111111111011111000, /* IRQL 25 */
+    0b11111111111111111111111011111010, /* IRQL 26 */
+    0b11111111111111111111111111111010, /* IRQL 27 */
+
+    /*
+     * IRQL 24 and 25 are actually identical, so IRQL 28 is actually the last
+     * IRQL to modify a bit on the master PIC. It happens to modify the very
+     * last of the IRQs, IRQ0, which corresponds to the system clock interval
+     * timer that keeps track of time (the Windows heartbeat). We only want to
+     * turn this off at a high-enough IRQL, which is why IRQLs 24 and 25 are the
+     * same to give this guy a chance to come up higher. Note that IRQL 28 is
+     * called CLOCK2_LEVEL, which explains the usage we just explained.
+     */
+    0b11111111111111111111111111111011, /* IRQL 28 */
+
+    /*
+     * We have finished off with the PIC so there's nothing left to mask at the
+     * level of these IRQLs, making them only logical IRQLs on x86 machines.
+     * Note that we have another 0 "droplet" you might've caught since IRQL 26.
+     * In this case, it's the 2nd bit that never gets turned off, which is IRQ2,
+     * the cascade IRQ that we use to bridge the slave PIC with the master PIC.
+     * We never want to turn it off, so no matter the IRQL, it will be set to 0.
+     */
+    0b11111111111111111111111111111011, /* IRQL 29 */
+    0b11111111111111111111111111111011, /* IRQL 30 */
+    0b11111111111111111111111111111011  /* IRQL 31 */
+};
+
+/* This table indicates which IRQs, if pending, can preempt a given IRQL level */
+ULONG FindHigherIrqlMask[32] =
+{
+    /*
+     * Software IRQLs, at these levels all hardware interrupts can preempt.
+     * Each higher IRQL simply enables which software IRQL can preempt the
+     * current level.
+     */
+    0b11111111111111111111111111111110, /* IRQL 0 */
+    0b11111111111111111111111111111100, /* IRQL 1 */
+    0b11111111111111111111111111111000, /* IRQL 2 */
+
+    /*
+     * IRQL3 means only hardware IRQLs can now preempt. These last 4 zeros will
+     * then continue throughout the rest of the list, trickling down.
+     */
+    0b11111111111111111111111111110000, /* IRQL 3 */
+
+    /*
+     * Just like in the previous list, these masks don't really mean anything
+     * since we've only got two PICs with 16 possible IRQs total
+     */
+    0b00000111111111111111111111110000, /* IRQL 4 */
+    0b00000011111111111111111111110000, /* IRQL 5 */
+    0b00000001111111111111111111110000, /* IRQL 6 */
+    0b00000000111111111111111111110000, /* IRQL 7 */
+    0b00000000011111111111111111110000, /* IRQL 8 */
+    0b00000000001111111111111111110000, /* IRQL 9 */
+    0b00000000000111111111111111110000, /* IRQL 10 */
+
+    /*
+     * Now we start progressivly limiting which slave PIC interrupts have the
+     * right to preempt us at each level.
+     */
+    0b00000000000011111111111111110000, /* IRQL 11 */
+    0b00000000000001111111111111110000, /* IRQL 12 */
+    0b00000000000000111111111111110000, /* IRQL 13 */
+    0b00000000000000011111111111110000, /* IRQL 14 */
+    0b00000000000000001111111111110000, /* IRQL 15 */
+    0b00000000000000000111111111110000, /* IRQL 16 */
+    0b00000000000000000011111111110000, /* IRQL 17 */
+    0b00000000000000000001111111110000, /* IRQL 18 */
+    0b00000000000000000001111111110000, /* IRQL 19 */
+
+    /*
+     * Also recall from the earlier table that IRQL 18/19 are treated the same
+     * in order to spread the masks better thoughout the 32 IRQLs and to reflect
+     * the fact that some bits will always stay on until much higher IRQLs since
+     * they are system-critical. One such example is the 1 bit that you start to
+     * see trickling down here. This is IRQ8, the RTC timer used for profiling,
+     * so it will always preempt until we reach PROFILE_LEVEL.
+     */
+    0b00000000000000000001011111110000, /* IRQL 20 */
+    0b00000000000000000001001111110000, /* IRQL 21 */
+    0b00000000000000000001000111110000, /* IRQL 22 */
+    0b00000000000000000001000011110000, /* IRQL 23 */
+    0b00000000000000000001000001110000, /* IRQL 24 */
+    0b00000000000000000001000000110000, /* IRQL 25 */
+    0b00000000000000000001000000010000, /* IRQL 26 */
+
+    /* At this point, only the clock (IRQ0) can still preempt... */
+    0b00000000000000000000000000010000, /* IRQL 27 */
+
+    /* And any higher than that there's no relation with hardware PICs anymore */
+    0b00000000000000000000000000000000, /* IRQL 28 */
+    0b00000000000000000000000000000000, /* IRQL 29 */
+    0b00000000000000000000000000000000, /* IRQL 30 */
+    0b00000000000000000000000000000000  /* IRQL 31 */
+};
index 2164d8c..f46a72b 100644 (file)
@@ -1,7 +1,6 @@
 /*
  * PROJECT:         ReactOS HAL
  * LICENSE:         BSD - See COPYING.ARM in the top level directory
- * FILE:            hal/halx86/up/pic.c
  * PURPOSE:         HAL PIC Management and Control Code
  * PROGRAMMERS:     ReactOS Portable Systems Group
  */
@@ -9,6 +8,7 @@
 /* INCLUDES *******************************************************************/
 
 #include <hal.h>
+
 #define NDEBUG
 #include <debug.h>
 
@@ -62,12 +62,20 @@ PHAL_DISMISS_INTERRUPT HalpSpecialDismissTable[16] =
     HalpDismissIrqGeneric,
     HalpDismissIrqGeneric,
     HalpDismissIrq07,
+#if defined(SARCH_PC98)
+    HalpDismissIrq08,
+#else
+    HalpDismissIrqGeneric,
+#endif
     HalpDismissIrqGeneric,
     HalpDismissIrqGeneric,
     HalpDismissIrqGeneric,
     HalpDismissIrqGeneric,
+#if defined(SARCH_PC98)
     HalpDismissIrqGeneric,
+#else
     HalpDismissIrq13,
+#endif
     HalpDismissIrqGeneric,
     HalpDismissIrq15
 };
@@ -86,166 +94,29 @@ PHAL_DISMISS_INTERRUPT HalpSpecialDismissLevelTable[16] =
     HalpDismissIrqLevel,
     HalpDismissIrqLevel,
     HalpDismissIrq07Level,
+#if defined(SARCH_PC98)
+    HalpDismissIrq08Level,
+#else
+    HalpDismissIrqLevel,
+#endif
     HalpDismissIrqLevel,
     HalpDismissIrqLevel,
     HalpDismissIrqLevel,
     HalpDismissIrqLevel,
+#if defined(SARCH_PC98)
     HalpDismissIrqLevel,
+#else
     HalpDismissIrq13Level,
+#endif
     HalpDismissIrqLevel,
     HalpDismissIrq15Level
 };
 
 /* This table contains the static x86 PIC mapping between IRQLs and IRQs */
-ULONG KiI8259MaskTable[32] =
-{
-    /*
-     * It Device IRQLs only start at 4 or higher, so these are just software
-     * IRQLs that don't really change anything on the hardware
-     */
-    0b00000000000000000000000000000000, /* IRQL 0 */
-    0b00000000000000000000000000000000, /* IRQL 1 */
-    0b00000000000000000000000000000000, /* IRQL 2 */
-    0b00000000000000000000000000000000, /* IRQL 3 */
-
-    /*
-     * These next IRQLs are actually useless from the PIC perspective, because
-     * with only 2 PICs, the mask you can send them is only 8 bits each, for 16
-     * bits total, so these IRQLs are masking off a phantom PIC.
-     */
-    0b11111111100000000000000000000000, /* IRQL 4 */
-    0b11111111110000000000000000000000, /* IRQL 5 */
-    0b11111111111000000000000000000000, /* IRQL 6 */
-    0b11111111111100000000000000000000, /* IRQL 7 */
-    0b11111111111110000000000000000000, /* IRQL 8 */
-    0b11111111111111000000000000000000, /* IRQL 9 */
-    0b11111111111111100000000000000000, /* IRQL 10 */
-    0b11111111111111110000000000000000, /* IRQL 11 */
-
-    /*
-     * Okay, now we're finally starting to mask off IRQs on the slave PIC, from
-     * IRQ15 to IRQ8. This means the higher-level IRQs get less priority in the
-     * IRQL sense.
-     */
-    0b11111111111111111000000000000000, /* IRQL 12 */
-    0b11111111111111111100000000000000, /* IRQL 13 */
-    0b11111111111111111110000000000000, /* IRQL 14 */
-    0b11111111111111111111000000000000, /* IRQL 15 */
-    0b11111111111111111111100000000000, /* IRQL 16 */
-    0b11111111111111111111110000000000, /* IRQL 17 */
-    0b11111111111111111111111000000000, /* IRQL 18 */
-    0b11111111111111111111111000000000, /* IRQL 19 */
-
-    /*
-     * Now we mask off the IRQs on the master. Notice the 0 "droplet"? You might
-     * have also seen that IRQL 18 and 19 are essentially equal as far as the
-     * PIC is concerned. That bit is actually IRQ8, which happens to be the RTC.
-     * The RTC will keep firing as long as we don't reach PROFILE_LEVEL which
-     * actually kills it. The RTC clock (unlike the system clock) is used by the
-     * profiling APIs in the HAL, so that explains the logic.
-     */
-    0b11111111111111111111111010000000, /* IRQL 20 */
-    0b11111111111111111111111011000000, /* IRQL 21 */
-    0b11111111111111111111111011100000, /* IRQL 22 */
-    0b11111111111111111111111011110000, /* IRQL 23 */
-    0b11111111111111111111111011111000, /* IRQL 24 */
-    0b11111111111111111111111011111000, /* IRQL 25 */
-    0b11111111111111111111111011111010, /* IRQL 26 */
-    0b11111111111111111111111111111010, /* IRQL 27 */
-
-    /*
-     * IRQL 24 and 25 are actually identical, so IRQL 28 is actually the last
-     * IRQL to modify a bit on the master PIC. It happens to modify the very
-     * last of the IRQs, IRQ0, which corresponds to the system clock interval
-     * timer that keeps track of time (the Windows heartbeat). We only want to
-     * turn this off at a high-enough IRQL, which is why IRQLs 24 and 25 are the
-     * same to give this guy a chance to come up higher. Note that IRQL 28 is
-     * called CLOCK2_LEVEL, which explains the usage we just explained.
-     */
-    0b11111111111111111111111111111011, /* IRQL 28 */
-
-    /*
-     * We have finished off with the PIC so there's nothing left to mask at the
-     * level of these IRQLs, making them only logical IRQLs on x86 machines.
-     * Note that we have another 0 "droplet" you might've caught since IRQL 26.
-     * In this case, it's the 2nd bit that never gets turned off, which is IRQ2,
-     * the cascade IRQ that we use to bridge the slave PIC with the master PIC.
-     * We never want to turn it off, so no matter the IRQL, it will be set to 0.
-     */
-    0b11111111111111111111111111111011, /* IRQL 29 */
-    0b11111111111111111111111111111011, /* IRQL 30 */
-    0b11111111111111111111111111111011  /* IRQL 31 */
-};
+extern ULONG KiI8259MaskTable[32];
 
 /* This table indicates which IRQs, if pending, can preempt a given IRQL level */
-ULONG FindHigherIrqlMask[32] =
-{
-    /*
-     * Software IRQLs, at these levels all hardware interrupts can preempt.
-     * Each higher IRQL simply enables which software IRQL can preempt the
-     * current level.
-     */
-    0b11111111111111111111111111111110, /* IRQL 0 */
-    0b11111111111111111111111111111100, /* IRQL 1 */
-    0b11111111111111111111111111111000, /* IRQL 2 */
-
-    /*
-     * IRQL3 means only hardware IRQLs can now preempt. These last 4 zeros will
-     * then continue throughout the rest of the list, trickling down.
-     */
-    0b11111111111111111111111111110000, /* IRQL 3 */
-
-    /*
-     * Just like in the previous list, these masks don't really mean anything
-     * since we've only got two PICs with 16 possible IRQs total
-     */
-    0b00000111111111111111111111110000, /* IRQL 4 */
-    0b00000011111111111111111111110000, /* IRQL 5 */
-    0b00000001111111111111111111110000, /* IRQL 6 */
-    0b00000000111111111111111111110000, /* IRQL 7 */
-    0b00000000011111111111111111110000, /* IRQL 8 */
-    0b00000000001111111111111111110000, /* IRQL 9 */
-    0b00000000000111111111111111110000, /* IRQL 10 */
-
-    /*
-     * Now we start progressivly limiting which slave PIC interrupts have the
-     * right to preempt us at each level.
-     */
-    0b00000000000011111111111111110000, /* IRQL 11 */
-    0b00000000000001111111111111110000, /* IRQL 12 */
-    0b00000000000000111111111111110000, /* IRQL 13 */
-    0b00000000000000011111111111110000, /* IRQL 14 */
-    0b00000000000000001111111111110000, /* IRQL 15 */
-    0b00000000000000000111111111110000, /* IRQL 16 */
-    0b00000000000000000011111111110000, /* IRQL 17 */
-    0b00000000000000000001111111110000, /* IRQL 18 */
-    0b00000000000000000001111111110000, /* IRQL 19 */
-
-    /*
-     * Also recall from the earlier table that IRQL 18/19 are treated the same
-     * in order to spread the masks better thoughout the 32 IRQLs and to reflect
-     * the fact that some bits will always stay on until much higher IRQLs since
-     * they are system-critical. One such example is the 1 bit that you start to
-     * see trickling down here. This is IRQ8, the RTC timer used for profiling,
-     * so it will always preempt until we reach PROFILE_LEVEL.
-     */
-    0b00000000000000000001011111110000, /* IRQL 20 */
-    0b00000000000000000001001111110000, /* IRQL 21 */
-    0b00000000000000000001000111110000, /* IRQL 22 */
-    0b00000000000000000001000011110000, /* IRQL 23 */
-    0b00000000000000000001000001110000, /* IRQL 24 */
-    0b00000000000000000001000000110000, /* IRQL 25 */
-    0b00000000000000000001000000010000, /* IRQL 26 */
-
-    /* At this point, only the clock (IRQ0) can still preempt... */
-    0b00000000000000000000000000010000, /* IRQL 27 */
-
-    /* And any higher than that there's no relation with hardware PICs anymore */
-    0b00000000000000000000000000000000, /* IRQL 28 */
-    0b00000000000000000000000000000000, /* IRQL 29 */
-    0b00000000000000000000000000000000, /* IRQL 30 */
-    0b00000000000000000000000000000000  /* IRQL 31 */
-};
+extern ULONG FindHigherIrqlMask[32];
 
 /* Denotes minimum required IRQL before we can process pending SW interrupts */
 KIRQL SWInterruptLookUpTable[8] =
@@ -351,6 +222,7 @@ HalpInitializePICs(IN BOOLEAN EnableInterrupts)
     ULONG EFlags;
     EISA_ELCR Elcr;
     ULONG i, j;
+    BOOLEAN ElcrFound;
 
     /* Save EFlags and disable interrupts */
     EFlags = __readeflags();
@@ -362,9 +234,23 @@ HalpInitializePICs(IN BOOLEAN EnableInterrupts)
     /* Read EISA Edge/Level Register for master and slave */
     Elcr.Bits = (__inbyte(EISA_ELCR_SLAVE) << 8) | __inbyte(EISA_ELCR_MASTER);
 
+#if defined(SARCH_PC98)
+    /* Force defaults when ELCR is not supported */
+    if (Elcr.Bits == 0xFFFF)
+    {
+        Elcr.Master.Irq0Level = 0;
+        Elcr.Master.Irq1Level = 0;
+        Elcr.Master.Irq7Level = 0;
+        Elcr.Slave.Irq8Level = 0;
+    }
+    ElcrFound = TRUE;
+#else
     /* IRQs 0, 1, 2, 8, and 13 are system-reserved and must be edge */
-    if (!(Elcr.Master.Irq0Level) && !(Elcr.Master.Irq1Level) && !(Elcr.Master.Irq2Level) &&
-        !(Elcr.Slave.Irq8Level) && !(Elcr.Slave.Irq13Level))
+    ElcrFound = (!(Elcr.Master.Irq0Level) && !(Elcr.Master.Irq1Level) && !(Elcr.Master.Irq2Level) &&
+                 !(Elcr.Slave.Irq8Level) && !(Elcr.Slave.Irq13Level));
+#endif
+
+    if (ElcrFound)
     {
         /* ELCR is as it's supposed to be, save it */
         HalpEisaELCR = Elcr.Bits;
@@ -383,10 +269,10 @@ HalpInitializePICs(IN BOOLEAN EnableInterrupts)
         }
     }
 
-    /* Register IRQ 2 */
+    /* Report cascade IRQ usage */
     HalpRegisterVector(IDT_INTERNAL,
-                       PRIMARY_VECTOR_BASE + 2,
-                       PRIMARY_VECTOR_BASE + 2,
+                       PRIMARY_VECTOR_BASE + PIC_CASCADE_IRQ,
+                       PRIMARY_VECTOR_BASE + PIC_CASCADE_IRQ,
                        HIGH_LEVEL);
 
     /* Restore interrupt state */
@@ -690,16 +576,40 @@ _HalpDismissIrqGeneric(IN KIRQL Irql,
         /* Check which PIC needs the EOI */
         if (Irq >= 8)
         {
+#if defined(SARCH_PC98)
+            I8259_OCW3 Ocw3;
+            I8259_ISR Isr;
+
+            /* Send the EOI for the IRQ */
+            __outbyte(PIC2_CONTROL_PORT, Ocw2.Bits | ((Irq - 8) & 0xFF));
+
+            /* Request the ISR */
+            Ocw3.Bits = 0;
+            Ocw3.Sbo = 1;
+            Ocw3.ReadRequest = ReadIsr;
+            __outbyte(PIC2_CONTROL_PORT, Ocw3.Bits);
+
+            /* Read the ISR */
+            Isr.Bits = __inbyte(PIC2_CONTROL_PORT);
+
+            /* Check if the interrupt serviced was the only one from the slave PIC */
+            if (Isr.Bits == 0)
+            {
+                /* If ISR is empty, send the EOI for cascade IRQ on the master PIC */
+                __outbyte(PIC1_CONTROL_PORT, Ocw2.Bits | PIC_CASCADE_IRQ);
+            }
+#else
             /* Send the EOI for the IRQ */
             __outbyte(PIC2_CONTROL_PORT, Ocw2.Bits | ((Irq - 8) & 0xFF));
 
-            /* Send the EOI for IRQ2 on the master because this was cascaded */
-            __outbyte(PIC1_CONTROL_PORT, Ocw2.Bits | 2);
+            /* Send the EOI for cascade IRQ on the master PIC */
+            __outbyte(PIC1_CONTROL_PORT, Ocw2.Bits | PIC_CASCADE_IRQ);
+#endif
         }
         else
         {
             /* Send the EOI for the IRQ */
-            __outbyte(PIC1_CONTROL_PORT, Ocw2.Bits | (Irq &0xFF));
+            __outbyte(PIC1_CONTROL_PORT, Ocw2.Bits | (Irq & 0xFF));
         }
 
         /* Enable interrupts and return success */
@@ -751,10 +661,10 @@ HalpDismissIrq15(IN KIRQL Irql,
     /* Is IRQ15 really active (this is IR7) */
     if (Isr.Irq7 == FALSE)
     {
-        /* It isn't, so we have to EOI IRQ2 because this was cascaded */
+        /* It isn't, so we have to EOI cascade IRQ */
         Ocw2.Bits = 0;
         Ocw2.EoiMode = SpecificEoi;
-        __outbyte(PIC1_CONTROL_PORT, Ocw2.Bits | 2);
+        __outbyte(PIC1_CONTROL_PORT, Ocw2.Bits | PIC_CASCADE_IRQ);
 
         /* And now fail since this was spurious */
         return FALSE;
@@ -764,7 +674,6 @@ HalpDismissIrq15(IN KIRQL Irql,
     return _HalpDismissIrqGeneric(Irql, Irq, OldIrql);
 }
 
-
 BOOLEAN
 NTAPI
 HalpDismissIrq13(IN KIRQL Irql,
@@ -778,6 +687,22 @@ HalpDismissIrq13(IN KIRQL Irql,
     return _HalpDismissIrqGeneric(Irql, Irq, OldIrql);
 }
 
+#if defined(SARCH_PC98)
+BOOLEAN
+NTAPI
+HalpDismissIrq08(
+    _In_ KIRQL Irql,
+    _In_ ULONG Irq,
+    _Out_ PKIRQL OldIrql)
+{
+    /* Clear the FPU busy latch */
+    __outbyte(CPU_IO_o_FPU_BUSY_LATCH, 0);
+
+    /* Do normal interrupt dismiss */
+    return _HalpDismissIrqGeneric(Irql, Irq, OldIrql);
+}
+#endif
+
 BOOLEAN
 NTAPI
 HalpDismissIrq07(IN KIRQL Irql,
@@ -834,11 +759,35 @@ _HalpDismissIrqLevel(IN KIRQL Irql,
     /* Check which PIC needs the EOI */
     if (Irq >= 8)
     {
+#if defined(SARCH_PC98)
+        I8259_OCW3 Ocw3;
+        I8259_ISR Isr;
+
         /* Send the EOI for the IRQ */
         __outbyte(PIC2_CONTROL_PORT, Ocw2.Bits | ((Irq - 8) & 0xFF));
 
-        /* Send the EOI for IRQ2 on the master because this was cascaded */
-        __outbyte(PIC1_CONTROL_PORT, Ocw2.Bits | 2);
+        /* Request the ISR */
+        Ocw3.Bits = 0;
+        Ocw3.Sbo = 1;
+        Ocw3.ReadRequest = ReadIsr;
+        __outbyte(PIC2_CONTROL_PORT, Ocw3.Bits);
+
+        /* Read the ISR */
+        Isr.Bits = __inbyte(PIC2_CONTROL_PORT);
+
+        /* Check if the interrupt serviced was the only one from the slave PIC */
+        if (Isr.Bits == 0)
+        {
+            /* If ISR is empty, send the EOI for cascade IRQ on the master PIC */
+            __outbyte(PIC1_CONTROL_PORT, Ocw2.Bits | PIC_CASCADE_IRQ);
+        }
+#else
+        /* Send the EOI for the IRQ */
+        __outbyte(PIC2_CONTROL_PORT, Ocw2.Bits | ((Irq - 8) & 0xFF));
+
+        /* Send the EOI for cascade IRQ on the master PIC */
+        __outbyte(PIC1_CONTROL_PORT, Ocw2.Bits | PIC_CASCADE_IRQ);
+#endif
     }
     else
     {
@@ -894,10 +843,10 @@ HalpDismissIrq15Level(IN KIRQL Irql,
     /* Is IRQ15 really active (this is IR7) */
     if (Isr.Irq7 == FALSE)
     {
-        /* It isn't, so we have to EOI IRQ2 because this was cascaded */
+        /* It isn't, so we have to EOI cascade IRQ */
         Ocw2.Bits = 0;
         Ocw2.EoiMode = SpecificEoi;
-        __outbyte(PIC1_CONTROL_PORT, Ocw2.Bits | 2);
+        __outbyte(PIC1_CONTROL_PORT, Ocw2.Bits | PIC_CASCADE_IRQ);
 
         /* And now fail since this was spurious */
         return FALSE;
@@ -920,6 +869,22 @@ HalpDismissIrq13Level(IN KIRQL Irql,
     return _HalpDismissIrqLevel(Irql, Irq, OldIrql);
 }
 
+#if defined(SARCH_PC98)
+BOOLEAN
+NTAPI
+HalpDismissIrq08Level(
+    _In_ KIRQL Irql,
+    _In_ ULONG Irq,
+    _Out_ PKIRQL OldIrql)
+{
+    /* Clear the FPU busy latch */
+    __outbyte(CPU_IO_o_FPU_BUSY_LATCH, 0);
+
+    /* Do normal interrupt dismiss */
+    return _HalpDismissIrqLevel(Irql, Irq, OldIrql);
+}
+#endif
+
 BOOLEAN
 NTAPI
 HalpDismissIrq07Level(IN KIRQL Irql,
@@ -1268,7 +1233,7 @@ HalpDispatchInterrupt2(VOID)
     return NULL;
 }
 
-#else
+#else /* _MINIHAL_ */
 
 KIRQL
 NTAPI
@@ -1292,4 +1257,4 @@ KfRaiseIrql(
     return NewIrql;
 }
 
-#endif
+#endif /* !_MINIHAL_ */
index 98f1d1d..6b12168 100644 (file)
@@ -14,6 +14,7 @@ list(APPEND HAL_XBOX_SOURCE
     generic/halinit.c
     generic/memory.c
     generic/misc.c
+    generic/nmi.c
     generic/pic.c
     generic/sysinfo.c
     generic/usage.c
@@ -35,16 +36,14 @@ list(APPEND HAL_XBOX_SOURCE
     xbox/part_xbox.c
     xbox/halinit_xbox.c
     xbox/reboot.c
+    up/irql.c
     up/pic.c)
 
 add_asm_files(lib_hal_xbox_asm ${HAL_XBOX_ASM_SOURCE})
 add_object_library(lib_hal_xbox ${HAL_XBOX_SOURCE} ${lib_hal_xbox_asm})
-if(NOT SARCH STREQUAL "xbox")
-    target_compile_definitions(lib_hal_xbox PRIVATE SARCH_XBOX)
-endif()
 add_dependencies(lib_hal_xbox bugcodes xdk asm)
 #add_pch(lib_hal_xbox xbox/halxbox.h)
 
 if(MSVC)
-    target_link_libraries(lib_hal_xbox lib_hal_generic)
+    target_link_libraries(lib_hal_xbox)
 endif()
index 9069c5d..51e0cb0 100644 (file)
@@ -1,11 +1,8 @@
 /*
- * COPYRIGHT:     See COPYING in the top level directory
- * PROJECT:       ReactOS kernel
- * FILE:          hal/halx86/xbox/halinit_xbox.c
- * PURPOSE:       Initialize the x86 hal
- * PROGRAMMER:    David Welch (welch@cwcom.net)
- * UPDATE HISTORY:
- *              11/06/98: Created
+ * PROJECT:     Xbox HAL
+ * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
+ * PURPOSE:     Initialize the x86 HAL
+ * COPYRIGHT:   Copyright 1998 David Welch (welch@cwcom.net)
  */
 
 /* INCLUDES *****************************************************************/
@@ -28,7 +25,7 @@ HalpInitProcessor(
     IN PLOADER_PARAMETER_BLOCK LoaderBlock)
 {
     /* Set default IDR */
-    KeGetPcr()->IDR = 0xFFFFFFFB;
+    KeGetPcr()->IDR = 0xFFFFFFFF & ~(1 << PIC_CASCADE_IRQ);
 }
 
 VOID
@@ -41,18 +38,18 @@ HalpInitPhase0(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
 VOID
 HalpInitPhase1(VOID)
 {
-    /* Enable IRQ 0 */
+    /* Enable timer interrupt handler */
     HalpEnableInterruptHandler(IDT_DEVICE,
                                0,
-                               PRIMARY_VECTOR_BASE,
+                               PRIMARY_VECTOR_BASE + PIC_TIMER_IRQ,
                                CLOCK2_LEVEL,
                                HalpClockInterrupt,
                                Latched);
 
-    /* Enable IRQ 8 */
+    /* Enable RTC interrupt handler */
     HalpEnableInterruptHandler(IDT_DEVICE,
                                0,
-                               PRIMARY_VECTOR_BASE + 8,
+                               PRIMARY_VECTOR_BASE + PIC_RTC_IRQ,
                                PROFILE_LEVEL,
                                HalpProfileInterrupt,
                                Latched);
index 9ae5318..8049fdd 100644 (file)
@@ -24,6 +24,7 @@ HKR, , Icon,           0, "-27"
 [Manufacturer]
 %GenericMfg% = GenericMfg
 %MsftMfg% = MsftMfg
+%NecMfg% = NecMfg
 
 [GenericMfg]
 %acpipic_up.DeviceDesc% = NO_DRV,acpipic_up
@@ -32,6 +33,9 @@ HKR, , Icon,           0, "-27"
 [MsftMfg]
 %xbox.DeviceDesc% = NO_DRV,xbox
 
+[NecMfg]
+%pc98_up.DeviceDesc% = NO_DRV,pc98_up
+
 ;------------------------------ NO DRIVER -----------------------------
 
 [NO_DRV]
@@ -53,6 +57,9 @@ e_isa_up.DeviceDesc = "Standard Uniprocessor PC"
 MsftMfg = "Microsoft Corporation"
 xbox.DeviceDesc = "Original Xbox (x86 based)"
 
+NecMfg = "NEC"
+pc98_up.DeviceDesc = "Uniprocessor NEC PC-98"
+
 [Strings.0405]
 ComputerClassName = "Počítač"
 GenericMfg = "(Obecné počítače)"
@@ -62,6 +69,8 @@ e_isa_up.DeviceDesc = "Standardní jednoprocesorové PC"
 MsftMfg = "Microsoft Corporation"
 xbox.DeviceDesc = "Original Xbox (x86 based)"
 
+pc98_up.DeviceDesc = "Uniprocessor NEC PC-98"
+
 [Strings.0a]
 ReactOS = "Equipo de ReactOS"
 
@@ -74,6 +83,8 @@ e_isa_up.DeviceDesc = "PC con uniprocesador estándar"
 MsftMfg = "Microsoft Corporation"
 xbox.DeviceDesc = "Original Xbox (x86 based)"
 
+pc98_up.DeviceDesc = "Uniprocessor NEC PC-98"
+
 [Strings.0415]
 ReactOS = "Zespół ReactOS"
 
@@ -86,6 +97,8 @@ e_isa_up.DeviceDesc = "Standardowy komputer PC"
 MsftMfg = "Microsoft Corporation"
 xbox.DeviceDesc = "Original Xbox (x86 based)"
 
+pc98_up.DeviceDesc = "Uniprocessor NEC PC-98"
+
 [Strings.0418]
 ReactOS = "Echipa ReactOS"
 
@@ -98,6 +111,8 @@ e_isa_up.DeviceDesc = "PC uniprocesor standard"
 MsftMfg = "Microsoft Corporation"
 xbox.DeviceDesc = "Original Xbox (x86 based)"
 
+pc98_up.DeviceDesc = "Uniprocessor NEC PC-98"
+
 [Strings.0419]
 ReactOS = "Команда ReactOS"
 
@@ -110,6 +125,8 @@ e_isa_up.DeviceDesc = "Стандартный однопроцессорный 
 MsftMfg = "Корпорация Microsoft"
 xbox.DeviceDesc = "Оригинальный Xbox (на базе x86)"
 
+pc98_up.DeviceDesc = "Однопроцессорный NEC PC-98"
+
 [Strings.041f]
 ReactOS = "ReactOS Takımı"
 
@@ -122,6 +139,8 @@ e_isa_up.DeviceDesc = "Ölçünlü Tek İşlemcili PC"
 MsftMfg = "Microsoft Corporation"
 xbox.DeviceDesc = "Original Xbox (x86 based)"
 
+pc98_up.DeviceDesc = "Uniprocessor NEC PC-98"
+
 [Strings.0422]
 ReactOS = "Команда ReactOS"
 
@@ -134,6 +153,8 @@ e_isa_up.DeviceDesc = "Стандартний однопроцесорний П
 MsftMfg = "Microsoft Corporation"
 xbox.DeviceDesc = "Original Xbox (x86 based)"
 
+pc98_up.DeviceDesc = "Однопроцесорний NEC PC-98"
+
 [Strings.0804]
 GenericMfg = "(通用计算机)"
 acpipic_up.DeviceDesc = "ACPI 单处理器 PC"
@@ -141,3 +162,5 @@ e_isa_up.DeviceDesc = "标准单处理器 PC"
 
 MsftMfg = "Microsoft Corporation"
 xbox.DeviceDesc = "Original Xbox (x86 based)"
+
+pc98_up.DeviceDesc = "Uniprocessor NEC PC-98"
index d5e10a9..e0da151 100644 (file)
@@ -7,13 +7,15 @@
 
 #pragma once
 
-#define CPU_IO_o_RESET          0x0F
+#define CPU_IO_o_RESET          0xF0
 #define CPU_IO_o_A20_UNMASK     0xF2
 
 #define CPU_IO_o_A20_CONTROL    0xF6
     #define CPU_A20_ENABLE          0x02
     #define CPU_A20_DISABLE         0x03
 
+#define CPU_IO_o_FPU_BUSY_LATCH 0xF8
+
 /*
  * ARTIC (A Relative Time Indication Counter) - 24-bit binary up counter
  */
diff --git a/sdk/include/reactos/drivers/pc98/pic.h b/sdk/include/reactos/drivers/pc98/pic.h
new file mode 100644 (file)
index 0000000..d47f7e0
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * PROJECT:     NEC PC-98 series onboard hardware
+ * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
+ * PURPOSE:     Intel 8259A PIC header file
+ * COPYRIGHT:   Copyright 2020 Dmitry Borisov (di.sean@protonmail.com)
+ */
+
+#pragma once
+
+#define PIC1_CONTROL_PORT      0x00
+#define PIC1_DATA_PORT         0x02
+#define PIC2_CONTROL_PORT      0x08
+#define PIC2_DATA_PORT         0x0A
+
+#define PIC_TIMER_IRQ      0
+#define PIC_CASCADE_IRQ    7
+#define PIC_RTC_IRQ        15
+
+/*
+ * Definitions for ICW/OCW Bits
+ */
+typedef enum _I8259_ICW1_OPERATING_MODE
+{
+    Cascade,
+    Single
+} I8259_ICW1_OPERATING_MODE;
+
+typedef enum _I8259_ICW1_INTERRUPT_MODE
+{
+    EdgeTriggered,
+    LevelTriggered
+} I8259_ICW1_INTERRUPT_MODE;
+
+typedef enum _I8259_ICW1_INTERVAL
+{
+    Interval8,
+    Interval4
+} I8259_ICW1_INTERVAL;
+
+typedef enum _I8259_ICW4_SYSTEM_MODE
+{
+    Mcs8085Mode,
+    New8086Mode
+} I8259_ICW4_SYSTEM_MODE;
+
+typedef enum _I8259_ICW4_EOI_MODE
+{
+    NormalEoi,
+    AutomaticEoi
+} I8259_ICW4_EOI_MODE;
+
+typedef enum _I8259_ICW4_BUFFERED_MODE
+{
+    NonBuffered,
+    NonBuffered2,
+    BufferedSlave,
+    BufferedMaster
+} I8259_ICW4_BUFFERED_MODE;
+
+typedef enum _I8259_READ_REQUEST
+{
+    InvalidRequest,
+    InvalidRequest2,
+    ReadIdr,
+    ReadIsr
+} I8259_READ_REQUEST;
+
+typedef enum _I8259_EOI_MODE
+{
+    RotateAutoEoiClear,
+    NonSpecificEoi,
+    InvalidEoiMode,
+    SpecificEoi,
+    RotateAutoEoiSet,
+    RotateNonSpecific,
+    SetPriority,
+    RotateSpecific
+} I8259_EOI_MODE;
+
+/*
+ * Definitions for ICW Registers
+ */
+typedef union _I8259_ICW1
+{
+    struct
+    {
+        UCHAR NeedIcw4:1;
+        UCHAR OperatingMode:1;
+        UCHAR Interval:1;
+        UCHAR InterruptMode:1;
+        UCHAR Init:1;
+        UCHAR InterruptVectorAddress:3;
+    };
+    UCHAR Bits;
+} I8259_ICW1, *PI8259_ICW1;
+
+typedef union _I8259_ICW2
+{
+    struct
+    {
+        UCHAR Sbz:3;
+        UCHAR InterruptVector:5;
+    };
+    UCHAR Bits;
+} I8259_ICW2, *PI8259_ICW2;
+
+typedef union _I8259_ICW3
+{
+    union
+    {
+        struct
+        {
+            UCHAR SlaveIrq0:1;
+            UCHAR SlaveIrq1:1;
+            UCHAR SlaveIrq2:1;
+            UCHAR SlaveIrq3:1;
+            UCHAR SlaveIrq4:1;
+            UCHAR SlaveIrq5:1;
+            UCHAR SlaveIrq6:1;
+            UCHAR SlaveIrq7:1;
+        };
+        struct
+        {
+            UCHAR SlaveId:3;
+            UCHAR Reserved:5;
+        };
+    };
+    UCHAR Bits;
+} I8259_ICW3, *PI8259_ICW3;
+
+typedef union _I8259_ICW4
+{
+    struct
+    {
+        UCHAR SystemMode:1;
+        UCHAR EoiMode:1;
+        UCHAR BufferedMode:2;
+        UCHAR SpecialFullyNestedMode:1;
+        UCHAR Reserved:3;
+    };
+    UCHAR Bits;
+} I8259_ICW4, *PI8259_ICW4;
+
+typedef union _I8259_OCW2
+{
+    struct
+    {
+        UCHAR IrqNumber:3;
+        UCHAR Sbz:2;
+        UCHAR EoiMode:3;
+    };
+    UCHAR Bits;
+} I8259_OCW2, *PI8259_OCW2;
+
+typedef union _I8259_OCW3
+{
+    struct
+    {
+        UCHAR ReadRequest:2;
+        UCHAR PollCommand:1;
+        UCHAR Sbo:1;
+        UCHAR Sbz:1;
+        UCHAR SpecialMaskMode:2;
+        UCHAR Reserved:1;
+    };
+    UCHAR Bits;
+} I8259_OCW3, *PI8259_OCW3;
+
+typedef union _I8259_ISR
+{
+    struct
+    {
+        UCHAR Irq0:1;
+        UCHAR Irq1:1;
+        UCHAR Irq2:1;
+        UCHAR Irq3:1;
+        UCHAR Irq4:1;
+        UCHAR Irq5:1;
+        UCHAR Irq6:1;
+        UCHAR Irq7:1;
+    };
+    UCHAR Bits;
+} I8259_ISR, *PI8259_ISR;
+
+typedef I8259_ISR I8259_IDR, *PI8259_IDR;
+
+/*
+ * NESA Edge/Level Triggered Register
+ */
+#define EISA_ELCR_MASTER       0x98D2
+#define EISA_ELCR_SLAVE        0x98D4
+
+typedef union _EISA_ELCR
+{
+    struct
+    {
+        struct
+        {
+            UCHAR Irq0Level:1;
+            UCHAR Irq1Level:1;
+            UCHAR Irq2Level:1;
+            UCHAR Irq3Level:1;
+            UCHAR Irq4Level:1;
+            UCHAR Irq5Level:1;
+            UCHAR Irq6Level:1;
+            UCHAR Irq7Level:1;
+        } Master;
+        struct
+        {
+            UCHAR Irq8Level:1;
+            UCHAR Irq9Level:1;
+            UCHAR Irq10Level:1;
+            UCHAR Irq11Level:1;
+            UCHAR Irq12Level:1;
+            UCHAR Irq13Level:1;
+            UCHAR Irq14Level:1;
+            UCHAR Irq15Level:1;
+        } Slave;
+    };
+    USHORT Bits;
+} EISA_ELCR, *PEISA_ELCR;
+
+typedef union _PIC_MASK
+{
+    struct
+    {
+        UCHAR Master;
+        UCHAR Slave;
+    };
+    USHORT Both;
+} PIC_MASK, *PPIC_MASK;
diff --git a/sdk/include/reactos/drivers/pc98/rtc.h b/sdk/include/reactos/drivers/pc98/rtc.h
new file mode 100644 (file)
index 0000000..4cc1c91
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * PROJECT:     NEC PC-98 series onboard hardware
+ * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
+ * PURPOSE:     NEC uPD1990A/uPD4990A RTC header file
+ * COPYRIGHT:   Copyright 2020 Dmitry Borisov (di.sean@protonmail.com)
+ */
+
+#pragma once
+
+#define RTC_IO_o_DATA    0x20
+    /* Input terminals */
+    #define RTC_DATA_INPUT                0x20
+    #define RTC_CLOCK                     0x10
+    #define RTC_STROBE                    0x08
+    /* Commands, shift register 40 bit */
+    #define RTC_CMD_REGISTER_HOLD         0x00
+    #define RTC_CMD_REGISTER_SHIFT        0x01
+    #define RTC_CMD_TIME_SET_COUNTER_HOLD 0x02
+    #define RTC_CMD_TIME_READ             0x03
+    #define RTC_CMD_TIMING_PULSE_64_HZ    0x04
+    #define RTC_CMD_TIMING_PULSE_256_HZ   0x05
+    #define RTC_CMD_TIMING_PULSE_2048_HZ  0x06
+    #define RTC_CMD_SERIAL_TRANSFER_MODE  0x07
+    /* Serial data commands, shift register 52 bit (uPD4990A only) */
+    #define RTC_CMD_TIMING_PULSE_4096_HZ  0x07
+    #define RTC_CMD_TIMING_PULSE_1_S_INT  0x08
+    #define RTC_CMD_TIMING_PULSE_10_S_INT 0x09
+    #define RTC_CMD_TIMING_PULSE_30_S_INT 0x0A
+    #define RTC_CMD_TIMING_PULSE_60_S_INT 0x0B
+    #define RTC_CMD_INTERRUPT_RESET       0x0C
+    #define RTC_CMD_INTERRUPT_START       0x0D
+    #define RTC_CMD_INTERRUPT_STOP        0x0E
+    #define RTC_CMD_TEST_MODE             0x0F
+
+#define RTC_IO_o_MODE    0x22
+
+#define RTC_IO_o_INT_CLOCK_DIVISOR    0x128
+    #define RTC_INT_CLOCK_DIVISOR_64      0x00
+    #define RTC_INT_CLOCK_DIVISOR_32      0x01
+    #define RTC_INT_CLOCK_DIVISOR_0       0x02
+    #define RTC_INT_CLOCK_DIVISOR_16      0x03
+
+#define RTC_IO_i_MODE    0x22
+#define RTC_IO_i_INTERRUPT_RESET      0x128
index 8d43951..bff9280 100644 (file)
@@ -8,7 +8,12 @@
 #pragma once
 
 #define PPI_IO_o_PORT_C     0x35
+
 #define PPI_IO_o_CONTROL    0x37
+    #define PPI_TIMER_1_GATE_TO_SPEAKER      0x06
+    #define PPI_TIMER_1_UNGATE_TO_SPEAKER    0x07
+    #define PPI_SHUTDOWN_1_ENABLE            0x0B
+    #define PPI_SHUTDOWN_0_ENABLE            0x0F
 
 #define PPI_IO_i_PORT_A     0x31
 #define PPI_IO_i_PORT_B     0x33
@@ -64,19 +69,3 @@ typedef union _SYSTEM_CONTROL_PORT_C_REGISTER
     };
     UCHAR Bits;
 } SYSTEM_CONTROL_PORT_C_REGISTER, *PSYSTEM_CONTROL_PORT_C_REGISTER;
-
-typedef union _SYSTEM_CONTROL_PORT_REGISTER
-{
-    struct
-    {
-        UCHAR InterruptEnableRxReady:1;
-        UCHAR InterruptEnableTxEmpty:1;
-        UCHAR InterruptEnableTxReady:1;
-        UCHAR Timer1GateToSpeaker:1;
-        UCHAR Mcke:1;
-        UCHAR Shut1:1;
-        UCHAR PrinterStrobeSignal:1;
-        UCHAR Shut0:1;
-    };
-    UCHAR Bits;
-} SYSTEM_CONTROL_PORT_REGISTER, *PSYSTEM_CONTROL_PORT_REGISTER;