66 lines
3.0 KiB
C
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
|