My Project
Loading...
Searching...
No Matches
time.h
Go to the documentation of this file.
1/*
2 * PROJECT: MatanelOS Kernel
3 * LICENSE: NONE
4 * PURPOSE: CMOS Time implementation.
5 */
6
7#ifndef X86_TIME_H
8#define X86_TIME_H
9#include <stdint.h>
10#include <stdbool.h>
11#include "intrinsics/intrin.h"
12
13// RTC CMOS ports
14#define CMOS_ADDRESS 0x70
15#define CMOS_DATA 0x71
16
17// TIME_ENTRY struct with full date
18typedef struct {
19 uint8_t second; // 0–59
20 uint8_t minute; // 0–59
21 uint8_t hour; // 0–23
22 uint8_t day; // 1–31
23 uint8_t month; // 1–12
24 uint16_t year; // full year, e.g., 2025
26
27// Read from CMOS
28static inline uint8_t cmos_read(uint8_t reg) {
30 return __inbyte(CMOS_DATA);
31}
32
33// Check if RTC is updating
34static inline bool rtc_updating(void) {
36 return (__inbyte(CMOS_DATA) & 0x80) != 0;
37}
38
39// Convert BCD → binary
40static inline uint8_t bcd_to_bin(uint8_t val) {
41 return ((val >> 4) * 10) + (val & 0x0F);
42}
43
44// Get current time/date (GIVES UTC TIME)
45static TIME_ENTRY get_time(void) {
46 TIME_ENTRY t;
47 uint8_t century = 0;
48 uint8_t regB;
49
50 // Wait until RTC is not updating
51 while (rtc_updating());
52
53 // Read raw values
54 t.second = cmos_read(0x00);
55 t.minute = cmos_read(0x02);
56 t.hour = cmos_read(0x04);
57 t.day = cmos_read(0x07);
58 t.month = cmos_read(0x08);
59 uint8_t year = cmos_read(0x09);
60
61 // Some BIOSes provide century register (0x32) if available
62 century = cmos_read(0x32);
63
64 // Status register B tells us data format
65 regB = cmos_read(0x0B);
66
67 // Convert from BCD if needed
68 if (!(regB & 0x04)) {
69 t.second = bcd_to_bin(t.second);
70 t.minute = bcd_to_bin(t.minute);
71 t.hour = bcd_to_bin(t.hour & 0x7F);
72 t.day = bcd_to_bin(t.day);
73 t.month = bcd_to_bin(t.month);
74 year = bcd_to_bin(year);
75 if (century) century = bcd_to_bin(century);
76 }
77
78 // Convert 12h → 24h if needed
79 if (!(regB & 0x02) && (t.hour & 0x80)) {
80 t.hour = ((t.hour & 0x7F) + 12) % 24;
81 }
82
83 // Build full year
84 if (century != 0) {
85 t.year = (century * 100) + year;
86 }
87 else {
88 // Fallback: assume 20xx
89 t.year = 2000 + year;
90 }
91
92 return t;
93}
94
95static bool is_leap_year(uint16_t year) {
96 return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
97}
98
99static const int days_in_month[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
100
101static uint64_t MeGetEpoch(void) {
102 TIME_ENTRY t = get_time();
103
104 // 1. count total days since 1970
105 uint64_t days = 0;
106 for (uint16_t y = 1970; y < t.year; y++)
107 days += 365 + (is_leap_year(y) ? 1 : 0);
108
109 for (uint8_t m = 1; m < t.month; m++)
110 days += days_in_month[m - 1] + (m == 2 && is_leap_year(t.year) ? 1 : 0);
111
112 days += t.day - 1;
113
114 // 2. convert to seconds
115 uint64_t seconds = days * 86400ULL;
116 seconds += t.hour * 3600ULL;
117 seconds += t.minute * 60ULL;
118 seconds += t.second;
119
120 return seconds;
121}
122#endif
FORCEINLINE void __outbyte(unsigned short port, unsigned char val)
Definition intrin.h:179
FORCEINLINE unsigned char __inbyte(unsigned short port)
Definition intrin.h:172
uint8_t month
Definition time.h:23
uint16_t year
Definition time.h:24
uint8_t day
Definition time.h:22
uint8_t second
Definition time.h:19
uint8_t minute
Definition time.h:20
uint8_t hour
Definition time.h:21
#define CMOS_DATA
Definition time.h:15
#define CMOS_ADDRESS
Definition time.h:14