1 #include "rtc.h" 2 #include <common/kprint.h> 3 4 /*置位0x70的第7位,禁止不可屏蔽中断*/ 5 6 #define read_cmos(addr) ({ \ 7 io_out8(0x70, 0x80 | addr); \ 8 io_in8(0x71); \ 9 }) 10 11 enum CMOSTimeSelector 12 { 13 T_SECOND = 0x0, 14 T_MINUTE = 0x2, 15 T_HOUR = 0x4, 16 T_DAY = 0x7, 17 T_MONTH = 0x8, 18 T_YEAR = 0x9, 19 }; 20 21 rtc_get_cmos_time(struct rtc_time_t * t)22int rtc_get_cmos_time(struct rtc_time_t *t) 23 { 24 // 为防止中断请求打断该过程,需要先关中断 25 cli(); 26 27 uint8_t status_register_B = read_cmos(0x0B); // 读取状态寄存器B 28 bool is_24h = ((status_register_B & 0x02) ? true : false); // 判断是否启用24小时模式 29 bool is_binary = ((status_register_B & 0x04) ? true : false); // 判断是否为二进制码 30 31 do 32 { 33 t->year = read_cmos(0x09); 34 t->month = read_cmos(0x08); 35 t->day = read_cmos(0x07); 36 t->hour = read_cmos(0x04); 37 t->minute = read_cmos(0x02); 38 t->second = read_cmos(0x00); 39 } while (t->second != read_cmos(0x00)); // 若读取时间过程中时间发生跳变则重新读取 40 // 使能NMI中断 41 io_out8(0x70, 0x00); 42 43 if (!is_binary) // 把BCD转为二进制 44 { 45 t->second = (t->second & 0xf) + (t->second >> 4) * 10; 46 t->minute = (t->minute & 0xf) + (t->minute >> 4) * 10; 47 t->hour = ((t->hour & 0xf) + ((t->hour & 0x70) >> 4) * 10) | (t->hour & 0x80); 48 t->day = (t->day & 0xf) + ((t->day / 16) * 10); 49 t->month = (t->month & 0xf) + (t->month >> 4) * 10; 50 t->year = (t->year & 0xf) + (t->year >> 4) * 10; 51 } 52 t->year += 2000; 53 54 if ((!is_24h) && t->hour & 0x80) // 将十二小时制转为24小时 55 t->hour = ((t->hour & 0x7f) + 12) % 24; 56 sti(); 57 return 0; 58 } 59