Files

66 lines
3.0 KiB
C

#ifndef FROSTBYTE_RTC_H
#define FROSTBYTE_RTC_H
#include "types.h"
/*
* CMOS real-time clock driver (MC146818-compatible, ports 0x70/0x71) --
* the first source of real wall-clock date/time this kernel has ever had.
* Every other notion of "time" in frostbyte (pit.h's tick counter,
* threadSleep, userAlarm) is relative to boot, not to the calendar; this
* is the piece that lets a process ask "what day is it" at all.
*
* Honest limitation, same spirit as syscall.c's own documented fork()-less
* design: the CMOS century register's index is not standardized (it is
* only discoverable via the ACPI FADT table, which this kernel does not
* parse), so rtcReadDateTime hardcodes the century to 20 -- correct for
* any date from 2000 through 2099, which covers every real boot this
* kernel will ever see, but not a documented general-purpose solution.
*/
typedef struct RtcDateTime {
int64 year; /* full year, e.g. 2026 */
int64 month; /* 1-12 */
int64 day; /* 1-31 */
int64 hour; /* 0-23, already normalized out of 12-hour/PM if needed */
int64 minute; /* 0-59 */
int64 second; /* 0-59 */
} RtcDateTime;
/* Converts a single CMOS BCD byte (e.g. 0x59) to its binary value (59).
Exposed on its own, like ata.c's ataModelString, because it is a real
piece of the conversion pipeline worth testing in isolation from any
hardware access. */
uint8 rtcBcdToBinary(uint8 bcd);
/* Reads the current date/time off the CMOS RTC. Polls Status Register A's
Update-In-Progress bit (bounded, like ata.c's ataPollTimeout) before
each of two back-to-back raw reads and only accepts the result once both
raw reads agree byte-for-byte, which rules out a read torn mid-tick by
the RTC's own once-a-second update. Returns false only if the two raw
reads never agreed within the bounded retry budget (never hangs). */
bool rtcReadDateTime(RtcDateTime* out);
/* Civil calendar date/time -> seconds since the Unix epoch
(1970-01-01T00:00:00Z), via Howard Hinnant's days_from_civil algorithm
(proleptic Gregorian, correct for any year the RtcDateTime fields above
can represent). Pure arithmetic, no hardware access -- deterministic and
testable without a real clock. */
int64 rtcEpochSeconds(const RtcDateTime* dt);
/* rtcReadDateTime + rtcEpochSeconds in one call, the usual entry point for
anything that just wants "now" as a plain integer (sysTime, syscall.c).
Returns 0 if the underlying read failed. */
int64 rtcNow(void);
/* Seconds since the Unix epoch -> civil calendar date/time, the exact
inverse of rtcEpochSeconds above (Howard Hinnant's civil_from_days,
proleptic Gregorian, same algorithm family as daysFromCivil in rtc.c).
Correct for any epochSeconds value representable in int64, including
negative ones (dates before 1970). Pure arithmetic, no hardware access
-- the piece sfs.h's on-disk mtime/ctime (raw epoch integers) needs to
become a human-readable date, e.g. for a shell `ls -l`. */
void rtcCivilFromEpoch(int64 epochSeconds, RtcDateTime* out);
#endif