https://git.reactos.org/?p=reactos.git;a=commitdiff;h=b36018ff2655b52833654…
commit b36018ff2655b52833654cc4ed4669079585247a
Author: Dmitry Borisov <di.sean(a)protonmail.com>
AuthorDate: Sat Jul 25 19:31:02 2020 +0600
Commit: GitHub <noreply(a)github.com>
CommitDate: Sat Jul 25 15:31:02 2020 +0200
[HALPC98] Add Hardware Abstraction Layer for NEC PC-98 series (#3002)
---
boot/bootdata/txtsetup.sif | 6 +
hal/halx86/CMakeLists.txt | 13 ++
hal/halx86/generic.cmake | 1 +
hal/halx86/generic/bios.c | 6 +-
hal/halx86/generic/cmos.c | 20 +-
hal/halx86/generic/dma.c | 18 ++
hal/halx86/generic/misc.c | 113 +---------
hal/halx86/generic/nmi.c | 108 ++++++++++
hal/halx86/generic/timer.c | 22 +-
hal/halx86/generic/usage.c | 62 +++++-
hal/halx86/include/bus.h | 8 +-
hal/halx86/include/hal.h | 9 +
hal/halx86/include/halhw.h | 40 ++--
hal/halx86/include/halp.h | 28 +++
hal/halx86/legacy/halpcat.c | 7 +-
hal/halx86/minihal/CMakeLists.txt | 29 ++-
hal/halx86/pc98.cmake | 57 +++++
hal/halx86/pc98/beep.c | 53 +++++
hal/halx86/pc98/clock.c | 75 +++++++
hal/halx86/pc98/cmos.c | 322 +++++++++++++++++++++++++++++
hal/halx86/pc98/delay.c | 39 ++++
hal/halx86/pc98/halpc98.rc | 9 +
hal/halx86/pc98/irql.c | 121 +++++++++++
hal/halx86/pc98/pic.c | 105 ++++++++++
hal/halx86/pc98/profil.c | 74 +++++++
hal/halx86/pc98/reboot.c | 75 +++++++
hal/halx86/pic.cmake | 1 +
hal/halx86/up/halinit_up.c | 22 +-
hal/halx86/up/irql.c | 163 +++++++++++++++
hal/halx86/up/pic.c | 295 ++++++++++++--------------
hal/halx86/xbox.cmake | 7 +-
hal/halx86/xbox/halinit_xbox.c | 21 +-
media/inf/hal.inf | 23 +++
sdk/include/reactos/drivers/pc98/cpu.h | 4 +-
sdk/include/reactos/drivers/pc98/pic.h | 231 +++++++++++++++++++++
sdk/include/reactos/drivers/pc98/rtc.h | 44 ++++
sdk/include/reactos/drivers/pc98/sysport.h | 21 +-
37 files changed, 1880 insertions(+), 372 deletions(-)
diff --git a/boot/bootdata/txtsetup.sif b/boot/bootdata/txtsetup.sif
index f8a80842196..807c8a7f902 100644
--- a/boot/bootdata/txtsetup.sif
+++ b/boot/bootdata/txtsetup.sif
@@ -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
diff --git a/hal/halx86/CMakeLists.txt b/hal/halx86/CMakeLists.txt
index 4dabc83e5b8..c7f1bdaccb5 100644
--- a/hal/halx86/CMakeLists.txt
+++ b/hal/halx86/CMakeLists.txt
@@ -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)
diff --git a/hal/halx86/generic.cmake b/hal/halx86/generic.cmake
index 143f6d18e3a..19eb850164b 100644
--- a/hal/halx86/generic.cmake
+++ b/hal/halx86/generic.cmake
@@ -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
diff --git a/hal/halx86/generic/bios.c b/hal/halx86/generic/bios.c
index 2fe73aa15e5..aac2502a872 100644
--- a/hal/halx86/generic/bios.c
+++ b/hal/halx86/generic/bios.c
@@ -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(a)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;
diff --git a/hal/halx86/generic/cmos.c b/hal/halx86/generic/cmos.c
index 689883bcc56..2703c6a89ff 100644
--- a/hal/halx86/generic/cmos.c
+++ b/hal/halx86/generic/cmos.c
@@ -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(a)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;
diff --git a/hal/halx86/generic/dma.c b/hal/halx86/generic/dma.c
index 39c2efe42a6..d8a8a696319 100644
--- a/hal/halx86/generic/dma.c
+++ b/hal/halx86/generic/dma.c
@@ -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
diff --git a/hal/halx86/generic/misc.c b/hal/halx86/generic/misc.c
index 7e1eb37d7ad..67b8bcf08fd 100644
--- a/hal/halx86/generic/misc.c
+++ b/hal/halx86/generic/misc.c
@@ -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
index 00000000000..3da64f1e1aa
--- /dev/null
+++ b/hal/halx86/generic/nmi.c
@@ -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;
+}
diff --git a/hal/halx86/generic/timer.c b/hal/halx86/generic/timer.c
index c9fe80c16e2..3d5b1b0e521 100644
--- a/hal/halx86/generic/timer.c
+++ b/hal/halx86/generic/timer.c
@@ -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(a)reactos.org)
* Timo Kreuzer (timo.kreuzer(a)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 ***********************************************************/
diff --git a/hal/halx86/generic/usage.c b/hal/halx86/generic/usage.c
index 5f94fee5f59..78ad3c6bf54 100644
--- a/hal/halx86/generic/usage.c
+++ b/hal/halx86/generic/usage.c
@@ -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(a)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 */
-
diff --git a/hal/halx86/include/bus.h b/hal/halx86/include/bus.h
index def39ebf80c..d7af1ea5eee 100644
--- a/hal/halx86/include/bus.h
+++ b/hal/halx86/include/bus.h
@@ -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
diff --git a/hal/halx86/include/hal.h b/hal/halx86/include/hal.h
index 7f632f3de04..860651951c8 100644
--- a/hal/halx86/include/hal.h
+++ b/hal/halx86/include/hal.h
@@ -59,7 +59,16 @@
#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"
diff --git a/hal/halx86/include/halhw.h b/hal/halx86/include/halhw.h
index 6da13728a4f..cf75684f161 100644
--- a/hal/halx86/include/halhw.h
+++ b/hal/halx86/include/halhw.h
@@ -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;
diff --git a/hal/halx86/include/halp.h b/hal/halx86/include/halp.h
index cb6f6e58809..1ab78747e73 100644
--- a/hal/halx86/include/halp.h
+++ b/hal/halx86/include/halp.h
@@ -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
diff --git a/hal/halx86/legacy/halpcat.c b/hal/halx86/legacy/halpcat.c
index c660296d8e8..4b6033e51ee 100644
--- a/hal/halx86/legacy/halpcat.c
+++ b/hal/halx86/legacy/halpcat.c
@@ -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();
}
diff --git a/hal/halx86/minihal/CMakeLists.txt b/hal/halx86/minihal/CMakeLists.txt
index 84bdf8fee25..47708f9247d 100644
--- a/hal/halx86/minihal/CMakeLists.txt
+++ b/hal/halx86/minihal/CMakeLists.txt
@@ -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
index 00000000000..fd51a9851b9
--- /dev/null
+++ b/hal/halx86/pc98.cmake
@@ -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
index 00000000000..2d21e2d3781
--- /dev/null
+++ b/hal/halx86/pc98/beep.c
@@ -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(a)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
index 00000000000..3b6c304c019
--- /dev/null
+++ b/hal/halx86/pc98/clock.c
@@ -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(a)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
index 00000000000..99dd76135fa
--- /dev/null
+++ b/hal/halx86/pc98/cmos.c
@@ -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(a)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
index 00000000000..37ab5776829
--- /dev/null
+++ b/hal/halx86/pc98/delay.c
@@ -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(a)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
index 00000000000..ea88398771d
--- /dev/null
+++ b/hal/halx86/pc98/halpc98.rc
@@ -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
index 00000000000..f14aa73518d
--- /dev/null
+++ b/hal/halx86/pc98/irql.c
@@ -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(a)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
index 00000000000..14559535b6a
--- /dev/null
+++ b/hal/halx86/pc98/pic.c
@@ -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(a)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
index 00000000000..6f0ab45c0ed
--- /dev/null
+++ b/hal/halx86/pc98/profil.c
@@ -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(a)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
index 00000000000..d26fef2d1d2
--- /dev/null
+++ b/hal/halx86/pc98/reboot.c
@@ -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(a)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();
+ }
+}
diff --git a/hal/halx86/pic.cmake b/hal/halx86/pic.cmake
index 40312d2273f..bd5f15f7894 100644
--- a/hal/halx86/pic.cmake
+++ b/hal/halx86/pic.cmake
@@ -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})
diff --git a/hal/halx86/up/halinit_up.c b/hal/halx86/up/halinit_up.c
index db65cd40d65..69c6cce2605 100644
--- a/hal/halx86/up/halinit_up.c
+++ b/hal/halx86/up/halinit_up.c
@@ -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(a)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(a)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
index 00000000000..fee6008884d
--- /dev/null
+++ b/hal/halx86/up/irql.c
@@ -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 */
+};
diff --git a/hal/halx86/up/pic.c b/hal/halx86/up/pic.c
index 2164d8c03b0..f46a72bc80f 100644
--- a/hal/halx86/up/pic.c
+++ b/hal/halx86/up/pic.c
@@ -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_ */
diff --git a/hal/halx86/xbox.cmake b/hal/halx86/xbox.cmake
index 98f1d1d3d8a..6b121689c95 100644
--- a/hal/halx86/xbox.cmake
+++ b/hal/halx86/xbox.cmake
@@ -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()
diff --git a/hal/halx86/xbox/halinit_xbox.c b/hal/halx86/xbox/halinit_xbox.c
index 9069c5d64a2..51e0cb00821 100644
--- a/hal/halx86/xbox/halinit_xbox.c
+++ b/hal/halx86/xbox/halinit_xbox.c
@@ -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(a)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(a)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);
diff --git a/media/inf/hal.inf b/media/inf/hal.inf
index 9ae5318a4f7..8049fddad96 100644
--- a/media/inf/hal.inf
+++ b/media/inf/hal.inf
@@ -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"
diff --git a/sdk/include/reactos/drivers/pc98/cpu.h
b/sdk/include/reactos/drivers/pc98/cpu.h
index d5e10a911c6..e0da151805f 100644
--- a/sdk/include/reactos/drivers/pc98/cpu.h
+++ b/sdk/include/reactos/drivers/pc98/cpu.h
@@ -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
index 00000000000..d47f7e02960
--- /dev/null
+++ b/sdk/include/reactos/drivers/pc98/pic.h
@@ -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(a)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
index 00000000000..4cc1c912e21
--- /dev/null
+++ b/sdk/include/reactos/drivers/pc98/rtc.h
@@ -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(a)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
diff --git a/sdk/include/reactos/drivers/pc98/sysport.h
b/sdk/include/reactos/drivers/pc98/sysport.h
index 8d439517ed8..bff9280b0e6 100644
--- a/sdk/include/reactos/drivers/pc98/sysport.h
+++ b/sdk/include/reactos/drivers/pc98/sysport.h
@@ -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;