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@reactos.org) @@ -10,8 +9,10 @@ /* INCLUDES *******************************************************************/ #include + #define NDEBUG #include + #include 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@reactos.org) * Eric Kohl @@ -10,6 +9,7 @@ /* INCLUDES ******************************************************************/ #include + #define NDEBUG #include @@ -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 -#include #define NDEBUG #include @@ -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 +#include + +#define NDEBUG +#include + +/* 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@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 ***********************************************************/ 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@reactos.org) */ @@ -9,6 +8,7 @@ /* INCLUDES *******************************************************************/ #include + #define NDEBUG #include @@ -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 +#include +#include +#include +#include +#include +#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 + #define NDEBUG #include @@ -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@protonmail.com) + */ + +/* INCLUDES ******************************************************************/ + +#include + +#define NDEBUG +#include + +/* 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@protonmail.com) + */ + +/* INCLUDES ******************************************************************/ + +#include + +/* 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@protonmail.com) + */ + +/* INCLUDES ******************************************************************/ + +#include + +#define NDEBUG +#include + +#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@protonmail.com) + */ + +/* INCLUDES ******************************************************************/ + +#include + +#define NDEBUG +#include + +/* 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 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@protonmail.com) + */ + +/* INCLUDES *******************************************************************/ + +#include + +/* 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@protonmail.com) + */ + +/* INCLUDES ******************************************************************/ + +#include + +/* 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@protonmail.com) + */ + +/* INCLUDES ******************************************************************/ + +#include + +#define NDEBUG +#include + +/* 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@protonmail.com) + */ + +/* INCLUDES ******************************************************************/ + +#include + +#define NDEBUG +#include + +/* 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@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 + #define NDEBUG #include @@ -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 + +/* 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 + #define NDEBUG #include @@ -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)); - /* 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 { /* 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@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); 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@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@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;