33 * \brief Clock
44 */
55
6- #include <kernel/cpu/idt.h>
76#include <machine/cpu.h>
87#include <sys/device.h>
98
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
2949static unsigned char
3050read_cmos (unsigned int reg )
@@ -40,38 +60,46 @@ read_cmos(unsigned int reg)
4060}
4161
4262static 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
6787static 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
77105static 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-
113125static int
114126clock_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