From 5c92d86010c8d572c9bd183e9647ede175d0faf3 Mon Sep 17 00:00:00 2001 From: Tulio A M Mendes Date: Thu, 12 Feb 2026 03:37:06 -0300 Subject: [PATCH] refactor: extract x86 CMOS I/O from drivers/rtc.c to HAL layer Created include/hal/rtc.h with generic HAL RTC interface and src/hal/x86/rtc.c with x86 CMOS port I/O implementation. src/drivers/rtc.c is now fully architecture-agnostic: it calls hal_rtc_read_raw() for hardware access and keeps only the generic BCD-to-binary conversion and UNIX timestamp calculation logic. This follows the same HAL pattern used by timer, keyboard, uart, and video drivers. --- include/hal/rtc.h | 37 ++++++++++++++++++++++++++++++++ src/drivers/rtc.c | 54 +++++++++++------------------------------------ src/hal/x86/rtc.c | 52 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 101 insertions(+), 42 deletions(-) create mode 100644 include/hal/rtc.h create mode 100644 src/hal/x86/rtc.c diff --git a/include/hal/rtc.h b/include/hal/rtc.h new file mode 100644 index 00000000..612797dc --- /dev/null +++ b/include/hal/rtc.h @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2018, Tulio A M Mendes + * All rights reserved. + * See LICENSE for details. + * + * Source: https://github.com/tadryanom/AdrOS + */ + +#ifndef HAL_RTC_H +#define HAL_RTC_H + +#include + +/* + * HAL RTC interface — architecture-specific implementations provide + * raw register reads from the hardware real-time clock. + * + * All values are returned as raw hardware values (may be BCD-encoded + * depending on the platform). The generic driver layer handles + * BCD-to-binary conversion and timestamp calculation. + */ + +struct hal_rtc_raw { + uint8_t second; + uint8_t minute; + uint8_t hour; + uint8_t day; + uint8_t month; + uint8_t year; /* two-digit year from hardware */ + uint8_t status_b; /* status/config register (x86: CMOS reg 0x0B) */ +}; + +void hal_rtc_init(void); +void hal_rtc_read_raw(struct hal_rtc_raw* raw); + +#endif diff --git a/src/drivers/rtc.c b/src/drivers/rtc.c index a75feea5..1d7c18b2 100644 --- a/src/drivers/rtc.c +++ b/src/drivers/rtc.c @@ -8,58 +8,28 @@ */ #include "rtc.h" - -#define CMOS_ADDR 0x70 -#define CMOS_DATA 0x71 - -#define RTC_REG_SEC 0x00 -#define RTC_REG_MIN 0x02 -#define RTC_REG_HOUR 0x04 -#define RTC_REG_DAY 0x07 -#define RTC_REG_MON 0x08 -#define RTC_REG_YEAR 0x09 -#define RTC_REG_STATB 0x0B - -static inline void port_outb(uint16_t port, uint8_t val) { - __asm__ volatile("outb %0, %1" : : "a"(val), "Nd"(port)); -} - -static inline uint8_t port_inb(uint16_t port) { - uint8_t ret; - __asm__ volatile("inb %1, %0" : "=a"(ret) : "Nd"(port)); - return ret; -} - -static uint8_t cmos_read(uint8_t reg) { - port_outb(CMOS_ADDR, reg); - return port_inb(CMOS_DATA); -} - -static int rtc_updating(void) { - port_outb(CMOS_ADDR, 0x0A); - return port_inb(CMOS_DATA) & 0x80; -} +#include "hal/rtc.h" static uint8_t bcd_to_bin(uint8_t v) { return (uint8_t)((v & 0x0F) + ((v >> 4) * 10)); } void rtc_init(void) { - /* Nothing to do — CMOS is always available on x86 */ + hal_rtc_init(); } void rtc_read(struct rtc_time* t) { - while (rtc_updating()) {} + struct hal_rtc_raw raw; + hal_rtc_read_raw(&raw); - t->second = cmos_read(RTC_REG_SEC); - t->minute = cmos_read(RTC_REG_MIN); - t->hour = cmos_read(RTC_REG_HOUR); - t->day = cmos_read(RTC_REG_DAY); - t->month = cmos_read(RTC_REG_MON); - t->year = cmos_read(RTC_REG_YEAR); + t->second = raw.second; + t->minute = raw.minute; + t->hour = raw.hour; + t->day = raw.day; + t->month = raw.month; + t->year = raw.year; - uint8_t statb = cmos_read(RTC_REG_STATB); - int bcd = !(statb & 0x04); + int bcd = !(raw.status_b & 0x04); if (bcd) { t->second = bcd_to_bin(t->second); @@ -72,7 +42,7 @@ void rtc_read(struct rtc_time* t) { t->year += 2000; - if (!(statb & 0x02) && (cmos_read(RTC_REG_HOUR) & 0x80)) { + if (!(raw.status_b & 0x02) && (raw.hour & 0x80)) { t->hour = (uint8_t)((t->hour + 12) % 24); } } diff --git a/src/hal/x86/rtc.c b/src/hal/x86/rtc.c new file mode 100644 index 00000000..a6130916 --- /dev/null +++ b/src/hal/x86/rtc.c @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2018, Tulio A M Mendes + * All rights reserved. + * See LICENSE for details. + * + * Source: https://github.com/tadryanom/AdrOS + */ + +#include "hal/rtc.h" + +#include "arch/x86/io.h" + +#define CMOS_ADDR 0x70 +#define CMOS_DATA 0x71 + +#define RTC_REG_SEC 0x00 +#define RTC_REG_MIN 0x02 +#define RTC_REG_HOUR 0x04 +#define RTC_REG_DAY 0x07 +#define RTC_REG_MON 0x08 +#define RTC_REG_YEAR 0x09 +#define RTC_REG_STATA 0x0A +#define RTC_REG_STATB 0x0B + +static uint8_t cmos_read(uint8_t reg) { + outb(CMOS_ADDR, reg); + return inb(CMOS_DATA); +} + +static int rtc_updating(void) { + outb(CMOS_ADDR, RTC_REG_STATA); + return inb(CMOS_DATA) & 0x80; +} + +void hal_rtc_init(void) { + /* Nothing to do — CMOS is always available on x86 */ +} + +void hal_rtc_read_raw(struct hal_rtc_raw* raw) { + if (!raw) return; + + while (rtc_updating()) {} + + raw->second = cmos_read(RTC_REG_SEC); + raw->minute = cmos_read(RTC_REG_MIN); + raw->hour = cmos_read(RTC_REG_HOUR); + raw->day = cmos_read(RTC_REG_DAY); + raw->month = cmos_read(RTC_REG_MON); + raw->year = cmos_read(RTC_REG_YEAR); + raw->status_b = cmos_read(RTC_REG_STATB); +} -- 2.43.0