#include #include #include #include #include #include #include #include #include #include #include #include #define RTC_CMOS_ADDR 0x70 #define RTC_CMOS_DATA 0x71 static uint8_t rtc_century; #define RTC_SEC 0x00 #define RTC_SEC_ALARM 0x01 #define RTC_MIN 0x02 #define RTC_MIN_ALARM 0x03 #define RTC_HOUR 0x04 #define RTC_HOUR_ALARM 0x05 #define RTC_WEEK_DAY 0x06 #define RTC_DAY 0x07 #define RTC_MONTH 0x08 #define RTC_YEAR 0x09 #define RTC_REG_A 0x0A #define RTC_REG_B 0x0B #define RTC_REG_C 0x0C #define RTC_REG_D 0x0D #define RTC_REG_A_UIP (1 << 7) #define RTC_REG_B_HOURFMT (1 << 1) #define RTC_REG_B_DATAMODE (1 << 2) static uint8_t rtc_read (uint8_t addr) { outb (RTC_CMOS_ADDR, RTC_REG_A); while (inb (RTC_CMOS_DATA) & RTC_REG_A_UIP) ; outb (RTC_CMOS_ADDR, addr); return inb (RTC_CMOS_DATA); } static void rtc_write (uint8_t addr, uint8_t value) { outb (RTC_CMOS_ADDR, addr); outb (RTC_CMOS_DATA, value); } static uint8_t rtc_bcd_to_bin (uint8_t value) { return (value & 0xF) + (value >> 4) * 10; } static uint8_t rtc_bin_to_bcd (uint8_t value) { return ((value / 10) << 4) + (value % 10); } void rtc_init (void) { struct limine_hhdm_response* hhdm = limine_hhdm_request.response; struct uacpi_table fadt_table; uacpi_status status = uacpi_table_find_by_signature (ACPI_FADT_SIGNATURE, &fadt_table); if (status != UACPI_STATUS_OK) { DEBUG ("Could not find FADT table!\n"); spin (); } struct acpi_fadt* fadt = (struct acpi_fadt*)fadt_table.virt_addr; rtc_century = fadt->century; } void rtc_date_time (struct date_time* date_time) { if (rtc_read (RTC_REG_A) & RTC_REG_A_UIP) stall_ms (1); uint8_t sec = rtc_read (RTC_SEC); uint8_t min = rtc_read (RTC_MIN); uint8_t hour = rtc_read (RTC_HOUR); uint8_t weekday = rtc_read (RTC_WEEK_DAY); uint8_t day = rtc_read (RTC_DAY); uint8_t month = rtc_read (RTC_MONTH); uint8_t year = rtc_read (RTC_YEAR); uint8_t century = rtc_century != 0 ? rtc_read (rtc_century) : 0; uint8_t b = rtc_read (RTC_REG_B); /* BCD */ if ((~b) & RTC_REG_B_DATAMODE) { sec = rtc_bcd_to_bin (sec); min = rtc_bcd_to_bin (min); hour = rtc_bcd_to_bin (hour); day = rtc_bcd_to_bin (day); month = rtc_bcd_to_bin (month); year = rtc_bcd_to_bin (year); if (rtc_century != 0) century = rtc_bcd_to_bin (century); } weekday--; int full_year; if (rtc_century != 0) full_year = (century * 100) + year; else full_year = (year < 80) ? (2000 + year) : (1900 + year); date_time->sec = sec; date_time->min = min; date_time->hour = hour; date_time->day = day; date_time->weekday = weekday; date_time->month = month; date_time->year = full_year; }