From 2dd1fdf869b487adc377123690214458dafecd76 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Fri, 24 Apr 2026 09:52:07 +0200 Subject: [PATCH] Implement RTC support --- sdk/xtdk/amd64/hltypes.h | 38 ++++- sdk/xtdk/i686/hltypes.h | 40 ++++- sdk/xtdk/rtltypes.h | 13 ++ sdk/xtdk/xtstruct.h | 1 + xtoskrnl/CMakeLists.txt | 1 + xtoskrnl/hl/amd64/rtc.cc | 13 ++ xtoskrnl/hl/i686/rtc.cc | 13 ++ xtoskrnl/hl/x86/rtc.cc | 328 ++++++++++++++++++++++++++++++++++++ xtoskrnl/includes/hl.hh | 1 + xtoskrnl/includes/hl/rtc.hh | 26 +++ 10 files changed, 466 insertions(+), 8 deletions(-) create mode 100644 xtoskrnl/hl/amd64/rtc.cc create mode 100644 xtoskrnl/hl/i686/rtc.cc create mode 100644 xtoskrnl/hl/x86/rtc.cc create mode 100644 xtoskrnl/includes/hl/rtc.hh diff --git a/sdk/xtdk/amd64/hltypes.h b/sdk/xtdk/amd64/hltypes.h index fde488f..86d7922 100644 --- a/sdk/xtdk/amd64/hltypes.h +++ b/sdk/xtdk/amd64/hltypes.h @@ -54,10 +54,6 @@ /* Maximum number of I/O APICs */ #define APIC_MAX_IOAPICS 64 -/* CMOS controller I/O ports */ -#define CMOS_ADDRESS_PORT 0x70 -#define CMOS_DATA_PORT 0x71 - /* I/O APIC base address */ #define IOAPIC_DEFAULT_BASE 0xFEC00000 @@ -94,6 +90,40 @@ #define PIT_DATA_PORT1 0x41 #define PIT_DATA_PORT2 0x42 +/* CMOS controller access ports */ +#define CMOS_SELECT_PORT 0x70 +#define CMOS_DATA_PORT 0x71 + +/* CMOD Select port definitions */ +#define CMOS_NMI_SELECT 0x80 +#define CMOS_REGISTER_SECOND 0x00 +#define CMOS_REGISTER_MINUTE 0x02 +#define CMOS_REGISTER_HOUR 0x04 +#define CMOS_REGISTER_WEEKDAY 0x06 +#define CMOS_REGISTER_DAY 0x07 +#define CMOS_REGISTER_MONTH 0x08 +#define CMOS_REGISTER_YEAR 0x09 +#define CMOS_REGISTER_A 0x0A +#define CMOS_REGISTER_B 0x0B +#define CMOS_REGISTER_C 0x0C + +/* CMOS Register A definitions */ +#define CMOS_REGISTER_A_RATE_MASK 0x0F +#define CMOS_REGISTER_A_UPDATE_IN_PROGRESS 0x80 + +/* CMOS Register B definitions */ +#define CMOS_REGISTER_B_24_HOUR 0x02 +#define CMOS_REGISTER_B_BINARY 0x04 +#define CMOS_REGISTER_B_PERIODIC 0x40 +#define CMOS_REGISTER_B_SET_CLOCK 0x80 + +/* CMOS Register C definitions */ +#define CMOS_REGISTER_C_PERIODIC 0x40 +#define CMOS_REGISTER_C_INTERRUPT 0x80 + +/* CMOS RTC 24-hour mode */ +#define CMOS_RTC_POST_MERIDIEM 0x80 + /* Serial ports information */ #define COMPORT_ADDRESS {0x3F8, 0x2F8, 0x3E8, 0x2E8, 0x5F8, 0x4F8, 0x5E8, 0x4E8} #define COMPORT_COUNT 8 diff --git a/sdk/xtdk/i686/hltypes.h b/sdk/xtdk/i686/hltypes.h index 973328a..d084439 100644 --- a/sdk/xtdk/i686/hltypes.h +++ b/sdk/xtdk/i686/hltypes.h @@ -60,10 +60,6 @@ /* Maximum number of I/O APICs */ #define APIC_MAX_IOAPICS 64 -/* CMOS controller I/O ports */ -#define CMOS_ADDRESS_PORT 0x70 -#define CMOS_DATA_PORT 0x71 - /* I/O APIC base address */ #define IOAPIC_DEFAULT_BASE 0xFEC00000 @@ -99,6 +95,42 @@ /* PIT ports definitions */ #define PIT_COMMAND_PORT 0x43 #define PIT_DATA_PORT0 0x40 +#define PIT_DATA_PORT1 0x41 +#define PIT_DATA_PORT2 0x42 + +/* CMOS controller access ports */ +#define CMOS_SELECT_PORT 0x70 +#define CMOS_DATA_PORT 0x71 + +/* CMOD Select port definitions */ +#define CMOS_NMI_SELECT 0x80 +#define CMOS_REGISTER_SECOND 0x00 +#define CMOS_REGISTER_MINUTE 0x02 +#define CMOS_REGISTER_HOUR 0x04 +#define CMOS_REGISTER_WEEKDAY 0x06 +#define CMOS_REGISTER_DAY 0x07 +#define CMOS_REGISTER_MONTH 0x08 +#define CMOS_REGISTER_YEAR 0x09 +#define CMOS_REGISTER_A 0x0A +#define CMOS_REGISTER_B 0x0B +#define CMOS_REGISTER_C 0x0C + +/* CMOS Register A definitions */ +#define CMOS_REGISTER_A_RATE_MASK 0x0F +#define CMOS_REGISTER_A_UPDATE_IN_PROGRESS 0x80 + +/* CMOS Register B definitions */ +#define CMOS_REGISTER_B_24_HOUR 0x02 +#define CMOS_REGISTER_B_BINARY 0x04 +#define CMOS_REGISTER_B_PERIODIC 0x40 +#define CMOS_REGISTER_B_SET_CLOCK 0x80 + +/* CMOS Register C definitions */ +#define CMOS_REGISTER_C_PERIODIC 0x40 +#define CMOS_REGISTER_C_INTERRUPT 0x80 + +/* CMOS RTC 24-hour mode */ +#define CMOS_RTC_POST_MERIDIEM 0x80 /* Serial ports information */ #define COMPORT_ADDRESS {0x3F8, 0x2F8, 0x3E8, 0x2E8, 0x5F8, 0x4F8, 0x5E8, 0x4E8} diff --git a/sdk/xtdk/rtltypes.h b/sdk/xtdk/rtltypes.h index dcadf39..b31c3f7 100644 --- a/sdk/xtdk/rtltypes.h +++ b/sdk/xtdk/rtltypes.h @@ -111,5 +111,18 @@ typedef struct _RTL_SHA1_CONTEXT UCHAR Buffer[SHA1_BLOCK_SIZE]; } RTL_SHA1_CONTEXT, *PRTL_SHA1_CONTEXT; +/* Runtime time fields structure definition */ +typedef struct _TIME_FIELDS +{ + SHORT Year; + SHORT Month; + SHORT Day; + SHORT Hour; + SHORT Minute; + SHORT Second; + SHORT Milliseconds; + SHORT Weekday; +} TIME_FIELDS, *PTIME_FIELDS; + #endif /* __XTOS_ASSEMBLER__ */ #endif /* __XTDK_RTLTYPES_H */ diff --git a/sdk/xtdk/xtstruct.h b/sdk/xtdk/xtstruct.h index c9c0e75..b9e1ce5 100644 --- a/sdk/xtdk/xtstruct.h +++ b/sdk/xtdk/xtstruct.h @@ -335,6 +335,7 @@ typedef struct _STRING STRING, *PSTRING; typedef struct _STRING32 STRING32, *PSTRING32; typedef struct _STRING64 STRING64, *PSTRING64; typedef struct _THREAD_INFORMATION_BLOCK THREAD_INFORMATION_BLOCK, *PTHREAD_INFORMATION_BLOCK; +typedef struct _TIME_FIELDS TIME_FIELDS, *PTIME_FIELDS; typedef struct _UEFI_FIRMWARE_INFORMATION UEFI_FIRMWARE_INFORMATION, *PUEFI_FIRMWARE_INFORMATION; typedef struct _UNICODE_STRING UNICODE_STRING, *PUNICODE_STRING; typedef struct _UNICODE_STRING32 UNICODE_STRING32, *PUNICODE_STRING32; diff --git a/xtoskrnl/CMakeLists.txt b/xtoskrnl/CMakeLists.txt index 712a26f..a0c48bd 100644 --- a/xtoskrnl/CMakeLists.txt +++ b/xtoskrnl/CMakeLists.txt @@ -21,6 +21,7 @@ list(APPEND XTOSKRNL_SOURCE ${XTOSKRNL_SOURCE_DIR}/hl/${ARCH}/ioport.cc ${XTOSKRNL_SOURCE_DIR}/hl/${ARCH}/irq.cc ${XTOSKRNL_SOURCE_DIR}/hl/${ARCH}/pic.cc + ${XTOSKRNL_SOURCE_DIR}/hl/${ARCH}/rtc.cc ${XTOSKRNL_SOURCE_DIR}/hl/${ARCH}/runlevel.cc ${XTOSKRNL_SOURCE_DIR}/hl/${ARCH}/timer.cc ${XTOSKRNL_SOURCE_DIR}/hl/acpi.cc diff --git a/xtoskrnl/hl/amd64/rtc.cc b/xtoskrnl/hl/amd64/rtc.cc new file mode 100644 index 0000000..b565bf3 --- /dev/null +++ b/xtoskrnl/hl/amd64/rtc.cc @@ -0,0 +1,13 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtoskrnl/hl/amd64/rtc.cc + * DESCRIPTION: Hardware Real-Time Clock (RTC) support + * DEVELOPERS: Aiken Harris + */ + +#include + + +/* Include common RTC interface */ +#include ARCH_COMMON(rtc.cc) diff --git a/xtoskrnl/hl/i686/rtc.cc b/xtoskrnl/hl/i686/rtc.cc new file mode 100644 index 0000000..b8d42a2 --- /dev/null +++ b/xtoskrnl/hl/i686/rtc.cc @@ -0,0 +1,13 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtoskrnl/hl/i686/rtc.cc + * DESCRIPTION: Hardware Real-Time Clock (RTC) support + * DEVELOPERS: Aiken Harris + */ + +#include + + +/* Include common RTC interface */ +#include ARCH_COMMON(rtc.cc) diff --git a/xtoskrnl/hl/x86/rtc.cc b/xtoskrnl/hl/x86/rtc.cc new file mode 100644 index 0000000..1eebd1c --- /dev/null +++ b/xtoskrnl/hl/x86/rtc.cc @@ -0,0 +1,328 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtoskrnl/hl/x86/rtc.cc + * DESCRIPTION: Hardware Real-Time Clock (RTC) support + * DEVELOPERS: Aiken Harris + */ + +#include + + +/** + * Queries the hardware Real-Time Clock (RTC) for the current date and time. + * + * @param Time + * Supplies a pointer to a structure to receive the system time. + * + * @return This routine returns the status code. + * + * @since XT 1.0 + */ +XTAPI +XTSTATUS +HL::Rtc::GetRealTimeClock(OUT PTIME_FIELDS Time) +{ + UCHAR Century1, Century2, CenturyRegister, RegisterB; + TIME_FIELDS TimeProbe1, TimeProbe2; + PACPI_FADT FadtTable; + BOOLEAN PostMeridiem; + XTSTATUS Status; + ULONG Index; + + /* Locate the ACPI FADT table */ + Status = HL::Acpi::GetAcpiTable(ACPI_FADT_SIGNATURE, (PACPI_DESCRIPTION_HEADER*)&FadtTable); + if(Status == STATUS_SUCCESS && FadtTable && FadtTable->CenturyAlarmIndex) + { + /* Cache the dynamically provided Century register index */ + CenturyRegister = FadtTable->CenturyAlarmIndex; + } + else + { + /* Century register is unavailable */ + CenturyRegister = 0; + Century1 = 0; + Century2 = 0; + } + + /* Read the RTC Status Register B to determine hardware data formats */ + RegisterB = HL::Firmware::ReadCmosRegister(CMOS_REGISTER_B); + + /* Assume failure */ + Status = STATUS_UNSUCCESSFUL; + + /* Execute a maximum of 100 retries to obtain a stable RTC snapshot */ + for(Index = 0; Index < 100; Index++) + { + /* Wait until the RTC hardware finishes any ongoing background updates */ + while(HL::Firmware::ReadCmosRegister(CMOS_REGISTER_A) & CMOS_REGISTER_A_UPDATE_IN_PROGRESS) + { + /* Yield the processor */ + AR::CpuFunc::YieldProcessor(); + } + + /* Latch the first sequential hardware time snapshot */ + TimeProbe1.Hour = HL::Firmware::ReadCmosRegister(CMOS_REGISTER_HOUR); + TimeProbe1.Minute = HL::Firmware::ReadCmosRegister(CMOS_REGISTER_MINUTE); + TimeProbe1.Second = HL::Firmware::ReadCmosRegister(CMOS_REGISTER_SECOND); + TimeProbe1.Day = HL::Firmware::ReadCmosRegister(CMOS_REGISTER_DAY); + TimeProbe1.Month = HL::Firmware::ReadCmosRegister(CMOS_REGISTER_MONTH); + TimeProbe1.Year = HL::Firmware::ReadCmosRegister(CMOS_REGISTER_YEAR); + TimeProbe1.Weekday = HL::Firmware::ReadCmosRegister(CMOS_REGISTER_WEEKDAY); + + /* Check if Century register is available */ + if(CenturyRegister) + { + /* Read the corresponding Century register */ + Century1 = HL::Firmware::ReadCmosRegister(CenturyRegister); + } + + /* Wait until the RTC hardware finishes any ongoing background updates */ + while(HL::Firmware::ReadCmosRegister(CMOS_REGISTER_A) & CMOS_REGISTER_A_UPDATE_IN_PROGRESS) + { + /* Yield the processor */ + AR::CpuFunc::YieldProcessor(); + } + + /* Latch the second sequential hardware time snapshot for verification */ + TimeProbe2.Hour = HL::Firmware::ReadCmosRegister(CMOS_REGISTER_HOUR); + TimeProbe2.Minute = HL::Firmware::ReadCmosRegister(CMOS_REGISTER_MINUTE); + TimeProbe2.Second = HL::Firmware::ReadCmosRegister(CMOS_REGISTER_SECOND); + TimeProbe2.Day = HL::Firmware::ReadCmosRegister(CMOS_REGISTER_DAY); + TimeProbe2.Month = HL::Firmware::ReadCmosRegister(CMOS_REGISTER_MONTH); + TimeProbe2.Year = HL::Firmware::ReadCmosRegister(CMOS_REGISTER_YEAR); + TimeProbe2.Weekday = HL::Firmware::ReadCmosRegister(CMOS_REGISTER_WEEKDAY); + + /* Check if Century register is available */ + if(CenturyRegister) + { + /* Read the corresponding Century register */ + Century2 = HL::Firmware::ReadCmosRegister(CenturyRegister); + } + + /* Compare both snapshots to guarantee data consistency */ + if((TimeProbe1.Hour == TimeProbe2.Hour) && + (TimeProbe1.Minute == TimeProbe2.Minute) && + (TimeProbe1.Second == TimeProbe2.Second) && + (TimeProbe1.Day == TimeProbe2.Day) && + (TimeProbe1.Month == TimeProbe2.Month) && + (TimeProbe1.Year == TimeProbe2.Year) && + (TimeProbe1.Weekday == TimeProbe2.Weekday) && + (Century1 == Century2)) + { + /* A stable time sample was acquired, break the loop */ + Status = STATUS_SUCCESS; + break; + } + } + + /* Copy the validated data into the output buffer */ + Time->Hour = TimeProbe1.Hour; + Time->Minute = TimeProbe1.Minute; + Time->Second = TimeProbe1.Second; + Time->Milliseconds = 0; + Time->Day = TimeProbe1.Day; + Time->Month = TimeProbe1.Month; + Time->Year = TimeProbe1.Year; + Time->Weekday = TimeProbe1.Weekday; + + /* Check if RTC is operating in 12-hour mode */ + if(!(RegisterB & CMOS_REGISTER_B_24_HOUR)) + { + /* Cache the PM status and strip the hardware flag */ + PostMeridiem = (Time->Hour & CMOS_RTC_POST_MERIDIEM) != 0; + Time->Hour &= ~CMOS_RTC_POST_MERIDIEM; + } + + /* Convert Binary-Coded Decimal (BCD) values to standard integers if necessary */ + if(!(RegisterB & CMOS_REGISTER_B_BINARY)) + { + /* Decode all standard time fields */ + Time->Hour = BCD_TO_DECIMAL(Time->Hour); + Time->Minute = BCD_TO_DECIMAL(Time->Minute); + Time->Second = BCD_TO_DECIMAL(Time->Second); + Time->Day = BCD_TO_DECIMAL(Time->Day); + Time->Month = BCD_TO_DECIMAL(Time->Month); + Time->Year = BCD_TO_DECIMAL(Time->Year); + Time->Weekday = BCD_TO_DECIMAL(Time->Weekday); + + /* Check if Century byte is available */ + if(CenturyRegister) + { + /* Convert Century byte */ + Century1 = BCD_TO_DECIMAL(Century1); + } + } + + /* Standardize hours into a strict 24-hour format */ + if(!(RegisterB & CMOS_REGISTER_B_24_HOUR)) + { + /* Adjust for midnight and noon boundary cases */ + if(Time->Hour == 12) + { + /* 12 AM evaluates to 00:00, 12 PM evaluates to 12:00 */ + Time->Hour = PostMeridiem ? 12 : 0; + } + else + { + /* Add 12 hours for PM times */ + Time->Hour += PostMeridiem ? 12 : 0; + } + } + + /* Merge the century offset with the 2-digit hardware year */ + if(Century1 >= 19 && Century1 <= 30) + { + /* Utilize the hardware-provided century base */ + Time->Year += (Century1 * 100); + } + else + { + /* Century byte is invalid; apply the sliding window */ + Time->Year += (Time->Year > 80) ? 1900 : 2000; + } + + /* Return status code */ + return Status; +} + +/** + * Updates the hardware Real-Time Clock (RTC) with the provided date and time. + * + * @param Time + * Supplies a pointer to a structure with populated data and time. + * + * @return This routine returns the status code. + * + * @since XT 1.0 + */ +XTAPI +XTSTATUS +HL::Rtc::SetRealTimeClock(IN PTIME_FIELDS Time) +{ + UCHAR Century, CenturyRegister, RegisterB; + TIME_FIELDS SystemTime; + BOOLEAN PostMeridiem; + PACPI_FADT FadtTable; + XTSTATUS Status; + + /* Validate the input time boundaries against calendar limits */ + if(Time->Hour > 23 || Time->Minute > 59 || Time->Second > 59 || + Time->Day == 0 || Time->Day > 31 || Time->Month == 0 || + Time->Month > 12 || Time->Weekday == 0 || Time->Weekday > 7) + { + /* Invalid time parameters, return error code */ + return STATUS_INVALID_PARAMETER; + } + + /* Assume Ante Meridiem */ + PostMeridiem = FALSE; + + /* Extract local copy */ + SystemTime.Hour = Time->Hour; + SystemTime.Minute = Time->Minute; + SystemTime.Second = Time->Second; + SystemTime.Day = Time->Day; + SystemTime.Month = Time->Month; + SystemTime.Year = (Time->Year % 100); + SystemTime.Weekday = Time->Weekday; + Century = (UCHAR)(Time->Year / 100); + + /* Locate the ACPI FADT table */ + Status = HL::Acpi::GetAcpiTable(ACPI_FADT_SIGNATURE, (PACPI_DESCRIPTION_HEADER*)&FadtTable); + if(Status == STATUS_SUCCESS && FadtTable && FadtTable->CenturyAlarmIndex) + { + /* Cache the dynamically provided Century register index */ + CenturyRegister = FadtTable->CenturyAlarmIndex; + } + else + { + /* Century register is unavailable */ + CenturyRegister = 0; + } + + /* Read the RTC Status Register B to determine hardware data formats */ + RegisterB = HL::Firmware::ReadCmosRegister(CMOS_REGISTER_B); + + /* Format hours if the hardware is running in 12-hour mode */ + if(!(RegisterB & CMOS_REGISTER_B_24_HOUR)) + { + /* Determine if the time is PM */ + PostMeridiem = (SystemTime.Hour >= 12); + + /* Adjust for midnight and noon boundary cases */ + if(SystemTime.Hour == 0) + { + /* Midnight evaluates to 12 AM */ + SystemTime.Hour = 12; + } + else if(SystemTime.Hour > 12) + { + /* Post-noon hour */ + SystemTime.Hour -= 12; + } + + /* Convert to BCD first if needed and apply the hardware PM flag */ + if(!(RegisterB & CMOS_REGISTER_B_BINARY)) + { + /* Encode to BCD */ + SystemTime.Hour = DECIMAL_TO_BCD(SystemTime.Hour); + } + + /* Apply the hardware PM flag to the highest bit */ + if(PostMeridiem) + { + /* Set PM flag */ + SystemTime.Hour |= CMOS_RTC_POST_MERIDIEM; + } + } + else + { + /* 24-hour mode, simply encode to BCD if necessary */ + if(!(RegisterB & CMOS_REGISTER_B_BINARY)) + { + /* Encode to BCD */ + SystemTime.Hour = DECIMAL_TO_BCD(SystemTime.Hour); + } + } + + /* Convert remaining standard fields to BCD if necessary */ + if(!(RegisterB & CMOS_REGISTER_B_BINARY)) + { + /* Encode all standard time fields */ + SystemTime.Minute = DECIMAL_TO_BCD(SystemTime.Minute); + SystemTime.Second = DECIMAL_TO_BCD(SystemTime.Second); + SystemTime.Day = DECIMAL_TO_BCD(SystemTime.Day); + SystemTime.Month = DECIMAL_TO_BCD(SystemTime.Month); + SystemTime.Year = DECIMAL_TO_BCD(SystemTime.Year); + SystemTime.Weekday = DECIMAL_TO_BCD((UCHAR)SystemTime.Weekday); + + /* Encode the Century byte */ + Century = DECIMAL_TO_BCD(Century); + } + + /* Freeze the RTC to prevent data tearing */ + HL::Firmware::WriteCmosRegister(CMOS_REGISTER_B, RegisterB | CMOS_REGISTER_B_SET_CLOCK); + + /* Push the formatted time values into the hardware registers */ + HL::Firmware::WriteCmosRegister(CMOS_REGISTER_HOUR, SystemTime.Hour); + HL::Firmware::WriteCmosRegister(CMOS_REGISTER_MINUTE, SystemTime.Minute); + HL::Firmware::WriteCmosRegister(CMOS_REGISTER_SECOND, SystemTime.Second); + HL::Firmware::WriteCmosRegister(CMOS_REGISTER_DAY, SystemTime.Day); + HL::Firmware::WriteCmosRegister(CMOS_REGISTER_MONTH, SystemTime.Month); + HL::Firmware::WriteCmosRegister(CMOS_REGISTER_YEAR, SystemTime.Year); + HL::Firmware::WriteCmosRegister(CMOS_REGISTER_WEEKDAY, SystemTime.Weekday); + + /* Check if Century register is available */ + if(CenturyRegister) + { + /* Write the corresponding Century register */ + HL::Firmware::WriteCmosRegister(CenturyRegister, Century); + } + + /* Unfreeze the RTC */ + HL::Firmware::WriteCmosRegister(CMOS_REGISTER_B, RegisterB); + + /* Return success status code */ + return STATUS_SUCCESS; +} diff --git a/xtoskrnl/includes/hl.hh b/xtoskrnl/includes/hl.hh index 2949ed3..f968069 100644 --- a/xtoskrnl/includes/hl.hh +++ b/xtoskrnl/includes/hl.hh @@ -21,6 +21,7 @@ #include #include #include +#include #include #include diff --git a/xtoskrnl/includes/hl/rtc.hh b/xtoskrnl/includes/hl/rtc.hh new file mode 100644 index 0000000..476d969 --- /dev/null +++ b/xtoskrnl/includes/hl/rtc.hh @@ -0,0 +1,26 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtoskrnl/includes/hl/rtc.hh + * DESCRIPTION: Hardware Real-Time Clock (RTC) support + * DEVELOPERS: Aiken Harris + */ + +#ifndef __XTOSKRNL_HL_RTC_HH +#define __XTOSKRNL_HL_RTC_HH + +#include + + +/* Hardware Layer */ +namespace HL +{ + class Rtc + { + public: + STATIC XTAPI XTSTATUS GetRealTimeClock(OUT PTIME_FIELDS Time); + STATIC XTAPI XTSTATUS SetRealTimeClock(IN PTIME_FIELDS Time); + }; +} + +#endif /* __XTOSKRNL_HL_RTC_HH */