- Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathrtc.c
More file actions
Latest commit
66 lines (55 loc) · 1.88 KB
/
Copy pathrtc.c
File metadata and controls
66 lines (55 loc) · 1.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include"types.h"
#defineCMOS_ADDRESS 0x70
#defineCMOS_DATA 0x71
staticinlineuint8_tinb(uint16_tport) {
uint8_tret;
__asm__ __volatile__ ("inb %1, %0" : "=a"(ret) : "Nd"(port));
returnret;
}
staticinlinevoidoutb(uint16_tport, uint8_tval) {
__asm__ __volatile__ ("outb %0, %1" : : "a"(val), "Nd"(port));
}
typedefstruct {
uint8_tsecond;
uint8_tminute;
uint8_thour;
uint8_tday;
uint8_tmonth;
uint32_tyear;
} RTCTime;
// Helper function to read a single CMOS register byte
staticuint8_tget_rtc_register(intreg) {
outb(CMOS_ADDRESS, reg);
returninb(CMOS_DATA);
}
// Convert Binary Coded Decimal (BCD) to standard 8-bit integer
staticuint8_tbcd_to_bin(uint8_tbcd) {
return ((bcd / 16) *10) + (bcd % 16);
}
/**
* @brief Reads the current hardware time from the CMOS chip
*/
voidread_rtc(RTCTime*time_out) {
// Wait if CMOS update is currently in progress (bit 7 of Register A)
outb(CMOS_ADDRESS, 0x0A);
while (inb(CMOS_DATA) &0x80);
// Read BCD time values from hardware registers
time_out->second=get_rtc_register(0x00);
time_out->minute=get_rtc_register(0x02);
time_out->hour=get_rtc_register(0x04);
time_out->day=get_rtc_register(0x07);
time_out->month=get_rtc_register(0x08);
time_out->year=get_rtc_register(0x09);
uint8_tregister_b=get_rtc_register(0x0B);
// Convert BCD to standard integers if necessary
if (!(register_b&0x04)) {
time_out->second=bcd_to_bin(time_out->second);
time_out->minute=bcd_to_bin(time_out->minute);
time_out->hour=bcd_to_bin(time_out->hour&0x7F);
time_out->day=bcd_to_bin(time_out->day);
time_out->month=bcd_to_bin(time_out->month);
time_out->year=bcd_to_bin(time_out->year);
}
// Adjust 2-digit year (e.g., 26 -> 2026)
time_out->year+=2000;
}