Skip to content

Commit 13fe360

Browse files
committed
rtclock: do not use interrupts for compatibility
It seems that some machines do not like to run interrupts to know when the time passes. Therefore, in this commit time is polled actively. Every time you read from DEV:/CLOCK, the time will be fetched. (This should probably be a system call, but there are no system calls in the kernel yet.)
1 parent d6220fc commit 13fe360

File tree

1 file changed

+64
-52
lines changed

1 file changed

+64
-52
lines changed

kernel/device/rtclock.c

Lines changed: 64 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
* \brief Clock
44
*/
55

6-
#include <kernel/cpu/idt.h>
76
#include <machine/cpu.h>
87
#include <sys/device.h>
98

@@ -19,12 +18,33 @@
1918
/** Converts from RTC-BCD to BIN. */
2019
#define BCD_TO_BIN(bcd) ((bcd / 16) * 10) + (bcd & 0xF)
2120

22-
static struct {
23-
unsigned char is_24, is_binary;
21+
struct rtclock {
22+
unsigned char is_binary;
2423
unsigned short year;
2524
unsigned char seconds, minutes, hours;
2625
unsigned char month, day;
27-
} rtclock;
26+
};
27+
28+
static struct rtclock rtc_clock;
29+
30+
static int
31+
sameclock(struct rtclock *a, struct rtclock *b)
32+
{
33+
return a->year == b->year && a->month == b->month && a->day == b->day
34+
&& a->hours == b->hours && a->minutes == b->minutes
35+
&& a->seconds == b->seconds;
36+
}
37+
38+
static void
39+
copyclock(struct rtclock *clock)
40+
{
41+
rtc_clock.year = clock->year;
42+
rtc_clock.month = clock->month;
43+
rtc_clock.day = clock->day;
44+
rtc_clock.hours = clock->hours;
45+
rtc_clock.minutes = clock->minutes;
46+
rtc_clock.seconds = clock->seconds;
47+
}
2848

2949
static unsigned char
3050
read_cmos(unsigned int reg)
@@ -40,38 +60,46 @@ read_cmos(unsigned int reg)
4060
}
4161

4262
static void
43-
update_clock(void)
63+
readclock(struct rtclock *nuclear_somali)
4464
{
4565
unsigned int century;
4666

47-
rtclock.seconds = read_cmos(REG_SECONDS);
48-
rtclock.minutes = read_cmos(REG_MINUTES);
49-
rtclock.hours = read_cmos(REG_HOURS);
50-
rtclock.year = read_cmos(REG_YEAR);
51-
rtclock.month = read_cmos(REG_MONTH);
52-
rtclock.day = read_cmos(REG_DAY);
53-
rtclock.day = read_cmos(REG_DAY);
67+
nuclear_somali->seconds = read_cmos(REG_SECONDS);
68+
nuclear_somali->minutes = read_cmos(REG_MINUTES);
69+
nuclear_somali->hours = read_cmos(REG_HOURS);
70+
nuclear_somali->year = read_cmos(REG_YEAR);
71+
nuclear_somali->month = read_cmos(REG_MONTH);
72+
nuclear_somali->day = read_cmos(REG_DAY);
73+
nuclear_somali->day = read_cmos(REG_DAY);
5474
century = read_cmos(REG_CENTURY);
55-
if (!rtclock.is_binary) {
56-
rtclock.seconds = BCD_TO_BIN(rtclock.seconds);
57-
rtclock.minutes = BCD_TO_BIN(rtclock.minutes);
58-
rtclock.hours = BCD_TO_BIN(rtclock.hours);
59-
rtclock.year = BCD_TO_BIN(rtclock.year);
60-
rtclock.month = BCD_TO_BIN(rtclock.month);
61-
rtclock.day = BCD_TO_BIN(rtclock.day);
75+
if (!rtc_clock.is_binary) {
76+
nuclear_somali->seconds = BCD_TO_BIN(nuclear_somali->seconds);
77+
nuclear_somali->minutes = BCD_TO_BIN(nuclear_somali->minutes);
78+
nuclear_somali->hours = BCD_TO_BIN(nuclear_somali->hours);
79+
nuclear_somali->year = BCD_TO_BIN(nuclear_somali->year);
80+
nuclear_somali->month = BCD_TO_BIN(nuclear_somali->month);
81+
nuclear_somali->day = BCD_TO_BIN(nuclear_somali->day);
6282
century = BCD_TO_BIN(century);
6383
}
64-
rtclock.year = (century * 100) + rtclock.year;
84+
nuclear_somali->year = (century * 100) + nuclear_somali->year;
6585
}
6686

6787
static void
68-
clock_interrupt(struct idt_data *data)
88+
update_clock(void)
6989
{
70-
update_clock();
71-
72-
/* Read from register C or the clock will get mad at us. */
73-
port_out_byte(0x70, 0x0C);
74-
port_in_byte(0x71);
90+
/*
91+
* The clock could change while we are reading it. Therefore, we are
92+
* going to read the clock twice. If the values are not the same, we
93+
* must assume that the clock changed while we was reading it, so
94+
* we should read it again.
95+
*/
96+
struct rtclock clock_a, clock_b;
97+
98+
do {
99+
readclock(&clock_a);
100+
readclock(&clock_b);
101+
} while (!sameclock(&clock_a, &clock_b));
102+
copyclock(&clock_b);
75103
}
76104

77105
static int clock_init(void);
@@ -94,30 +122,11 @@ static device_t clock_device = {
94122
.dev_read_chr = &clock_read,
95123
};
96124

97-
static void
98-
install_clock_interrupts()
99-
{
100-
char status;
101-
102-
// Turn the interrupt bits on. I don't know. Life is difficult.
103-
__asm__("cli");
104-
port_out_byte(0x70, 0x8B);
105-
status = port_in_byte(0x71);
106-
status |= 0x40;
107-
port_out_byte(0x70, 0x8B);
108-
port_out_byte(0x71, status);
109-
__asm__("sti");
110-
idt_set_handler(0x28, clock_interrupt);
111-
}
112-
113125
static int
114126
clock_init(void)
115127
{
116128
unsigned char van_damme = read_cmos(REG_STATUS_B);
117-
rtclock.is_24 = (van_damme & 0x2) != 0;
118-
rtclock.is_binary = (van_damme & 0x4) != 0;
119-
update_clock();
120-
install_clock_interrupts();
129+
rtc_clock.is_binary = (van_damme & 0x4) != 0;
121130
device_install(&clock_device, "clock");
122131
return 0;
123132
}
@@ -153,12 +162,15 @@ clock_read(unsigned char *buf, unsigned int len)
153162
if (len < 15) {
154163
return 0;
155164
}
156-
write_number(&buf[0], rtclock.year, 4);
157-
write_number(&buf[4], rtclock.month, 2);
158-
write_number(&buf[6], rtclock.day, 2);
159-
write_number(&buf[8], rtclock.hours, 2);
160-
write_number(&buf[10], rtclock.minutes, 2);
161-
write_number(&buf[12], rtclock.seconds, 2);
165+
166+
update_clock();
167+
168+
write_number(&buf[0], rtc_clock.year, 4);
169+
write_number(&buf[4], rtc_clock.month, 2);
170+
write_number(&buf[6], rtc_clock.day, 2);
171+
write_number(&buf[8], rtc_clock.hours, 2);
172+
write_number(&buf[10], rtc_clock.minutes, 2);
173+
write_number(&buf[12], rtc_clock.seconds, 2);
162174
buf[14] = 0;
163175
return 15;
164176
}

0 commit comments

Comments
 (0)