CS318 - Pintos
Pintos source browser for JHU CS318 course
src
devices
rtc.c
Go to the documentation of this file.
1
#include "
devices/rtc.h
"
2
#include <stdio.h>
3
#include "
threads/io.h
"
4
5
/** This code is an interface to the MC146818A-compatible real
6
time clock found on PC motherboards. See [MC146818A] for
7
hardware details. */
8
9
/** I/O register addresses. */
10
#define CMOS_REG_SET 0x70
/**< Selects CMOS register exposed by REG_IO. */
11
#define CMOS_REG_IO 0x71
/**< Contains the selected data byte. */
12
13
/** Indexes of CMOS registers with real-time clock functions.
14
Note that all of these registers are in BCD format,
15
so that 0x59 means 59, not 89. */
16
#define RTC_REG_SEC 0
/**< Second: 0x00...0x59. */
17
#define RTC_REG_MIN 2
/**< Minute: 0x00...0x59. */
18
#define RTC_REG_HOUR 4
/**< Hour: 0x00...0x23. */
19
#define RTC_REG_MDAY 7
/**< Day of the month: 0x01...0x31. */
20
#define RTC_REG_MON 8
/**< Month: 0x01...0x12. */
21
#define RTC_REG_YEAR 9
/**< Year: 0x00...0x99. */
22
23
/** Indexes of CMOS control registers. */
24
#define RTC_REG_A 0x0a
/**< Register A: update-in-progress. */
25
#define RTC_REG_B 0x0b
/**< Register B: 24/12 hour time, irq enables. */
26
#define RTC_REG_C 0x0c
/**< Register C: pending interrupts. */
27
#define RTC_REG_D 0x0d
/**< Register D: valid time? */
28
29
/** Register A. */
30
#define RTCSA_UIP 0x80
/**< Set while time update in progress. */
31
32
/** Register B. */
33
#define RTCSB_SET 0x80
/**< Disables update to let time be set. */
34
#define RTCSB_DM 0x04
/**< 0 = BCD time format, 1 = binary format. */
35
#define RTCSB_24HR 0x02
/**< 0 = 12-hour format, 1 = 24-hour format. */
36
37
static
int
bcd_to_bin
(
uint8_t
);
38
static
uint8_t
cmos_read
(
uint8_t
index);
39
40
/** Returns number of seconds since Unix epoch of January 1,
41
1970. */
42
time_t
43
rtc_get_time
(
void
)
44
{
45
static
const
int
days_per_month[12] =
46
{
47
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
48
};
49
int
sec, min, hour, mday, mon, year;
50
time_t
time;
51
int
i;
52
53
/* Get time components.
54
55
We repeatedly read the time until it is stable from one read
56
to another, in case we start our initial read in the middle
57
of an update. This strategy is not recommended by the
58
MC146818A datasheet, but it is simpler than any of their
59
suggestions and, furthermore, it is also used by Linux.
60
61
The MC146818A can be configured for BCD or binary format,
62
but for historical reasons everyone always uses BCD format
63
except on obscure non-PC platforms, so we don't bother
64
trying to detect the format in use. */
65
do
66
{
67
sec =
bcd_to_bin
(
cmos_read
(
RTC_REG_SEC
));
68
min =
bcd_to_bin
(
cmos_read
(
RTC_REG_MIN
));
69
hour =
bcd_to_bin
(
cmos_read
(
RTC_REG_HOUR
));
70
mday =
bcd_to_bin
(
cmos_read
(
RTC_REG_MDAY
));
71
mon =
bcd_to_bin
(
cmos_read
(
RTC_REG_MON
));
72
year =
bcd_to_bin
(
cmos_read
(
RTC_REG_YEAR
));
73
}
74
while
(sec !=
bcd_to_bin
(
cmos_read
(
RTC_REG_SEC
)));
75
76
/* Translate years-since-1900 into years-since-1970.
77
If it's before the epoch, assume that it has passed 2000.
78
This will break at 2070, but that's long after our 31-bit
79
time_t breaks in 2038. */
80
if
(year < 70)
81
year += 100;
82
year -= 70;
83
84
/* Break down all components into seconds. */
85
time = (year * 365 + (year - 1) / 4) * 24 * 60 * 60;
86
for
(i = 1; i <= mon; i++)
87
time += days_per_month[i - 1] * 24 * 60 * 60;
88
if
(mon > 2 && year % 4 == 0)
89
time += 24 * 60 * 60;
90
time += (mday - 1) * 24 * 60 * 60;
91
time += hour * 60 * 60;
92
time += min * 60;
93
time += sec;
94
95
return
time;
96
}
97
98
/** Returns the integer value of the given BCD byte. */
99
static
int
100
bcd_to_bin
(
uint8_t
x
)
101
{
102
return
(
x
& 0x0f) + ((
x
>> 4) * 10);
103
}
104
105
/** Reads a byte from the CMOS register with the given INDEX and
106
returns the byte read. */
107
static
uint8_t
108
cmos_read
(
uint8_t
index)
109
{
110
outb
(
CMOS_REG_SET
, index);
111
return
inb
(
CMOS_REG_IO
);
112
}
uint8_t
unsigned char uint8_t
Definition:
stdint.h:20
RTC_REG_HOUR
#define RTC_REG_HOUR
Hour: 0x00...0x23.
Definition:
rtc.c:18
RTC_REG_SEC
#define RTC_REG_SEC
Indexes of CMOS registers with real-time clock functions.
Definition:
rtc.c:16
bcd_to_bin
static int bcd_to_bin(uint8_t)
Returns the integer value of the given BCD byte.
Definition:
rtc.c:100
rtc_get_time
time_t rtc_get_time(void)
Returns number of seconds since Unix epoch of January 1,.
Definition:
rtc.c:43
x
static char x
Verifies that mapping over the data segment is disallowed.
Definition:
mmap-over-data.c:9
CMOS_REG_IO
#define CMOS_REG_IO
Contains the selected data byte.
Definition:
rtc.c:11
CMOS_REG_SET
#define CMOS_REG_SET
This code is an interface to the MC146818A-compatible real time clock found on PC motherboards.
Definition:
rtc.c:10
outb
static void outb(uint16_t port, uint8_t data)
Writes byte DATA to PORT.
Definition:
io.h:66
RTC_REG_MDAY
#define RTC_REG_MDAY
Day of the month: 0x01...0x31.
Definition:
rtc.c:19
RTC_REG_YEAR
#define RTC_REG_YEAR
Year: 0x00...0x99.
Definition:
rtc.c:21
cmos_read
static uint8_t cmos_read(uint8_t index)
Reads a byte from the CMOS register with the given INDEX and returns the byte read.
Definition:
rtc.c:108
time_t
unsigned long time_t
Definition:
rtc.h:4
inb
static uint8_t inb(uint16_t port)
Reads and returns a byte from PORT.
Definition:
io.h:9
io.h
rtc.h
RTC_REG_MIN
#define RTC_REG_MIN
Minute: 0x00...0x59.
Definition:
rtc.c:17
RTC_REG_MON
#define RTC_REG_MON
Month: 0x01...0x12.
Definition:
rtc.c:20
Generated on Thu Aug 22 2019 10:19:15 for CS318 - Pintos by
1.8.16