AquilaOS documentation
How it works, and its code
Loading...
Searching...
No Matches
cmos.c
Go to the documentation of this file.
1
6
7#include <core/system.h>
8#include <core/types.h>
9#include <cpu/io.h>
10
11#define RTC_SEC 0x00 /* seconds */
12#define RTC_MIN 0x02 /* minutes */
13#define RTC_HRS 0x04 /* hours */
14#define RTC_WD 0x06 /* the day of the week */
15#define RTC_DOM 0x07 /* the day of the month */
16#define RTC_MON 0x08 /* the month */
17#define RTC_YR 0x09 /* the year */
18#define RTC_SA 0x0A /* status register A */
19#define RTC_SB 0x0B /* status register B */
20
21#define RTC_UIP 0x80 /* an update in progress (status A) */
22#define RTC_24H 0x02 /* 24-hour mode (status B) */
23#define RTC_BIN 0x04 /* binary mode, else BCD (status B) */
24#define RTC_PM 0x80 /* the PM flag in the hours (12-hour mode) */
25
26static struct ioaddr cmos;
27
31{
32 io_out8(&cmos, 0, reg & 0x7F);
33 return io_in8(&cmos, 1);
34}
35
46
48static inline uint8_t bcd_to_bin(uint8_t bcd)
49{
50 return ((bcd >> 4) & 0xF) * 10 + (bcd & 0xF);
51}
52
55static int cmos_time(struct cmos_rtc *rtc)
56{
58
59 /* wait for an update in progress to finish, so that the values read
60 * are consistent; bounded, since a machine without a CMOS clock reads
61 * all ones, an update that never ends (an update takes 2 ms at most) */
62 for (int i = 0; i < 1000000 && (cmos_reg_read(RTC_SA) & RTC_UIP); ++i)
63 ;
64
65 rtc->yr = cmos_reg_read(RTC_YR);
72
73 /* the PM flag only means something in 12-hour mode */
74 int pm = !(fmt & RTC_24H) && (rtc->hrs & RTC_PM);
75 rtc->hrs &= ~RTC_PM;
76
77 if (!(fmt & RTC_BIN)) {
78 /* convert the values from BCD to binary */
79 rtc->yr = bcd_to_bin(rtc->yr);
80 rtc->mon = bcd_to_bin(rtc->mon);
81 rtc->mday = bcd_to_bin(rtc->mday);
82 rtc->hrs = bcd_to_bin(rtc->hrs);
83 rtc->min = bcd_to_bin(rtc->min);
84 rtc->sec = bcd_to_bin(rtc->sec);
85 rtc->wday = bcd_to_bin(rtc->wday);
86 }
87
88 if (!(fmt & RTC_24H)) {
89 /* 12-hour mode: 12 AM is 0, 12 PM is 12 */
90 rtc->hrs %= 12;
91 if (pm) rtc->hrs += 12;
92 }
93
94 return 0;
95}
96
97/*
98 * Reads the date and time from the real time clock, as UNIX time.
99 */
100int arch_time_get(struct timespec *ts)
101{
102 struct cmos_rtc rtc;
103 cmos_time(&rtc);
104
105 time_t time = 0;
106 uint32_t yr = rtc.yr + 2000;
107 uint32_t mon = rtc.mon;
108
109 /* the formula below counts months from March, so January and
110 * February are months 13 and 14 of the previous year */
111 if (mon <= 2) {
112 mon += 12;
113 yr -= 1;
114 }
115
116 /* the years, in days */
117 time = (365 * yr) + (yr / 4) - (yr / 100) + (yr / 400);
118 /* the months and days, in days */
119 time += (30 * mon) + (3 * (mon + 1) / 5) + rtc.mday;
120 /* UNIX time starts on January 1st, 1970 */
121 time -= 719561;
122 /* the days, in seconds */
123 time *= 86400;
124 /* and the time of day */
125 time += (3600 * rtc.hrs) + (60 * rtc.min) + rtc.sec;
126
127 ts->tv_sec = time;
128 ts->tv_nsec = 0;
129
130 return 0;
131}
132
140{
141 cmos = *ioaddr;
142 printk("cmos: initializing [%p (%s)]\n", cmos.addr, ioaddr_type_str(&cmos));
143
144 return 0;
145}
static uint8_t io_in8(struct ioaddr *io, uintptr_t off)
Reads an 8-, 16- or 32-bit register.
Definition io.h:28
static void io_out8(struct ioaddr *io, uintptr_t off, uint8_t val)
Writes an 8-, 16- or 32-bit register.
Definition io.h:44
static char * ioaddr_type_str(struct ioaddr *io)
Definition io.h:101
#define RTC_DOM
Definition cmos.c:15
#define RTC_SEC
Definition cmos.c:11
#define RTC_UIP
Definition cmos.c:21
#define RTC_SB
Definition cmos.c:19
#define RTC_MIN
Definition cmos.c:12
static struct ioaddr cmos
Definition cmos.c:26
#define RTC_MON
Definition cmos.c:16
#define RTC_WD
Definition cmos.c:14
#define RTC_YR
Definition cmos.c:17
#define RTC_SA
Definition cmos.c:18
static uint8_t cmos_reg_read(uint8_t reg)
Reads a CMOS register.
Definition cmos.c:30
static uint8_t bcd_to_bin(uint8_t bcd)
Converts a BCD byte to binary.
Definition cmos.c:48
#define RTC_BIN
Definition cmos.c:23
#define RTC_24H
Definition cmos.c:22
#define RTC_PM
Definition cmos.c:24
static int cmos_time(struct cmos_rtc *rtc)
Reads the real time clock's date and time, in binary and in 24-hour time.
Definition cmos.c:55
#define RTC_HRS
Definition cmos.c:13
int x86_cmos_setup(struct ioaddr *ioaddr)
Sets where the CMOS's ports are.
Definition cmos.c:139
int printk(const char *fmt,...)
Writes a kernel message, to the message buffer and the consoles.
Definition printk.c:249
int arch_time_get(struct timespec *ts)
Reads the date and time from the real time clock.
Definition rtc.c:16
unsigned int uint32_t
Definition stddef.h:22
unsigned char uint8_t
Definition stddef.h:20
The real time clock's date and time, as it keeps them.
Definition cmos.c:37
uint8_t mon
Definition cmos.c:39
uint8_t mday
Definition cmos.c:40
uint8_t min
Definition cmos.c:42
uint8_t sec
Definition cmos.c:43
uint8_t yr
Definition cmos.c:38
uint8_t hrs
Definition cmos.c:41
uint8_t wday
Definition cmos.c:44
Where a device's registers are.
Definition io.h:95
uintptr_t addr
Definition io.h:97
uint32_t tv_nsec
Definition types.h:32
time_t tv_sec
Definition types.h:31
uint64_t time_t
Definition types.h:26