MOS Source Code
Loading...
Searching...
No Matches
rtc.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-3.0-or-later
2
3#define CURRENT_YEAR 2024
4
6
7#include "mos/assert.hpp"
11
12#include <mos/types.hpp>
13
15 .name = "rtc",
16 .ticks = 0,
17 .frequency = 1000,
18};
19
20static const u8 RTC_STATUS_REG_B = 0x0B;
21static const u8 CMOS_PORT_ADDRESS = 0x70;
22static const u8 CMOS_PORT_DATA = 0x71;
23
29
31{
32 return rtc_read_reg(0x0A) & 0x80;
33}
34
36{
37 u8 last_second;
38 u8 last_minute;
39 u8 last_hour;
40 u8 last_day;
41 u8 last_month;
42 u8 last_year;
43
45 ; // Make sure an update isn't in progress
46 time->second = rtc_read_reg(0x00);
47 time->minute = rtc_read_reg(0x02);
48 time->hour = rtc_read_reg(0x04);
49 time->day = rtc_read_reg(0x07);
50 time->month = rtc_read_reg(0x08);
51 time->year = rtc_read_reg(0x09);
52
53 do
54 {
55 last_second = time->second;
56 last_minute = time->minute;
57 last_hour = time->hour;
58 last_day = time->day;
59 last_month = time->month;
60 last_year = time->year;
61
63 ; // Make sure an update isn't in progress
64 time->second = rtc_read_reg(0x00);
65 time->minute = rtc_read_reg(0x02);
66 time->hour = rtc_read_reg(0x04);
67 time->day = rtc_read_reg(0x07);
68 time->month = rtc_read_reg(0x08);
69 time->year = rtc_read_reg(0x09);
70 } while ((last_second != time->second) || (last_minute != time->minute) || (last_hour != time->hour) || (last_day != time->day) || (last_month != time->month) ||
71 (last_year != time->year));
72
73#define bcd_to_binary(val) (((val) & 0x0F) + ((val) / 16) * 10)
74
75 const u8 registerB = rtc_read_reg(0x0B);
76 if (!(registerB & 0x04))
77 {
78 // BCD to binary values
79 time->second = bcd_to_binary(time->second);
80 time->minute = bcd_to_binary(time->minute);
81 time->hour = ((time->hour & 0x0F) + (((time->hour & 0x70) / 16) * 10)) | (time->hour & 0x80); //
82 time->day = bcd_to_binary(time->day);
83 time->month = bcd_to_binary(time->month);
84 time->year = bcd_to_binary(time->year);
85 }
86
87 if (!(registerB & 0x02) && (time->hour & 0x80))
88 {
89 // 12 hour clock to 24 hour
90 time->hour = ((time->hour & 0x7F) + 12) % 24;
91 }
92
93 time->year += (CURRENT_YEAR / 100) * 100;
94 if (time->year < CURRENT_YEAR)
95 time->year += 100;
96}
97
98bool rtc_irq_handler(u32 irq, void *data)
99{
100 MOS_UNUSED(data);
101 MOS_ASSERT(irq == IRQ_CMOS_RTC);
102 rtc_read_reg(0x0C); // select register C and ack the interrupt
104 return true;
105}
106
108{
109 port_outb(CMOS_PORT_ADDRESS, 0x80 | RTC_STATUS_REG_B); // select register B, and disable NMI
110 const u8 val = port_inb(CMOS_PORT_DATA); // read the current value of register B
111 port_outb(CMOS_PORT_ADDRESS, 0x80 | RTC_STATUS_REG_B); // set the index again (a read will reset the index to register D)
112 port_outb(CMOS_PORT_DATA, val | 0x40); // write the previous value ORed with 0x40. This turns on bit 6 of register B
113
114 rtc_read_reg(0x0C); // select register C and ack the interrupt
116}
#define MOS_ASSERT(cond)
Definition assert.hpp:14
void clocksource_register(clocksource_t *clocksource)
void clocksource_tick(clocksource_t *clocksource)
#define MOS_UNUSED(x)
Definition mos_global.h:65
u16 x86_port_t
Definition port.hpp:8
should_inline void port_outb(u16 port, u8 value)
Definition port.hpp:31
should_inline u8 port_inb(u16 port)
Definition port.hpp:10
static clocksource_t rtc_clocksource
Definition rtc.cpp:14
void rtc_read_time(timeval_t *time)
Definition rtc.cpp:35
static const u8 RTC_STATUS_REG_B
Definition rtc.cpp:20
u8 rtc_is_update_in_progress()
Definition rtc.cpp:30
bool rtc_irq_handler(u32 irq, void *data)
Definition rtc.cpp:98
#define CURRENT_YEAR
Definition rtc.cpp:3
static const u8 CMOS_PORT_ADDRESS
Definition rtc.cpp:21
u8 rtc_read_reg(x86_port_t reg)
Definition rtc.cpp:24
#define bcd_to_binary(val)
void rtc_init()
Definition rtc.cpp:107
static const u8 CMOS_PORT_DATA
Definition rtc.cpp:22
unsigned int u32
Definition types.h:17
unsigned char u8
Definition types.h:15
@ IRQ_CMOS_RTC