Added .gitignore
[comos.git] / kernel / rtc.c
blobb81a77fef950dadf3a4bbd8f41948e2b31c3d25c
1 #include "rtc.h"
2 #include "stdlib.h"
3 #include "console.h"
4 #include "interrupt.h"
5 #include "portio.h"
7 static uint8_t read_cmos(const uint8_t reg)
9 /* we don't to cause any undefined behaviour by reading above CMOS RAM */
10 if(reg >= 64){return 0;}
12 outb(0x70, reg);
13 return inb(0x71);
16 static void write_cmos(uint8_t reg, uint8_t val)
18 /* we don't to cause any undefined behaviour by reading above CMOS RAM */
19 if(reg >= 64){return;}
21 outb(0x70, reg);
22 outb(0x71, val);
25 static uint16_t cmos_checksum()
27 uint8_t i;
28 uint16_t checksum;
30 checksum = 0;
32 for(i = 16; i < 46; i++)
33 {checksum += read_cmos(i);}
35 return hs2net_16(checksum);
38 static void rtc_handler(int vector, struct interrupt_stack *is)
40 time.second = bcd2bin(read_cmos(0x00));
41 time.minute = bcd2bin(read_cmos(0x02));
42 time.hour = bcd2bin(read_cmos(0x04));
43 time.day_of_week = bcd2bin(read_cmos(0x06));
44 time.day_of_month = bcd2bin(read_cmos(0x07));
45 time.month = bcd2bin(read_cmos(0x08));
47 uint8_t year = bcd2bin(read_cmos(0x09));
48 uint16_t century = bcd2bin(read_cmos(0x32));
50 century *= 100;
51 time.year = century + year;
53 read_cmos(0x0C); /* clear pending interrupts */
54 ack_irq(8);
57 static void force_update()
59 read_cmos(0x0C); /* clear pending interrupts */
61 time.second = bcd2bin(read_cmos(0x00));
62 time.minute = bcd2bin(read_cmos(0x02));
63 time.hour = bcd2bin(read_cmos(0x04));
64 time.day_of_week = bcd2bin(read_cmos(0x06));
65 time.day_of_month = bcd2bin(read_cmos(0x07));
66 time.month = bcd2bin(read_cmos(0x08));
68 uint8_t year = bcd2bin(read_cmos(0x09));
69 uint16_t century = bcd2bin(read_cmos(0x32));
71 century *= 100;
72 time.year = century + year;
75 void init_rtc()
77 uint8_t status_b;
78 uint16_t theirs, ours;
80 theirs = read_cmos(46) & 0xFF;
81 theirs += ((read_cmos(47) << 8) & 0xFF00);
83 ours = cmos_checksum();
85 /* QEMU seems to not use the checksum field, so we have to take this with a grain of salt. */
86 if(theirs != ours)
88 console_printf(get_vterm(0), "CMOS: checksum error. theirs = %x, ours = %x \n", theirs, ours);
91 /* this, on the other hand, is not to be looked over lightly */
92 if(!(read_cmos(0x0D) & 0x80))
94 console_printf(get_vterm(0), "CMOS: data invalid (status register D = %x) \n", read_cmos(0x0D));
95 return;
98 status_b = read_cmos(0x0B);
99 status_b |= 0x12; /* set UI and 24h */
100 status_b &= 0x9F; /* clear PI and AI */
101 write_cmos(0x0B, status_b);
103 time.second = 0;
104 interrupt_set_handler(irq_to_int(8), &rtc_handler);
105 unmask_irq(8);
107 read_cmos(0x0C); /* clear pending interrupts */
108 force_update();
110 console_printf(get_vterm(0), "RTC: current time = %u:%u:%u, date = %u/%u/%u\n", time.hour, time.minute, time.second, time.month, time.day_of_month, time.year);