[HALPC98] Add Hardware Abstraction Layer for NEC PC-98 series (#3002)

This commit is contained in:
Dmitry Borisov 2020-07-25 19:31:02 +06:00 committed by GitHub
parent 0c222cfe96
commit b36018ff26
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
37 changed files with 1880 additions and 372 deletions

View file

@ -226,6 +226,7 @@ pci_up = "Standard PC Uniprocessor"
acpi_up = "ACPI PC Uniprocessor"
;acpi_mp = "ACPI PC Multiprocessor"
xbox = "Original Xbox (x86 based)"
pc98_up = "Uniprocessor NEC PC-98"
[Computer.NTamd64]
x64_up = "Standard x64 Uniprocessor"
@ -237,6 +238,7 @@ pci_up = "PC UP"
acpi_up = "ACPI UP"
;acpi_mp = "ACPI MP"
xbox = "Xbox"
pc98_up = "NEC PC-98 UP"
[Map.Computer.NTamd64]
x64_up = "ACPI UP"
@ -261,6 +263,10 @@ halacpi.dll = 1,,,,,,,2,,,hal.dll,1,2
ntoskrnl.exe = 1,,,,,,,2,,,,1,2
halxbox.dll = 1,,,,,,,2,,,hal.dll,1,2
[Files.pc98_up]
ntoskrnl.exe = 1,,,,,,,2,,,,1,2
halpc98.dll = 1,,,,,,,2,,,hal.dll,1,2
[Files.x64_up]
ntoskrnl.exe = 1,,,,,,,2,,,,1,2
hal.dll = 1,,,,,,,2,,,,1,2

View file

@ -32,6 +32,14 @@ function(add_hal _halname)
target_link_libraries(${_halname} ${_haldata_LIBS})
endif()
if(${_halname} STREQUAL "halpc98")
target_compile_definitions(lib_hal_pc98 PRIVATE SARCH_PC98)
endif()
if(${_halname} STREQUAL "halxbox")
target_compile_definitions(lib_hal_xbox PRIVATE SARCH_XBOX)
endif()
if(${_halname} STREQUAL "hal")
target_link_libraries(${_halname} libcntpr arbiter)
else()
@ -61,14 +69,19 @@ if(ARCH STREQUAL "i386")
include(up.cmake)
include(pic.cmake)
include(xbox.cmake)
include(pc98.cmake)
add_subdirectory(minihal)
remove_definitions(-DSARCH_XBOX)
remove_definitions(-DSARCH_PC98)
# hal
add_hal(hal SOURCES up/halup.rc COMPONENTS generic legacy up pic)
add_hal(halacpi SOURCES acpi/halacpi.rc COMPONENTS generic acpi up pic)
add_hal(halapic SOURCES acpi/halacpi.rc COMPONENTS generic legacy up apic)
add_hal(halaacpi SOURCES acpi/halacpi.rc COMPONENTS generic acpi up apic)
add_hal(halxbox SOURCES xbox/halxbox.rc COMPONENTS xbox up)
add_hal(halpc98 SOURCES pc98/halpc98.rc COMPONENTS pc98 up)
#add_hal(halmps SOURCES up/halup.rc COMPONENTS generic legacy smp pic)
#add_hal(halmacpi SOURCES acpi/halacpi.rc COMPONENTS generic acpi smp pic)

View file

@ -8,6 +8,7 @@ list(APPEND HAL_GENERIC_SOURCE
generic/halinit.c
generic/memory.c
generic/misc.c
generic/nmi.c
generic/pic.c
generic/reboot.c
generic/sysinfo.c

View file

@ -1,7 +1,6 @@
/*
* PROJECT: ReactOS Hardware Abstraction Layer (HAL)
* LICENSE: BSD - See COPYING.ARM in the top level directory
* FILE: hal/halx86/generic/bios.c
* PURPOSE: BIOS Access Routines
* PROGRAMMERS: ReactOS Portable Systems Group
* Alex Ionescu (alex.ionescu@reactos.org)
@ -10,8 +9,10 @@
/* INCLUDES *******************************************************************/
#include <hal.h>
#define NDEBUG
#include <debug.h>
#include <setjmp.h>
void __cdecl HalpTrap0D();
@ -645,7 +646,8 @@ BOOLEAN
NTAPI
HalpBiosDisplayReset(VOID)
{
#ifdef SARCH_XBOX
#if defined(SARCH_XBOX) || defined(SARCH_PC98)
/* There is no VGA BIOS on these machine types */
return FALSE;
#else
ULONG Flags;

View file

@ -1,7 +1,6 @@
/*
* PROJECT: ReactOS HAL
* LICENSE: GPL - See COPYING in the top level directory
* FILE: hal/halx86/generic/cmos.c
* PURPOSE: CMOS Access Routines (Real Time Clock and LastKnownGood)
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
* Eric Kohl
@ -10,6 +9,7 @@
/* INCLUDES ******************************************************************/
#include <hal.h>
#define NDEBUG
#include <debug.h>
@ -23,6 +23,7 @@ UCHAR HalpCmosCenturyOffset;
/* PRIVATE FUNCTIONS *********************************************************/
_Requires_lock_held_(HalpSystemHardwareLock)
UCHAR
NTAPI
HalpReadCmos(IN UCHAR Reg)
@ -34,6 +35,7 @@ HalpReadCmos(IN UCHAR Reg)
return READ_PORT_UCHAR(CMOS_DATA_PORT);
}
_Requires_lock_held_(HalpSystemHardwareLock)
VOID
NTAPI
HalpWriteCmos(IN UCHAR Reg,
@ -48,10 +50,11 @@ HalpWriteCmos(IN UCHAR Reg,
ULONG
NTAPI
HalpGetCmosData(IN ULONG BusNumber,
IN ULONG SlotNumber,
IN PVOID Buffer,
IN ULONG Length)
HalpGetCmosData(
_In_ ULONG BusNumber,
_In_ ULONG SlotNumber,
_Out_writes_bytes_(Length) PVOID Buffer,
_In_ ULONG Length)
{
PUCHAR Ptr = (PUCHAR)Buffer;
ULONG Address = SlotNumber;
@ -173,9 +176,10 @@ HalpInitializeCmos(VOID)
*/
ARC_STATUS
NTAPI
HalGetEnvironmentVariable(IN PCH Name,
IN USHORT ValueLength,
IN PCH Value)
HalGetEnvironmentVariable(
_In_ PCH Name,
_In_ USHORT ValueLength,
_Out_writes_z_(ValueLength) PCH Value)
{
UCHAR Val;

View file

@ -133,6 +133,24 @@ static DMA_OPERATIONS HalpDmaOperations = {
/* FUNCTIONS *****************************************************************/
#if defined(SARCH_PC98)
/*
* Disable I/O for safety.
* FIXME: Add support for PC-98 DMA controllers.
*/
#undef WRITE_PORT_UCHAR
#undef READ_PORT_UCHAR
#define WRITE_PORT_UCHAR(Port, Data) \
do { \
UNIMPLEMENTED; \
(Port); \
(Data); \
} while (0)
#define READ_PORT_UCHAR(Port) 0x00
#endif
#ifndef _MINIHAL_
INIT_FUNCTION
VOID

View file

@ -1,15 +1,13 @@
/*
* PROJECT: ReactOS Hardware Abstraction Layer (HAL)
* LICENSE: BSD - See COPYING.ARM in the top level directory
* FILE: hal/halx86/generic/misc.c
* PURPOSE: NMI, I/O Mapping and x86 Subs
* PURPOSE: I/O Mapping and x86 Subs
* PROGRAMMERS: ReactOS Portable Systems Group
*/
/* INCLUDES *******************************************************************/
#include <hal.h>
#include <drivers/bootvid/display.h>
#define NDEBUG
#include <debug.h>
@ -21,8 +19,6 @@
/* GLOBALS *******************************************************************/
BOOLEAN HalpNMIInProgress;
UCHAR HalpSerialLen;
CHAR HalpSerialNumber[31];
@ -148,7 +144,7 @@ HalpOpenRegistryKey(IN PHANDLE KeyHandle,
/* We're done */
return Status;
}
#endif
#endif /* !_MINIHAL_ */
VOID
NTAPI
@ -223,108 +219,6 @@ HalpFlushTLB(VOID)
/* FUNCTIONS *****************************************************************/
/*
* @implemented
*/
VOID
NTAPI
HalHandleNMI(IN PVOID NmiInfo)
{
#ifndef _MINIHAL_
SYSTEM_CONTROL_PORT_B_REGISTER SystemControl;
//
// Don't recurse
//
if (HalpNMIInProgress++) ERROR_DBGBREAK();
//
// Read the system control register B
//
SystemControl.Bits = __inbyte(SYSTEM_CONTROL_PORT_B);
//
// Switch to boot video
//
if (InbvIsBootDriverInstalled())
{
//
// Acquire ownership
//
InbvAcquireDisplayOwnership();
InbvResetDisplay();
//
// Fill the screen
//
InbvSolidColorFill(0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1, BV_COLOR_RED);
InbvSetScrollRegion(0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1);
//
// Enable text
//
InbvSetTextColor(BV_COLOR_WHITE);
InbvInstallDisplayStringFilter(NULL);
InbvEnableDisplayString(TRUE);
}
//
// Display NMI failure string
//
InbvDisplayString("\r\n*** Hardware Malfunction\r\n\r\n");
InbvDisplayString("Call your hardware vendor for support\r\n\r\n");
//
// Check for parity error
//
if (SystemControl.ParityCheck)
{
//
// Display message
//
InbvDisplayString("NMI: Parity Check / Memory Parity Error\r\n");
}
//
// Check for I/O failure
//
if (SystemControl.ChannelCheck)
{
//
// Display message
//
InbvDisplayString("NMI: Channel Check / IOCHK\r\n");
}
//
// Check for EISA systems
//
if (HalpBusType == MACHINE_TYPE_EISA)
{
//
// FIXME: Not supported
//
UNIMPLEMENTED;
}
//
// Halt the system
//
InbvDisplayString("\r\n*** The system has halted ***\r\n");
//
// Enter the debugger if possible
//
KiBugCheckData[0] = (ULONG_PTR)KeServiceDescriptorTable; /* NMI Corruption? */
//if (!(KdDebuggerNotPresent) && (KdDebuggerEnabled)) KeEnterKernelDebugger();
#endif
//
// Freeze the system
//
while (TRUE);
}
/*
* @implemented
*/
@ -407,5 +301,4 @@ KeReleaseSpinLock(PKSPIN_LOCK SpinLock,
KfReleaseSpinLock(SpinLock, NewIrql);
}
#endif
#endif /* _M_IX86 */

108
hal/halx86/generic/nmi.c Normal file
View file

@ -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;
}

View file

@ -1,7 +1,6 @@
/*
* PROJECT: ReactOS HAL
* LICENSE: GPL - See COPYING in the top level directory
* FILE: hal/halx86/generic/timer.c
* PURPOSE: HAL Timer Routines
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
* Timo Kreuzer (timo.kreuzer@reactos.org)
@ -101,6 +100,10 @@ HalpInitializeClock(VOID)
DPRINT("HalpInitializeClock()\n");
#if defined(SARCH_PC98)
HalpInitializeClockPc98();
#endif
/* Get increment and rollover for the largest time clock ms possible */
Increment = HalpRolloverTable[HalpLargestClockMS - 1].Increment;
RollOver = (USHORT)HalpRolloverTable[HalpLargestClockMS - 1].RollOver;
@ -129,7 +132,7 @@ HalpClockInterruptHandler(IN PKTRAP_FRAME TrapFrame)
KiEnterInterruptTrap(TrapFrame);
/* Start the interrupt */
if (HalBeginSystemInterrupt(CLOCK2_LEVEL, PRIMARY_VECTOR_BASE, &Irql))
if (HalBeginSystemInterrupt(CLOCK2_LEVEL, PRIMARY_VECTOR_BASE + PIC_TIMER_IRQ, &Irql))
{
/* Update the performance counter */
HalpPerfCounter.QuadPart += HalpCurrentRollOver;
@ -170,13 +173,20 @@ HalpProfileInterruptHandler(IN PKTRAP_FRAME TrapFrame)
KiEnterInterruptTrap(TrapFrame);
/* Start the interrupt */
if (HalBeginSystemInterrupt(PROFILE_LEVEL, PRIMARY_VECTOR_BASE + 8, &Irql))
if (HalBeginSystemInterrupt(PROFILE_LEVEL, PRIMARY_VECTOR_BASE + PIC_RTC_IRQ, &Irql))
{
#if defined(SARCH_PC98)
/* Clear the interrupt flag */
HalpAcquireCmosSpinLock();
(VOID)__inbyte(RTC_IO_i_INTERRUPT_RESET);
HalpReleaseCmosSpinLock();
#else
/* Spin until the interrupt pending bit is clear */
HalpAcquireCmosSpinLock();
while (HalpReadCmos(RTC_REGISTER_C) & RTC_REG_C_IRQ)
;
NOTHING;
HalpReleaseCmosSpinLock();
#endif
/* If profiling is enabled, call the kernel function */
if (!HalpProfilingStopped)
@ -192,9 +202,9 @@ HalpProfileInterruptHandler(IN PKTRAP_FRAME TrapFrame)
/* Spurious, just end the interrupt */
KiEoiHelper(TrapFrame);
}
#endif
#endif /* !_MINIHAL_ */
#endif
#endif /* _M_IX86 */
/* PUBLIC FUNCTIONS ***********************************************************/

View file

@ -1,7 +1,6 @@
/*
* PROJECT: ReactOS HAL
* LICENSE: GPL - See COPYING in the top level directory
* FILE: hal/halx86/generic/usage.c
* PURPOSE: HAL Resource Report Routines
* PROGRAMMERS: Stefan Ginsberg (stefan.ginsberg@reactos.org)
*/
@ -9,6 +8,7 @@
/* INCLUDES *******************************************************************/
#include <hal.h>
#define NDEBUG
#include <debug.h>
@ -82,6 +82,60 @@ ADDRESS_USAGE HalpDefaultIoSpace =
{
NULL, CmResourceTypePort, IDT_INTERNAL,
{
#if defined(SARCH_PC98)
/* PIC 1 */
{0x00, 1},
{0x02, 1},
/* PIC 2 */
{0x08, 1},
{0x0A, 1},
/* DMA */
{0x01, 1},
{0x03, 1},
{0x05, 1},
{0x07, 1},
{0x09, 1},
{0x0B, 1},
{0x0D, 1},
{0x0F, 1},
{0x11, 1},
{0x13, 1},
{0x15, 1},
{0x17, 1},
{0x19, 1},
{0x1B, 1},
{0x1D, 1},
{0x1F, 1},
{0x21, 1},
{0x23, 1},
{0x25, 1},
{0x27, 1},
{0x29, 1},
{0x2B, 1},
{0x2D, 1},
{0xE05, 1},
{0xE07, 1},
{0xE09, 1},
{0xE0B, 1},
/* RTC */
{0x20, 1},
{0x22, 1},
{0x128, 1},
/* System Control */
{0x33, 1},
{0x37, 1},
/* PIT */
{0x71, 1},
{0x73, 1},
{0x75, 1},
{0x77, 1},
{0x3FD9,1},
{0x3FDB,1},
{0x3FDD,1},
{0x3FDF,1},
/* x87 Coprocessor */
{0xF8, 8},
#else
{0x00, 0x20}, /* DMA 1 */
{0xC0, 0x20}, /* DMA 2 */
{0x80, 0x10}, /* DMA EPAR */
@ -92,6 +146,7 @@ ADDRESS_USAGE HalpDefaultIoSpace =
{0x92, 0x1}, /* System Control Port A */
{0x70, 0x2}, /* CMOS */
{0xF0, 0x10}, /* x87 Coprocessor */
#endif
{0xCF8, 0x8}, /* PCI 0 */
{0,0},
}
@ -523,7 +578,7 @@ HalpReportResourceUsage(IN PUNICODE_STRING HalName,
/* Get the machine's serial number */
HalpReportSerialNumber();
}
#endif
#endif /* !_MINIHAL_ */
INIT_FUNCTION
VOID
@ -614,7 +669,6 @@ HalpGetNMICrashFlag(VOID)
ZwClose(Handle);
}
}
#endif
#endif /* !_MINIHAL_ */
/* EOF */

View file

@ -411,10 +411,10 @@ HalpGetSystemInterruptVector_Acpi(
ULONG
NTAPI
HalpGetCmosData(
IN ULONG BusNumber,
IN ULONG SlotNumber,
IN PVOID Buffer,
IN ULONG Length
_In_ ULONG BusNumber,
_In_ ULONG SlotNumber,
_Out_writes_bytes_(Length) PVOID Buffer,
_In_ ULONG Length
);
ULONG

View file

@ -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"

View file

@ -32,7 +32,7 @@
//
// Video Modes for INT10h AH=00 (in AL)
//
#define GRAPHICS_MODE_12 0x12 /* 80x30 8x16 640x480 16/256K */
#define GRAPHICS_MODE_12 0x12 /* 80x30 8x16 640x480 16/256K */
#if defined(SARCH_XBOX)
//
@ -152,6 +152,10 @@ typedef union _SYSTEM_CONTROL_PORT_B_REGISTER
#define PIC2_CONTROL_PORT 0xA0
#define PIC2_DATA_PORT 0xA1
#define PIC_TIMER_IRQ 0
#define PIC_CASCADE_IRQ 2
#define PIC_RTC_IRQ 8
//
// Definitions for ICW/OCW Bits
//
@ -304,19 +308,16 @@ typedef union _I8259_OCW3
typedef union _I8259_ISR
{
union
struct
{
struct
{
UCHAR Irq0:1;
UCHAR Irq1:1;
UCHAR Irq2:1;
UCHAR Irq3:1;
UCHAR Irq4:1;
UCHAR Irq5:1;
UCHAR Irq6:1;
UCHAR Irq7:1;
};
UCHAR Irq0:1;
UCHAR Irq1:1;
UCHAR Irq2:1;
UCHAR Irq3:1;
UCHAR Irq4:1;
UCHAR Irq5:1;
UCHAR Irq6:1;
UCHAR Irq7:1;
};
UCHAR Bits;
} I8259_ISR, *PI8259_ISR;
@ -362,15 +363,12 @@ typedef union _EISA_ELCR
USHORT Bits;
} EISA_ELCR, *PEISA_ELCR;
typedef struct _PIC_MASK
typedef union _PIC_MASK
{
union
struct
{
struct
{
UCHAR Master;
UCHAR Slave;
};
USHORT Both;
UCHAR Master;
UCHAR Slave;
};
USHORT Both;
} PIC_MASK, *PPIC_MASK;

View file

@ -378,12 +378,14 @@ HalpInitializeCmos(
VOID
);
_Requires_lock_held_(HalpSystemHardwareLock)
UCHAR
NTAPI
HalpReadCmos(
IN UCHAR Reg
);
_Requires_lock_held_(HalpSystemHardwareLock)
VOID
NTAPI
HalpWriteCmos(
@ -394,12 +396,14 @@ HalpWriteCmos(
//
// Spinlock for protecting CMOS access
//
_Acquires_lock_(HalpSystemHardwareLock)
VOID
NTAPI
HalpAcquireCmosSpinLock(
VOID
);
_Releases_lock_(HalpSystemHardwareLock)
VOID
NTAPI
HalpReleaseCmosSpinLock(
@ -516,6 +520,30 @@ HalpInitProcessor(
IN PLOADER_PARAMETER_BLOCK LoaderBlock
);
#if defined(SARCH_PC98)
BOOLEAN
NTAPI
HalpDismissIrq08(
_In_ KIRQL Irql,
_In_ ULONG Irq,
_Out_ PKIRQL OldIrql
);
BOOLEAN
NTAPI
HalpDismissIrq08Level(
_In_ KIRQL Irql,
_In_ ULONG Irq,
_Out_ PKIRQL OldIrql
);
VOID
NTAPI
HalpInitializeClockPc98(VOID);
extern ULONG PIT_FREQUENCY;
#endif /* SARCH_PC98 */
#ifdef _M_AMD64
VOID

View file

@ -1,7 +1,6 @@
/*
* PROJECT: ReactOS HAL
* LICENSE: BSD - See COPYING.ARM in the top level directory
* FILE: hal/halx86/legacy/halpcat.c
* PURPOSE: HAL Legacy Support Code
* PROGRAMMERS: ReactOS Portable Systems Group
*/
@ -9,6 +8,7 @@
/* INCLUDES *******************************************************************/
#include <hal.h>
#define NDEBUG
#include <debug.h>
@ -28,6 +28,9 @@ BOOLEAN HalDisableFirmwareMapper = FALSE;
#if defined(SARCH_XBOX)
PWCHAR HalHardwareIdString = L"xbox";
PWCHAR HalName = L"Xbox HAL";
#elif defined(SARCH_PC98)
PWCHAR HalHardwareIdString = L"pc98_up";
PWCHAR HalName = L"NEC PC-98 Compatible NESA/C-Bus HAL";
#else
PWCHAR HalHardwareIdString = L"e_isa_up";
PWCHAR HalName = L"PC Compatible Eisa/Isa HAL";
@ -51,7 +54,7 @@ HalpBuildAddressMap(VOID)
{
/* FIXME: Inherit ROM blocks from the registry */
//HalpInheritROMBlocks();
/* FIXME: Add the ROM blocks to our ranges */
//HalpAddROMRanges();
}

View file

@ -7,16 +7,12 @@ list(APPEND MINI_HAL_SOURCE
../legacy/bus/pcibus.c
../legacy/bus/sysbus.c
../legacy/bussupp.c
../generic/beep.c
../generic/bios.c
../generic/clock.c
../generic/cmos.c
../generic/dma.c
../generic/display.c
../generic/drive.c
../generic/misc.c
../generic/profil.c
../generic/reboot.c
../generic/nmi.c
../generic/spinlock.c
../generic/sysinfo.c
../generic/timer.c
@ -26,6 +22,29 @@ list(APPEND MINI_HAL_SOURCE
../up/processor.c
../include/hal.h)
if(SARCH STREQUAL "xbox")
list(APPEND MINI_HAL_SOURCE
../generic/beep.c
../generic/cmos.c
../generic/profil.c
../xbox/clock.c
../xbox/reboot.c)
elseif(SARCH STREQUAL "pc98")
list(APPEND MINI_HAL_SOURCE
../pc98/beep.c
../pc98/clock.c
../pc98/cmos.c
../pc98/profil.c
../pc98/reboot.c)
else()
list(APPEND MINI_HAL_SOURCE
../generic/beep.c
../generic/clock.c
../generic/cmos.c
../generic/profil.c
../generic/reboot.c)
endif()
add_asm_files(mini_hal_asm ../generic/systimer.S)
add_library(mini_hal ${MINI_HAL_SOURCE} ${mini_hal_asm})
target_compile_definitions(mini_hal PRIVATE _BLDR_ _MINIHAL_)

57
hal/halx86/pc98.cmake Normal file
View file

@ -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()

53
hal/halx86/pc98/beep.c Normal file
View file

@ -0,0 +1,53 @@
/*
* PROJECT: NEC PC-98 series HAL
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: Speaker support (beeping)
* COPYRIGHT: Copyright 2020 Dmitry Borisov (di.sean@protonmail.com)
*/
/* INCLUDES ******************************************************************/
#include <hal.h>
#define NDEBUG
#include <debug.h>
/* FUNCTIONS *****************************************************************/
BOOLEAN
NTAPI
HalMakeBeep(
_In_ ULONG Frequency)
{
TIMER_CONTROL_PORT_REGISTER TimerControl;
ULONG Divider;
BOOLEAN Success = FALSE;
HalpAcquireCmosSpinLock();
__outbyte(PPI_IO_o_CONTROL, PPI_TIMER_1_UNGATE_TO_SPEAKER);
if (Frequency)
{
Divider = PIT_FREQUENCY / Frequency;
if (Divider <= 0x10000)
{
TimerControl.BcdMode = FALSE;
TimerControl.OperatingMode = PitOperatingMode3;
TimerControl.Channel = PitChannel1;
TimerControl.AccessMode = PitAccessModeLowHigh;
__outbyte(TIMER_CONTROL_PORT, TimerControl.Bits);
__outbyte(TIMER_CHANNEL1_DATA_PORT, FIRSTBYTE(Divider));
__outbyte(TIMER_CHANNEL1_DATA_PORT, SECONDBYTE(Divider));
__outbyte(PPI_IO_o_CONTROL, PPI_TIMER_1_GATE_TO_SPEAKER);
Success = TRUE;
}
}
HalpReleaseCmosSpinLock();
return Success;
}

75
hal/halx86/pc98/clock.c Normal file
View file

@ -0,0 +1,75 @@
/*
* PROJECT: NEC PC-98 series HAL
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: PIT rollover tables
* COPYRIGHT: Copyright 2020 Dmitry Borisov (di.sean@protonmail.com)
*/
/* INCLUDES ******************************************************************/
#include <hal.h>
/* GLOBALS *******************************************************************/
#define LPT_STATUS 0x42
#define SYSTEM_CLOCK_8_MHZ 0x20
ULONG PIT_FREQUENCY;
HALP_ROLLOVER HalpRolloverTable[15];
/* Accuracy is 97.5% */
static const HALP_ROLLOVER RolloverTable1[15] =
{
{1996, 9996}, /* 1 ms */
{3993, 19997},
{5990, 29998},
{7987, 39999},
{9984, 50000},
{11980, 59996},
{13977, 69997},
{15974, 79998},
{17971, 89999},
{19968, 100000},
{21964, 109996},
{23961, 119997},
{25958, 129998},
{27955, 139999},
{29951, 149995} /* 15 ms */
};
static const HALP_ROLLOVER RolloverTable2[15] =
{
{2463, 10022}, /* 1 ms */
{4912, 19987},
{7376, 30013},
{9825, 39978},
{12288, 50000},
{14751, 60022},
{17200, 69987},
{19664, 80013},
{22113, 89978},
{24576, 100000},
{27039, 110022},
{29488, 119987},
{31952, 130013},
{34401, 139978},
{36864, 150000} /* 15 ms */
};
/* PRIVATE FUNCTIONS *********************************************************/
VOID
NTAPI
HalpInitializeClockPc98(VOID)
{
/* Obtain system clock value from the parallel port */
if (__inbyte(LPT_STATUS) & SYSTEM_CLOCK_8_MHZ)
{
PIT_FREQUENCY = TIMER_FREQUENCY_1;
RtlCopyMemory(HalpRolloverTable, RolloverTable1, sizeof(HALP_ROLLOVER) * 15);
}
else
{
PIT_FREQUENCY = TIMER_FREQUENCY_2;
RtlCopyMemory(HalpRolloverTable, RolloverTable2, sizeof(HALP_ROLLOVER) * 15);
}
}

322
hal/halx86/pc98/cmos.c Normal file
View file

@ -0,0 +1,322 @@
/*
* PROJECT: NEC PC-98 series HAL
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: RTC and NVRAM access routines
* COPYRIGHT: Copyright 2020 Dmitry Borisov (di.sean@protonmail.com)
*/
/* INCLUDES ******************************************************************/
#include <hal.h>
#define NDEBUG
#include <debug.h>
#if defined(ALLOC_PRAGMA) && !defined(_MINIHAL_)
#pragma alloc_text(INIT, HalpInitializeCmos)
#endif
/* GLOBALS *******************************************************************/
/*
* The PC-98 hardware maps data from the NVRAM directly into the text video
* memory address space. Every fourth byte is a "writable data".
*
* |0x2FE2|0x2FE3|0x2FE4|0x2FE5|0x2FE6|0x2FE7| .... |0x2FFD|0x2FFE|
* | D | | | | D | | .... | | D |
*
* Most of these bits of the NVRAM are already used. There are some reserved
* bits in the 0x3FE6 and 0x3FFE that we can use.
*/
#define NVRAM_START 0x3FE2
#define NVRAM_SIZE 0x1C
#define NVRAM_UNUSED_REG 0x14
#define NVRAM_UNUSED_BIT 0x80
static ULONG_PTR MappedNvram;
/* PRIVATE FUNCTIONS *********************************************************/
/* Avoid double calls */
#undef BCD_INT
static UCHAR
BCD_INT(
_In_ UCHAR Bcd)
{
return ((Bcd & 0xF0) >> 4) * 10 + (Bcd & 0x0F);
}
static UCHAR
NTAPI
HalpReadNvram(
_In_ UCHAR Register)
{
return READ_REGISTER_UCHAR((PUCHAR)(MappedNvram + Register));
}
_Requires_lock_held_(HalpSystemHardwareLock)
static VOID
NTAPI
HalpWriteNvram(
_In_ UCHAR Register,
_In_ UCHAR Value)
{
__outbyte(GDC1_IO_o_MODE_FLIPFLOP1, GDC1_NVRAM_UNPROTECT);
WRITE_REGISTER_UCHAR((PUCHAR)(MappedNvram + Register), Value);
__outbyte(GDC1_IO_o_MODE_FLIPFLOP1, GDC1_NVRAM_PROTECT);
}
_Requires_lock_held_(HalpSystemHardwareLock)
static UCHAR
NTAPI
HalpRtcReadByte(VOID)
{
UCHAR i;
UCHAR Byte = 0;
/* Read byte from single wire bus */
for (i = 0; i < 8; i++)
{
Byte |= (__inbyte(PPI_IO_i_PORT_B) & 1) << i;
__outbyte(RTC_IO_o_DATA, RTC_CLOCK | RTC_CMD_SERIAL_TRANSFER_MODE);
KeStallExecutionProcessor(1);
__outbyte(RTC_IO_o_DATA, RTC_CMD_SERIAL_TRANSFER_MODE);
KeStallExecutionProcessor(1);
}
return Byte;
}
_Requires_lock_held_(HalpSystemHardwareLock)
static VOID
NTAPI
HalpRtcWriteBit(
_In_ UCHAR Bit)
{
Bit = (Bit & 1) << 5;
__outbyte(RTC_IO_o_DATA, Bit | RTC_CMD_SERIAL_TRANSFER_MODE);
KeStallExecutionProcessor(1);
__outbyte(RTC_IO_o_DATA, Bit | RTC_CLOCK | RTC_CMD_SERIAL_TRANSFER_MODE);
KeStallExecutionProcessor(1);
}
_Requires_lock_held_(HalpSystemHardwareLock)
static VOID
NTAPI
HalpRtcWriteCommand(
_In_ UCHAR Command)
{
UCHAR i;
for (i = 0; i < 4; i++)
HalpRtcWriteBit(Command >> i);
__outbyte(RTC_IO_o_DATA, RTC_STROBE | RTC_CMD_SERIAL_TRANSFER_MODE);
KeStallExecutionProcessor(1);
__outbyte(RTC_IO_o_DATA, RTC_CMD_SERIAL_TRANSFER_MODE);
KeStallExecutionProcessor(1);
}
UCHAR
NTAPI
HalpReadCmos(
_In_ UCHAR Reg)
{
/* Not supported by hardware */
return 0;
}
VOID
NTAPI
HalpWriteCmos(
_In_ UCHAR Reg,
_In_ UCHAR Value)
{
/* Not supported by hardware */
NOTHING;
}
ULONG
NTAPI
HalpGetCmosData(
_In_ ULONG BusNumber,
_In_ ULONG SlotNumber,
_Out_writes_bytes_(Length) PVOID Buffer,
_In_ ULONG Length)
{
/* Not supported by hardware */
return 0;
}
ULONG
NTAPI
HalpSetCmosData(
_In_ ULONG BusNumber,
_In_ ULONG SlotNumber,
_In_reads_bytes_(Length) PVOID Buffer,
_In_ ULONG Length)
{
/* Not supported by hardware */
return 0;
}
INIT_FUNCTION
VOID
NTAPI
HalpInitializeCmos(VOID)
{
PHYSICAL_ADDRESS PhysicalAddress;
/* TODO: Detect TVRAM address */
if (TRUE)
PhysicalAddress.QuadPart = VRAM_NORMAL_TEXT + NVRAM_START;
else
PhysicalAddress.QuadPart = VRAM_HI_RESO_TEXT + NVRAM_START;
MappedNvram = (ULONG_PTR)HalpMapPhysicalMemory64(PhysicalAddress, BYTES_TO_PAGES(NVRAM_SIZE));
}
/* PUBLIC FUNCTIONS **********************************************************/
ARC_STATUS
NTAPI
HalGetEnvironmentVariable(
_In_ PCH Name,
_In_ USHORT ValueLength,
_Out_writes_z_(ValueLength) PCH Value)
{
UCHAR Val;
/* Only variable supported on x86 */
if (_stricmp(Name, "LastKnownGood"))
return ENOENT;
if (!MappedNvram)
return ENOENT;
HalpAcquireCmosSpinLock();
Val = HalpReadNvram(NVRAM_UNUSED_REG) & NVRAM_UNUSED_BIT;
HalpReleaseCmosSpinLock();
/* Check the flag */
if (Val)
strncpy(Value, "FALSE", ValueLength);
else
strncpy(Value, "TRUE", ValueLength);
return ESUCCESS;
}
ARC_STATUS
NTAPI
HalSetEnvironmentVariable(
_In_ PCH Name,
_In_ PCH Value)
{
UCHAR Val;
/* Only variable supported on x86 */
if (_stricmp(Name, "LastKnownGood"))
return ENOMEM;
if (!MappedNvram)
return ENOMEM;
/* Check if this is true or false */
if (!_stricmp(Value, "TRUE"))
{
HalpAcquireCmosSpinLock();
Val = HalpReadNvram(NVRAM_UNUSED_REG) | NVRAM_UNUSED_BIT;
}
else if (!_stricmp(Value, "FALSE"))
{
HalpAcquireCmosSpinLock();
Val = HalpReadNvram(NVRAM_UNUSED_REG) & ~NVRAM_UNUSED_BIT;
}
else
{
/* Fail */
return ENOMEM;
}
HalpWriteNvram(NVRAM_UNUSED_REG, Val);
HalpReleaseCmosSpinLock();
return ESUCCESS;
}
BOOLEAN
NTAPI
HalQueryRealTimeClock(
_Out_ PTIME_FIELDS Time)
{
UCHAR Temp;
HalpAcquireCmosSpinLock();
HalpRtcWriteCommand(RTC_CMD_TIME_READ);
HalpRtcWriteCommand(RTC_CMD_REGISTER_SHIFT);
KeStallExecutionProcessor(19);
/* Set the time data */
Time->Second = BCD_INT(HalpRtcReadByte());
Time->Minute = BCD_INT(HalpRtcReadByte());
Time->Hour = BCD_INT(HalpRtcReadByte());
Time->Day = BCD_INT(HalpRtcReadByte());
Temp = HalpRtcReadByte();
Time->Weekday = Temp & 0x0F;
Time->Month = Temp >> 4;
Time->Year = BCD_INT(HalpRtcReadByte());
Time->Milliseconds = 0;
Time->Year += (Time->Year >= 80) ? 1900 : 2000;
HalpRtcWriteCommand(RTC_CMD_REGISTER_HOLD);
HalpReleaseCmosSpinLock();
return TRUE;
}
BOOLEAN
NTAPI
HalSetRealTimeClock(
_In_ PTIME_FIELDS Time)
{
UCHAR i, j;
UCHAR SysTime[6];
HalpAcquireCmosSpinLock();
HalpRtcWriteCommand(RTC_CMD_REGISTER_SHIFT);
SysTime[0] = INT_BCD(Time->Second);
SysTime[1] = INT_BCD(Time->Minute);
SysTime[2] = INT_BCD(Time->Hour);
SysTime[3] = INT_BCD(Time->Day);
SysTime[4] = (Time->Month << 4) | (Time->Weekday & 0x0F);
SysTime[5] = INT_BCD(Time->Year % 100);
/* Write time fields to RTC */
for (i = 0; i < 6; i++)
{
for (j = 0; j < 8; j++)
HalpRtcWriteBit(SysTime[i] >> j);
}
HalpRtcWriteCommand(RTC_CMD_TIME_SET_COUNTER_HOLD);
HalpRtcWriteCommand(RTC_CMD_REGISTER_HOLD);
HalpReleaseCmosSpinLock();
return TRUE;
}

39
hal/halx86/pc98/delay.c Normal file
View file

@ -0,0 +1,39 @@
/*
* PROJECT: NEC PC-98 series HAL
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: Delay routines
* COPYRIGHT: Copyright 2020 Dmitry Borisov (di.sean@protonmail.com)
*/
/* INCLUDES ******************************************************************/
#include <hal.h>
#define NDEBUG
#include <debug.h>
/* PRIVATE FUNCTIONS *********************************************************/
VOID
NTAPI
HalpCalibrateStallExecution(VOID)
{
/* FIXME */
NOTHING;
}
/* PUBLIC FUNCTIONS **********************************************************/
#ifndef _MINIHAL_
VOID
NTAPI
KeStallExecutionProcessor(
_In_ ULONG MicroSeconds)
{
while (MicroSeconds--)
{
/* FIXME: Use stall factor */
WRITE_PORT_UCHAR((PUCHAR)CPU_IO_o_ARTIC_DELAY, 0);
}
}
#endif

View file

@ -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>

121
hal/halx86/pc98/irql.c Normal file
View file

@ -0,0 +1,121 @@
/*
* PROJECT: NEC PC-98 series HAL
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: IRQL mapping
* COPYRIGHT: Copyright 2020 Dmitry Borisov (di.sean@protonmail.com)
*/
/* INCLUDES *******************************************************************/
#include <hal.h>
/* GLOBALS ********************************************************************/
/* This table contains the static x86 PIC mapping between IRQLs and IRQs */
ULONG KiI8259MaskTable[32] =
{
/*
* See comments of the PC/AT version.
*/
0b00000000000000000000000000000000, /* IRQL 0 */
0b00000000000000000000000000000000, /* IRQL 1 */
0b00000000000000000000000000000000, /* IRQL 2 */
0b00000000000000000000000000000000, /* IRQL 3 */
0b11111111100000000000000000000000, /* IRQL 4 */
0b11111111110000000000000000000000, /* IRQL 5 */
0b11111111111000000000000000000000, /* IRQL 6 */
0b11111111111100000000000000000000, /* IRQL 7 */
0b11111111111110000000000000000000, /* IRQL 8 */
0b11111111111111000000000000000000, /* IRQL 9 */
0b11111111111111100000000000000000, /* IRQL 10 */
0b11111111111111110000000000000000, /* IRQL 11 */
/*
* Okay, now we're finally starting to mask off IRQs on the slave PIC, from
* IRQ15 to IRQ8. Note that the output of INT of RTC is connected to the IR7.
* We need to keep this IRQ unmasked, so we can ensure profiling the whole system.
*/
0b11111111111111110000000000000000, /* IRQL 12 */
0b11111111111111110100000000000000, /* IRQL 13 */
0b11111111111111110110000000000000, /* IRQL 14 */
0b11111111111111110111000000000000, /* IRQL 15 */
0b11111111111111110111100000000000, /* IRQL 16 */
0b11111111111111110111110000000000, /* IRQL 17 */
0b11111111111111110111111000000000, /* IRQL 18 */
0b11111111111111110111111000000000, /* IRQL 19 */
/*
* Now we mask off the IRQs on the master. Since IRQL 19 we have 0 "droplet".
* It's the cascade IRQ that we use to bridge the slave PIC with the master PIC.
*/
0b11111111111111110111111100000000, /* IRQL 20 */
0b11111111111111110111111101000000, /* IRQL 21 */
0b11111111111111110111111101100000, /* IRQL 22 */
0b11111111111111110111111101110000, /* IRQL 23 */
0b11111111111111110111111101111000, /* IRQL 24 */
0b11111111111111110111111101111100, /* IRQL 25 */
0b11111111111111110111111101111110, /* IRQL 26 */
0b11111111111111111111111101111110, /* IRQL 27 */
/*
* See comments of the PC/AT version.
*/
0b11111111111111111111111101111111, /* IRQL 28 */
0b11111111111111111111111101111111, /* IRQL 29 */
0b11111111111111111111111101111111, /* IRQL 30 */
0b11111111111111111111111101111111 /* IRQL 31 */
};
/* This table indicates which IRQs, if pending, can preempt a given IRQL level */
ULONG FindHigherIrqlMask[32] =
{
/*
* See comments of the PC/AT version.
*/
0b11111111111111111111111111111110, /* IRQL 0 */
0b11111111111111111111111111111100, /* IRQL 1 */
0b11111111111111111111111111111000, /* IRQL 2 */
0b11111111111111111111111111110000, /* IRQL 3 */
0b00000111111111111111111111110000, /* IRQL 4 */
0b00000011111111111111111111110000, /* IRQL 5 */
0b00000001111111111111111111110000, /* IRQL 6 */
0b00000000111111111111111111110000, /* IRQL 7 */
0b00000000011111111111111111110000, /* IRQL 8 */
0b00000000001111111111111111110000, /* IRQL 9 */
0b00000000000111111111111111110000, /* IRQL 10 */
/*
* Now we start progressivly limiting which slave PIC interrupts have the
* right to preempt us at each level. The RTC timer used for profiling,
* so it will always preempt until we reach PROFILE_LEVEL.
*/
0b00000000000011111111111111110000, /* IRQL 11 */
0b00000000000011111111111111110000, /* IRQL 12 */
0b00000000000010111111111111110000, /* IRQL 13 */
0b00000000000010011111111111110000, /* IRQL 14 */
0b00000000000010001111111111110000, /* IRQL 15 */
0b00000000000010000111111111110000, /* IRQL 16 */
0b00000000000010000011111111110000, /* IRQL 17 */
0b00000000000010000001111111110000, /* IRQL 18 */
0b00000000000010000001111111110000, /* IRQL 19 */
/*
* Now with IRQs on the master PIC.
*/
0b00000000000010000000011111110000, /* IRQL 20 */
0b00000000000010000000001111110000, /* IRQL 21 */
0b00000000000010000000000111110000, /* IRQL 22 */
0b00000000000010000000000011110000, /* IRQL 23 */
0b00000000000010000000000001110000, /* IRQL 24 */
0b00000000000010000000000000110000, /* IRQL 25 */
0b00000000000010000000000000010000, /* IRQL 26 */
/*
* See comments of the PC/AT version.
*/
0b00000000000000000000000000010000, /* IRQL 27 */
0b00000000000000000000000000000000, /* IRQL 28 */
0b00000000000000000000000000000000, /* IRQL 29 */
0b00000000000000000000000000000000, /* IRQL 30 */
0b00000000000000000000000000000000 /* IRQL 31 */
};

105
hal/halx86/pc98/pic.c Normal file
View file

@ -0,0 +1,105 @@
/*
* PROJECT: NEC PC-98 series HAL
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: PIC initialization
* COPYRIGHT: Copyright 2020 Dmitry Borisov (di.sean@protonmail.com)
*/
/* INCLUDES ******************************************************************/
#include <hal.h>
/* PRIVATE FUNCTIONS *********************************************************/
static VOID
HalpIoWait(VOID)
{
UCHAR i;
/*
* Give the old PICs enough time to react to commands.
* (KeStallExecutionProcessor is not available at this stage)
*/
for (i = 0; i < 6; i++)
__outbyte(CPU_IO_o_ARTIC_DELAY, 0);
}
VOID
NTAPI
HalpInitializeLegacyPICs(VOID)
{
I8259_ICW1 Icw1;
I8259_ICW2 Icw2;
I8259_ICW3 Icw3;
I8259_ICW4 Icw4;
ASSERT(!(__readeflags() & EFLAGS_INTERRUPT_MASK));
/* Initialize ICW1 for master, interval 8, edge-triggered mode with ICW4 */
Icw1.NeedIcw4 = TRUE;
Icw1.OperatingMode = Cascade;
Icw1.Interval = Interval8;
Icw1.InterruptMode = EdgeTriggered;
Icw1.Init = TRUE;
Icw1.InterruptVectorAddress = 0;
__outbyte(PIC1_CONTROL_PORT, Icw1.Bits);
HalpIoWait();
/* ICW2 - interrupt vector offset */
Icw2.Bits = PRIMARY_VECTOR_BASE;
__outbyte(PIC1_DATA_PORT, Icw2.Bits);
HalpIoWait();
/* Connect slave to cascade IRQ */
Icw3.Bits = 0;
Icw3.SlaveIrq7 = TRUE;
__outbyte(PIC1_DATA_PORT, Icw3.Bits);
HalpIoWait();
/* Enable 8086 mode, non-automatic EOI, buffered mode, special fully nested mode */
Icw4.SystemMode = New8086Mode;
Icw4.EoiMode = NormalEoi;
Icw4.BufferedMode = BufferedMaster;
Icw4.SpecialFullyNestedMode = TRUE;
Icw4.Reserved = 0;
__outbyte(PIC1_DATA_PORT, Icw4.Bits);
HalpIoWait();
/* Mask all interrupts */
__outbyte(PIC1_DATA_PORT, 0xFF);
HalpIoWait();
/* Initialize ICW1 for slave, interval 8, edge-triggered mode with ICW4 */
Icw1.NeedIcw4 = TRUE;
Icw1.InterruptMode = EdgeTriggered;
Icw1.OperatingMode = Cascade;
Icw1.Interval = Interval8;
Icw1.Init = TRUE;
Icw1.InterruptVectorAddress = 0; /* This is only used in MCS80/85 mode */
__outbyte(PIC2_CONTROL_PORT, Icw1.Bits);
HalpIoWait();
/* Set interrupt vector base */
Icw2.Bits = PRIMARY_VECTOR_BASE + 8;
__outbyte(PIC2_DATA_PORT, Icw2.Bits);
HalpIoWait();
/* Slave ID */
Icw3.Bits = 0;
Icw3.SlaveId = PIC_CASCADE_IRQ;
__outbyte(PIC2_DATA_PORT, Icw3.Bits);
HalpIoWait();
/* Enable 8086 mode, non-automatic EOI, buffered mode, non special fully nested mode */
Icw4.SystemMode = New8086Mode;
Icw4.EoiMode = NormalEoi;
Icw4.BufferedMode = BufferedSlave;
Icw4.SpecialFullyNestedMode = FALSE;
Icw4.Reserved = 0;
__outbyte(PIC2_DATA_PORT, Icw4.Bits);
HalpIoWait();
/* Mask all interrupts */
__outbyte(PIC2_DATA_PORT, 0xFF);
HalpIoWait();
}

74
hal/halx86/pc98/profil.c Normal file
View file

@ -0,0 +1,74 @@
/*
* PROJECT: NEC PC-98 series HAL
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: System Profiling
* COPYRIGHT: Copyright 2020 Dmitry Borisov (di.sean@protonmail.com)
*/
/* INCLUDES ******************************************************************/
#include <hal.h>
#define NDEBUG
#include <debug.h>
/* GLOBALS *******************************************************************/
BOOLEAN HalpProfilingStopped = TRUE;
UCHAR HalpProfileRate = 3;
/* FUNCTIONS *****************************************************************/
VOID
NTAPI
HalStopProfileInterrupt(
_In_ KPROFILE_SOURCE ProfileSource)
{
UNREFERENCED_PARAMETER(ProfileSource);
HalpAcquireCmosSpinLock();
/* Clear the interrupt flag */
(VOID)__inbyte(RTC_IO_i_INTERRUPT_RESET);
HalpProfilingStopped = TRUE;
HalpReleaseCmosSpinLock();
}
VOID
NTAPI
HalStartProfileInterrupt(
_In_ KPROFILE_SOURCE ProfileSource)
{
UNREFERENCED_PARAMETER(ProfileSource);
HalpProfilingStopped = FALSE;
HalpAcquireCmosSpinLock();
/* Configure the clock divisor for generating periodic interrupts */
__outbyte(RTC_IO_o_INT_CLOCK_DIVISOR, HalpProfileRate | 0x80);
HalpReleaseCmosSpinLock();
}
ULONG_PTR
NTAPI
HalSetProfileInterval(
_In_ ULONG_PTR Interval)
{
/*
* FIXME:
* 1) What is the maximum and minimum interrupt frequency for the RTC?
* 2) Find the maximum possible clock divisor value.
*/
UNIMPLEMENTED;
/* Update interval */
if (!HalpProfilingStopped)
HalStartProfileInterrupt(0);
/* For now... */
return Interval;
}

75
hal/halx86/pc98/reboot.c Normal file
View file

@ -0,0 +1,75 @@
/*
* PROJECT: NEC PC-98 series HAL
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: Reboot routine
* COPYRIGHT: Copyright 2020 Dmitry Borisov (di.sean@protonmail.com)
*/
/* INCLUDES ******************************************************************/
#include <hal.h>
#define NDEBUG
#include <debug.h>
/* PRIVATE FUNCTIONS *********************************************************/
static VOID
DECLSPEC_NORETURN
NTAPI
HalpFreezeSystem(VOID)
{
HaliHaltSystem();
while (TRUE)
NOTHING;
}
VOID
NTAPI
HalpReboot(VOID)
{
/* Disable interrupts */
_disable();
/* Flush write buffers */
KeFlushWriteBuffer();
/* Send the reset command */
WRITE_PORT_UCHAR((PUCHAR)PPI_IO_o_CONTROL, PPI_SHUTDOWN_0_ENABLE);
WRITE_PORT_UCHAR((PUCHAR)PPI_IO_o_CONTROL, PPI_SHUTDOWN_1_ENABLE);
WRITE_PORT_UCHAR((PUCHAR)CPU_IO_o_RESET, 0);
/* Halt the CPU */
__halt();
}
/* PUBLIC FUNCTIONS **********************************************************/
VOID
NTAPI
HalReturnToFirmware(
_In_ FIRMWARE_REENTRY Action)
{
switch (Action)
{
case HalPowerDownRoutine:
HalpFreezeSystem();
case HalHaltRoutine:
case HalRebootRoutine:
#ifndef _MINIHAL_
/* Acquire the display */
InbvAcquireDisplayOwnership();
#endif
/* Call the internal reboot function */
HalpReboot();
/* Anything else */
default:
/* Print message and break */
DbgPrint("HalReturnToFirmware called!\n");
DbgBreakPoint();
}
}

View file

@ -9,6 +9,7 @@ list(APPEND HAL_PIC_SOURCE
generic/profil.c
generic/timer.c
up/halinit_up.c
up/irql.c
up/pic.c)
add_asm_files(lib_hal_pic_asm ${HAL_PIC_ASM_SOURCE})

View file

@ -1,16 +1,14 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: hal/halx86/up/halinit_up.c
* PURPOSE: Initialize the x86 hal
* PROGRAMMER: David Welch (welch@cwcom.net)
* UPDATE HISTORY:
* 11/06/98: Created
* PROJECT: ReactOS Hardware Abstraction Layer
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: Initialize the x86 HAL
* COPYRIGHT: Copyright 1998 David Welch (welch@cwcom.net)
*/
/* INCLUDES *****************************************************************/
#include <hal.h>
#define NDEBUG
#include <debug.h>
@ -27,7 +25,7 @@ HalpInitProcessor(
IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{
/* Set default IDR */
KeGetPcr()->IDR = 0xFFFFFFFB;
KeGetPcr()->IDR = 0xFFFFFFFF & ~(1 << PIC_CASCADE_IRQ);
}
VOID
@ -39,18 +37,18 @@ HalpInitPhase0(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
VOID
HalpInitPhase1(VOID)
{
/* Enable IRQ 0 */
/* Enable timer interrupt handler */
HalpEnableInterruptHandler(IDT_DEVICE,
0,
PRIMARY_VECTOR_BASE,
PRIMARY_VECTOR_BASE + PIC_TIMER_IRQ,
CLOCK2_LEVEL,
HalpClockInterrupt,
Latched);
/* Enable IRQ 8 */
/* Enable RTC interrupt handler */
HalpEnableInterruptHandler(IDT_DEVICE,
0,
PRIMARY_VECTOR_BASE + 8,
PRIMARY_VECTOR_BASE + PIC_RTC_IRQ,
PROFILE_LEVEL,
HalpProfileInterrupt,
Latched);

163
hal/halx86/up/irql.c Normal file
View file

@ -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 */
};

View file

@ -1,7 +1,6 @@
/*
* PROJECT: ReactOS HAL
* LICENSE: BSD - See COPYING.ARM in the top level directory
* FILE: hal/halx86/up/pic.c
* PURPOSE: HAL PIC Management and Control Code
* PROGRAMMERS: ReactOS Portable Systems Group
*/
@ -9,6 +8,7 @@
/* INCLUDES *******************************************************************/
#include <hal.h>
#define NDEBUG
#include <debug.h>
@ -62,12 +62,20 @@ PHAL_DISMISS_INTERRUPT HalpSpecialDismissTable[16] =
HalpDismissIrqGeneric,
HalpDismissIrqGeneric,
HalpDismissIrq07,
#if defined(SARCH_PC98)
HalpDismissIrq08,
#else
HalpDismissIrqGeneric,
#endif
HalpDismissIrqGeneric,
HalpDismissIrqGeneric,
HalpDismissIrqGeneric,
HalpDismissIrqGeneric,
#if defined(SARCH_PC98)
HalpDismissIrqGeneric,
#else
HalpDismissIrq13,
#endif
HalpDismissIrqGeneric,
HalpDismissIrq15
};
@ -86,166 +94,29 @@ PHAL_DISMISS_INTERRUPT HalpSpecialDismissLevelTable[16] =
HalpDismissIrqLevel,
HalpDismissIrqLevel,
HalpDismissIrq07Level,
#if defined(SARCH_PC98)
HalpDismissIrq08Level,
#else
HalpDismissIrqLevel,
#endif
HalpDismissIrqLevel,
HalpDismissIrqLevel,
HalpDismissIrqLevel,
HalpDismissIrqLevel,
#if defined(SARCH_PC98)
HalpDismissIrqLevel,
#else
HalpDismissIrq13Level,
#endif
HalpDismissIrqLevel,
HalpDismissIrq15Level
};
/* This table contains the static x86 PIC mapping between IRQLs and IRQs */
ULONG KiI8259MaskTable[32] =
{
/*
* It Device IRQLs only start at 4 or higher, so these are just software
* IRQLs that don't really change anything on the hardware
*/
0b00000000000000000000000000000000, /* IRQL 0 */
0b00000000000000000000000000000000, /* IRQL 1 */
0b00000000000000000000000000000000, /* IRQL 2 */
0b00000000000000000000000000000000, /* IRQL 3 */
/*
* These next IRQLs are actually useless from the PIC perspective, because
* with only 2 PICs, the mask you can send them is only 8 bits each, for 16
* bits total, so these IRQLs are masking off a phantom PIC.
*/
0b11111111100000000000000000000000, /* IRQL 4 */
0b11111111110000000000000000000000, /* IRQL 5 */
0b11111111111000000000000000000000, /* IRQL 6 */
0b11111111111100000000000000000000, /* IRQL 7 */
0b11111111111110000000000000000000, /* IRQL 8 */
0b11111111111111000000000000000000, /* IRQL 9 */
0b11111111111111100000000000000000, /* IRQL 10 */
0b11111111111111110000000000000000, /* IRQL 11 */
/*
* Okay, now we're finally starting to mask off IRQs on the slave PIC, from
* IRQ15 to IRQ8. This means the higher-level IRQs get less priority in the
* IRQL sense.
*/
0b11111111111111111000000000000000, /* IRQL 12 */
0b11111111111111111100000000000000, /* IRQL 13 */
0b11111111111111111110000000000000, /* IRQL 14 */
0b11111111111111111111000000000000, /* IRQL 15 */
0b11111111111111111111100000000000, /* IRQL 16 */
0b11111111111111111111110000000000, /* IRQL 17 */
0b11111111111111111111111000000000, /* IRQL 18 */
0b11111111111111111111111000000000, /* IRQL 19 */
/*
* Now we mask off the IRQs on the master. Notice the 0 "droplet"? You might
* have also seen that IRQL 18 and 19 are essentially equal as far as the
* PIC is concerned. That bit is actually IRQ8, which happens to be the RTC.
* The RTC will keep firing as long as we don't reach PROFILE_LEVEL which
* actually kills it. The RTC clock (unlike the system clock) is used by the
* profiling APIs in the HAL, so that explains the logic.
*/
0b11111111111111111111111010000000, /* IRQL 20 */
0b11111111111111111111111011000000, /* IRQL 21 */
0b11111111111111111111111011100000, /* IRQL 22 */
0b11111111111111111111111011110000, /* IRQL 23 */
0b11111111111111111111111011111000, /* IRQL 24 */
0b11111111111111111111111011111000, /* IRQL 25 */
0b11111111111111111111111011111010, /* IRQL 26 */
0b11111111111111111111111111111010, /* IRQL 27 */
/*
* IRQL 24 and 25 are actually identical, so IRQL 28 is actually the last
* IRQL to modify a bit on the master PIC. It happens to modify the very
* last of the IRQs, IRQ0, which corresponds to the system clock interval
* timer that keeps track of time (the Windows heartbeat). We only want to
* turn this off at a high-enough IRQL, which is why IRQLs 24 and 25 are the
* same to give this guy a chance to come up higher. Note that IRQL 28 is
* called CLOCK2_LEVEL, which explains the usage we just explained.
*/
0b11111111111111111111111111111011, /* IRQL 28 */
/*
* We have finished off with the PIC so there's nothing left to mask at the
* level of these IRQLs, making them only logical IRQLs on x86 machines.
* Note that we have another 0 "droplet" you might've caught since IRQL 26.
* In this case, it's the 2nd bit that never gets turned off, which is IRQ2,
* the cascade IRQ that we use to bridge the slave PIC with the master PIC.
* We never want to turn it off, so no matter the IRQL, it will be set to 0.
*/
0b11111111111111111111111111111011, /* IRQL 29 */
0b11111111111111111111111111111011, /* IRQL 30 */
0b11111111111111111111111111111011 /* IRQL 31 */
};
extern ULONG KiI8259MaskTable[32];
/* This table indicates which IRQs, if pending, can preempt a given IRQL level */
ULONG FindHigherIrqlMask[32] =
{
/*
* Software IRQLs, at these levels all hardware interrupts can preempt.
* Each higher IRQL simply enables which software IRQL can preempt the
* current level.
*/
0b11111111111111111111111111111110, /* IRQL 0 */
0b11111111111111111111111111111100, /* IRQL 1 */
0b11111111111111111111111111111000, /* IRQL 2 */
/*
* IRQL3 means only hardware IRQLs can now preempt. These last 4 zeros will
* then continue throughout the rest of the list, trickling down.
*/
0b11111111111111111111111111110000, /* IRQL 3 */
/*
* Just like in the previous list, these masks don't really mean anything
* since we've only got two PICs with 16 possible IRQs total
*/
0b00000111111111111111111111110000, /* IRQL 4 */
0b00000011111111111111111111110000, /* IRQL 5 */
0b00000001111111111111111111110000, /* IRQL 6 */
0b00000000111111111111111111110000, /* IRQL 7 */
0b00000000011111111111111111110000, /* IRQL 8 */
0b00000000001111111111111111110000, /* IRQL 9 */
0b00000000000111111111111111110000, /* IRQL 10 */
/*
* Now we start progressivly limiting which slave PIC interrupts have the
* right to preempt us at each level.
*/
0b00000000000011111111111111110000, /* IRQL 11 */
0b00000000000001111111111111110000, /* IRQL 12 */
0b00000000000000111111111111110000, /* IRQL 13 */
0b00000000000000011111111111110000, /* IRQL 14 */
0b00000000000000001111111111110000, /* IRQL 15 */
0b00000000000000000111111111110000, /* IRQL 16 */
0b00000000000000000011111111110000, /* IRQL 17 */
0b00000000000000000001111111110000, /* IRQL 18 */
0b00000000000000000001111111110000, /* IRQL 19 */
/*
* Also recall from the earlier table that IRQL 18/19 are treated the same
* in order to spread the masks better thoughout the 32 IRQLs and to reflect
* the fact that some bits will always stay on until much higher IRQLs since
* they are system-critical. One such example is the 1 bit that you start to
* see trickling down here. This is IRQ8, the RTC timer used for profiling,
* so it will always preempt until we reach PROFILE_LEVEL.
*/
0b00000000000000000001011111110000, /* IRQL 20 */
0b00000000000000000001001111110000, /* IRQL 21 */
0b00000000000000000001000111110000, /* IRQL 22 */
0b00000000000000000001000011110000, /* IRQL 23 */
0b00000000000000000001000001110000, /* IRQL 24 */
0b00000000000000000001000000110000, /* IRQL 25 */
0b00000000000000000001000000010000, /* IRQL 26 */
/* At this point, only the clock (IRQ0) can still preempt... */
0b00000000000000000000000000010000, /* IRQL 27 */
/* And any higher than that there's no relation with hardware PICs anymore */
0b00000000000000000000000000000000, /* IRQL 28 */
0b00000000000000000000000000000000, /* IRQL 29 */
0b00000000000000000000000000000000, /* IRQL 30 */
0b00000000000000000000000000000000 /* IRQL 31 */
};
extern ULONG FindHigherIrqlMask[32];
/* Denotes minimum required IRQL before we can process pending SW interrupts */
KIRQL SWInterruptLookUpTable[8] =
@ -351,6 +222,7 @@ HalpInitializePICs(IN BOOLEAN EnableInterrupts)
ULONG EFlags;
EISA_ELCR Elcr;
ULONG i, j;
BOOLEAN ElcrFound;
/* Save EFlags and disable interrupts */
EFlags = __readeflags();
@ -362,9 +234,23 @@ HalpInitializePICs(IN BOOLEAN EnableInterrupts)
/* Read EISA Edge/Level Register for master and slave */
Elcr.Bits = (__inbyte(EISA_ELCR_SLAVE) << 8) | __inbyte(EISA_ELCR_MASTER);
#if defined(SARCH_PC98)
/* Force defaults when ELCR is not supported */
if (Elcr.Bits == 0xFFFF)
{
Elcr.Master.Irq0Level = 0;
Elcr.Master.Irq1Level = 0;
Elcr.Master.Irq7Level = 0;
Elcr.Slave.Irq8Level = 0;
}
ElcrFound = TRUE;
#else
/* IRQs 0, 1, 2, 8, and 13 are system-reserved and must be edge */
if (!(Elcr.Master.Irq0Level) && !(Elcr.Master.Irq1Level) && !(Elcr.Master.Irq2Level) &&
!(Elcr.Slave.Irq8Level) && !(Elcr.Slave.Irq13Level))
ElcrFound = (!(Elcr.Master.Irq0Level) && !(Elcr.Master.Irq1Level) && !(Elcr.Master.Irq2Level) &&
!(Elcr.Slave.Irq8Level) && !(Elcr.Slave.Irq13Level));
#endif
if (ElcrFound)
{
/* ELCR is as it's supposed to be, save it */
HalpEisaELCR = Elcr.Bits;
@ -383,10 +269,10 @@ HalpInitializePICs(IN BOOLEAN EnableInterrupts)
}
}
/* Register IRQ 2 */
/* Report cascade IRQ usage */
HalpRegisterVector(IDT_INTERNAL,
PRIMARY_VECTOR_BASE + 2,
PRIMARY_VECTOR_BASE + 2,
PRIMARY_VECTOR_BASE + PIC_CASCADE_IRQ,
PRIMARY_VECTOR_BASE + PIC_CASCADE_IRQ,
HIGH_LEVEL);
/* Restore interrupt state */
@ -690,16 +576,40 @@ _HalpDismissIrqGeneric(IN KIRQL Irql,
/* Check which PIC needs the EOI */
if (Irq >= 8)
{
#if defined(SARCH_PC98)
I8259_OCW3 Ocw3;
I8259_ISR Isr;
/* Send the EOI for the IRQ */
__outbyte(PIC2_CONTROL_PORT, Ocw2.Bits | ((Irq - 8) & 0xFF));
/* 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_ */

View file

@ -14,6 +14,7 @@ list(APPEND HAL_XBOX_SOURCE
generic/halinit.c
generic/memory.c
generic/misc.c
generic/nmi.c
generic/pic.c
generic/sysinfo.c
generic/usage.c
@ -35,16 +36,14 @@ list(APPEND HAL_XBOX_SOURCE
xbox/part_xbox.c
xbox/halinit_xbox.c
xbox/reboot.c
up/irql.c
up/pic.c)
add_asm_files(lib_hal_xbox_asm ${HAL_XBOX_ASM_SOURCE})
add_object_library(lib_hal_xbox ${HAL_XBOX_SOURCE} ${lib_hal_xbox_asm})
if(NOT SARCH STREQUAL "xbox")
target_compile_definitions(lib_hal_xbox PRIVATE SARCH_XBOX)
endif()
add_dependencies(lib_hal_xbox bugcodes xdk asm)
#add_pch(lib_hal_xbox xbox/halxbox.h)
if(MSVC)
target_link_libraries(lib_hal_xbox lib_hal_generic)
target_link_libraries(lib_hal_xbox)
endif()

View file

@ -1,11 +1,8 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: hal/halx86/xbox/halinit_xbox.c
* PURPOSE: Initialize the x86 hal
* PROGRAMMER: David Welch (welch@cwcom.net)
* UPDATE HISTORY:
* 11/06/98: Created
* PROJECT: Xbox HAL
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: Initialize the x86 HAL
* COPYRIGHT: Copyright 1998 David Welch (welch@cwcom.net)
*/
/* INCLUDES *****************************************************************/
@ -28,7 +25,7 @@ HalpInitProcessor(
IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{
/* Set default IDR */
KeGetPcr()->IDR = 0xFFFFFFFB;
KeGetPcr()->IDR = 0xFFFFFFFF & ~(1 << PIC_CASCADE_IRQ);
}
VOID
@ -41,18 +38,18 @@ HalpInitPhase0(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
VOID
HalpInitPhase1(VOID)
{
/* Enable IRQ 0 */
/* Enable timer interrupt handler */
HalpEnableInterruptHandler(IDT_DEVICE,
0,
PRIMARY_VECTOR_BASE,
PRIMARY_VECTOR_BASE + PIC_TIMER_IRQ,
CLOCK2_LEVEL,
HalpClockInterrupt,
Latched);
/* Enable IRQ 8 */
/* Enable RTC interrupt handler */
HalpEnableInterruptHandler(IDT_DEVICE,
0,
PRIMARY_VECTOR_BASE + 8,
PRIMARY_VECTOR_BASE + PIC_RTC_IRQ,
PROFILE_LEVEL,
HalpProfileInterrupt,
Latched);

View file

@ -24,6 +24,7 @@ HKR, , Icon, 0, "-27"
[Manufacturer]
%GenericMfg% = GenericMfg
%MsftMfg% = MsftMfg
%NecMfg% = NecMfg
[GenericMfg]
%acpipic_up.DeviceDesc% = NO_DRV,acpipic_up
@ -32,6 +33,9 @@ HKR, , Icon, 0, "-27"
[MsftMfg]
%xbox.DeviceDesc% = NO_DRV,xbox
[NecMfg]
%pc98_up.DeviceDesc% = NO_DRV,pc98_up
;------------------------------ NO DRIVER -----------------------------
[NO_DRV]
@ -53,6 +57,9 @@ e_isa_up.DeviceDesc = "Standard Uniprocessor PC"
MsftMfg = "Microsoft Corporation"
xbox.DeviceDesc = "Original Xbox (x86 based)"
NecMfg = "NEC"
pc98_up.DeviceDesc = "Uniprocessor NEC PC-98"
[Strings.0405]
ComputerClassName = "Počítač"
GenericMfg = "(Obecné počítače)"
@ -62,6 +69,8 @@ e_isa_up.DeviceDesc = "Standardní jednoprocesorové PC"
MsftMfg = "Microsoft Corporation"
xbox.DeviceDesc = "Original Xbox (x86 based)"
pc98_up.DeviceDesc = "Uniprocessor NEC PC-98"
[Strings.0a]
ReactOS = "Equipo de ReactOS"
@ -74,6 +83,8 @@ e_isa_up.DeviceDesc = "PC con uniprocesador estándar"
MsftMfg = "Microsoft Corporation"
xbox.DeviceDesc = "Original Xbox (x86 based)"
pc98_up.DeviceDesc = "Uniprocessor NEC PC-98"
[Strings.0415]
ReactOS = "Zespół ReactOS"
@ -86,6 +97,8 @@ e_isa_up.DeviceDesc = "Standardowy komputer PC"
MsftMfg = "Microsoft Corporation"
xbox.DeviceDesc = "Original Xbox (x86 based)"
pc98_up.DeviceDesc = "Uniprocessor NEC PC-98"
[Strings.0418]
ReactOS = "Echipa ReactOS"
@ -98,6 +111,8 @@ e_isa_up.DeviceDesc = "PC uniprocesor standard"
MsftMfg = "Microsoft Corporation"
xbox.DeviceDesc = "Original Xbox (x86 based)"
pc98_up.DeviceDesc = "Uniprocessor NEC PC-98"
[Strings.0419]
ReactOS = "Команда ReactOS"
@ -110,6 +125,8 @@ e_isa_up.DeviceDesc = "Стандартный однопроцессорный
MsftMfg = "Корпорация Microsoft"
xbox.DeviceDesc = "Оригинальный Xbox (на базе x86)"
pc98_up.DeviceDesc = "Однопроцессорный NEC PC-98"
[Strings.041f]
ReactOS = "ReactOS Takımı"
@ -122,6 +139,8 @@ e_isa_up.DeviceDesc = "Ölçünlü Tek İşlemcili PC"
MsftMfg = "Microsoft Corporation"
xbox.DeviceDesc = "Original Xbox (x86 based)"
pc98_up.DeviceDesc = "Uniprocessor NEC PC-98"
[Strings.0422]
ReactOS = "Команда ReactOS"
@ -134,6 +153,8 @@ e_isa_up.DeviceDesc = "Стандартний однопроцесорний П
MsftMfg = "Microsoft Corporation"
xbox.DeviceDesc = "Original Xbox (x86 based)"
pc98_up.DeviceDesc = "Однопроцесорний NEC PC-98"
[Strings.0804]
GenericMfg = "(通用计算机)"
acpipic_up.DeviceDesc = "ACPI 单处理器 PC"
@ -141,3 +162,5 @@ e_isa_up.DeviceDesc = "标准单处理器 PC"
MsftMfg = "Microsoft Corporation"
xbox.DeviceDesc = "Original Xbox (x86 based)"
pc98_up.DeviceDesc = "Uniprocessor NEC PC-98"

View file

@ -7,13 +7,15 @@
#pragma once
#define CPU_IO_o_RESET 0x0F
#define CPU_IO_o_RESET 0xF0
#define CPU_IO_o_A20_UNMASK 0xF2
#define CPU_IO_o_A20_CONTROL 0xF6
#define CPU_A20_ENABLE 0x02
#define CPU_A20_DISABLE 0x03
#define CPU_IO_o_FPU_BUSY_LATCH 0xF8
/*
* ARTIC (A Relative Time Indication Counter) - 24-bit binary up counter
*/

View file

@ -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;

View file

@ -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

View file

@ -8,7 +8,12 @@
#pragma once
#define PPI_IO_o_PORT_C 0x35
#define PPI_IO_o_CONTROL 0x37
#define PPI_TIMER_1_GATE_TO_SPEAKER 0x06
#define PPI_TIMER_1_UNGATE_TO_SPEAKER 0x07
#define PPI_SHUTDOWN_1_ENABLE 0x0B
#define PPI_SHUTDOWN_0_ENABLE 0x0F
#define PPI_IO_i_PORT_A 0x31
#define PPI_IO_i_PORT_B 0x33
@ -64,19 +69,3 @@ typedef union _SYSTEM_CONTROL_PORT_C_REGISTER
};
UCHAR Bits;
} SYSTEM_CONTROL_PORT_C_REGISTER, *PSYSTEM_CONTROL_PORT_C_REGISTER;
typedef union _SYSTEM_CONTROL_PORT_REGISTER
{
struct
{
UCHAR InterruptEnableRxReady:1;
UCHAR InterruptEnableTxEmpty:1;
UCHAR InterruptEnableTxReady:1;
UCHAR Timer1GateToSpeaker:1;
UCHAR Mcke:1;
UCHAR Shut1:1;
UCHAR PrinterStrobeSignal:1;
UCHAR Shut0:1;
};
UCHAR Bits;
} SYSTEM_CONTROL_PORT_REGISTER, *PSYSTEM_CONTROL_PORT_REGISTER;