1 2 #include <stdbool.h> 3 #include <stdint.h> 4 #include <string.h> 5 6 #include <sys/kassert.h> 7 #include <sys/kdebug.h> 8 #include <sys/ktime.h> 9 10 #include "ioport.h" 11 12 #define RTC_SECONDS 0x00 13 #define RTC_MINUTES 0x02 14 #define RTC_HOURS 0x04 15 #define RTC_WEEKDAY 0x06 16 #define RTC_DAY 0x07 17 #define RTC_MONTH 0x08 18 #define RTC_YEAR 0x09 19 20 UnixEpoch RTC_ReadTime(); 21 22 void RTC_Init()23RTC_Init() 24 { 25 uint64_t startTSC, stopTSC; 26 UnixEpoch first, second; 27 28 kprintf("RTC: Measuring CPU clock...\n"); 29 30 first = RTC_ReadTime(); 31 while (1) { 32 second = RTC_ReadTime(); 33 if (first != second) 34 break; 35 first = second; 36 } 37 startTSC = Time_GetTSC(); 38 39 first = RTC_ReadTime(); 40 while (1) { 41 second = RTC_ReadTime(); 42 if (first != second) 43 break; 44 first = second; 45 } 46 stopTSC = Time_GetTSC(); 47 48 kprintf("RTC: %lld Ticks Per Second: %lld\n", second, stopTSC - startTSC); 49 50 KTime_SetTime(second, stopTSC, stopTSC - startTSC); 51 } 52 53 static inline uint8_t RTC_ReadReg(uint8_t reg)54RTC_ReadReg(uint8_t reg) 55 { 56 outb(0x70, reg); 57 return inb(0x71); 58 } 59 60 UnixEpoch RTC_ReadTime()61RTC_ReadTime() 62 { 63 KTime tm; 64 bool isPM = false; 65 uint8_t flags = RTC_ReadReg(0x0B); 66 67 // Read RTC 68 tm.sec = RTC_ReadReg(RTC_SECONDS); 69 tm.min = RTC_ReadReg(RTC_MINUTES); 70 tm.hour = RTC_ReadReg(RTC_HOURS); 71 tm.wday = RTC_ReadReg(RTC_WEEKDAY); 72 tm.mday = RTC_ReadReg(RTC_DAY); 73 tm.month = RTC_ReadReg(RTC_MONTH); 74 tm.year = RTC_ReadReg(RTC_YEAR); 75 76 // Convert BCD & 24-hour checks 77 if (tm.hour & 0x80) { 78 isPM = true; 79 } 80 if ((flags & 0x04) == 0) { 81 #define BCD_TO_BIN(_B) ((_B & 0x0F) + ((_B >> 4) * 10)) 82 tm.sec = BCD_TO_BIN(tm.sec); 83 tm.min = BCD_TO_BIN(tm.min); 84 tm.hour = BCD_TO_BIN((tm.hour & 0x7F)); 85 tm.wday = BCD_TO_BIN(tm.wday); 86 tm.mday = BCD_TO_BIN(tm.mday); 87 tm.month = BCD_TO_BIN(tm.month); 88 tm.year = BCD_TO_BIN(tm.year); 89 } 90 if (((flags & 0x02) == 0) && isPM) { 91 tm.hour = (tm.hour + 12) % 24; 92 } 93 94 tm.year += 2000; 95 tm.yday = -1; 96 97 tm.wday -= 1; 98 tm.month -= 1; 99 100 // KTime_SetTime(&tm); 101 return KTime_ToEpoch(&tm); 102 } 103 104