Lines Matching full:rtc

45 #include <isa/rtc.h>
53 /* Register layout of the RTC */
80 u_int addr; /* RTC register to read or write */
91 * RTC time is considered "broken" if:
92 * - RTC updates are halted by the guest
93 * - RTC date/time fields have invalid values
108 static MALLOC_DEFINE(M_VRTC, "vrtc", "bhyve virtual rtc");
116 &rtc_flag_broken_time, 0, "Stop guest when invalid RTC time is detected");
122 * The RTC is counting only when dividers are not held in reset. in divider_enabled()
131 * RTC date/time can be updated only if: in update_enabled()
171 rtcset(struct rtcdev *rtc, int val) in rtcset() argument
177 return ((rtc->reg_b & RTCSB_BIN) ? val : bin2bcd_data[val]); in rtcset()
185 struct rtcdev *rtc; in secs_to_rtc() local
197 * If the RTC is halted then the guest has "ownership" of the in secs_to_rtc()
198 * date/time fields. Don't update the RTC date/time fields in in secs_to_rtc()
223 rtc = &vrtc->rtcdev; in secs_to_rtc()
224 rtc->sec = rtcset(rtc, ct.sec); in secs_to_rtc()
225 rtc->min = rtcset(rtc, ct.min); in secs_to_rtc()
227 if (rtc->reg_b & RTCSB_24HR) { in secs_to_rtc()
249 rtc->hour = rtcset(rtc, hour); in secs_to_rtc()
251 if ((rtc->reg_b & RTCSB_24HR) == 0 && ct.hour >= 12) in secs_to_rtc()
252 rtc->hour |= 0x80; /* set MSB to indicate PM */ in secs_to_rtc()
254 rtc->day_of_week = rtcset(rtc, ct.dow + 1); in secs_to_rtc()
255 rtc->day_of_month = rtcset(rtc, ct.day); in secs_to_rtc()
256 rtc->month = rtcset(rtc, ct.mon); in secs_to_rtc()
257 rtc->year = rtcset(rtc, ct.year % 100); in secs_to_rtc()
258 rtc->century = rtcset(rtc, ct.year / 100); in secs_to_rtc()
262 rtcget(struct rtcdev *rtc, int val, int *retval) in rtcget() argument
266 if (rtc->reg_b & RTCSB_BIN) { in rtcget()
286 struct rtcdev *rtc; in rtc_to_secs() local
294 rtc = &vrtc->rtcdev; in rtc_to_secs()
298 error = rtcget(rtc, rtc->sec, &ct.sec); in rtc_to_secs()
300 VM_CTR2(vm, "Invalid RTC sec %#x/%d", rtc->sec, ct.sec); in rtc_to_secs()
304 error = rtcget(rtc, rtc->min, &ct.min); in rtc_to_secs()
306 VM_CTR2(vm, "Invalid RTC min %#x/%d", rtc->min, ct.min); in rtc_to_secs()
311 hour = rtc->hour; in rtc_to_secs()
312 if ((rtc->reg_b & RTCSB_24HR) == 0) { in rtc_to_secs()
318 error = rtcget(rtc, hour, &ct.hour); in rtc_to_secs()
319 if ((rtc->reg_b & RTCSB_24HR) == 0) { in rtc_to_secs()
336 VM_CTR2(vm, "Invalid RTC 12-hour format %#x/%d", in rtc_to_secs()
337 rtc->hour, ct.hour); in rtc_to_secs()
343 VM_CTR2(vm, "Invalid RTC hour %#x/%d", rtc->hour, ct.hour); in rtc_to_secs()
348 * Ignore 'rtc->dow' because some guests like Linux don't bother in rtc_to_secs()
355 error = rtcget(rtc, rtc->day_of_month, &ct.day); in rtc_to_secs()
357 VM_CTR2(vm, "Invalid RTC mday %#x/%d", rtc->day_of_month, in rtc_to_secs()
362 error = rtcget(rtc, rtc->month, &ct.mon); in rtc_to_secs()
364 VM_CTR2(vm, "Invalid RTC month %#x/%d", rtc->month, ct.mon); in rtc_to_secs()
368 error = rtcget(rtc, rtc->year, &year); in rtc_to_secs()
370 VM_CTR2(vm, "Invalid RTC year %#x/%d", rtc->year, year); in rtc_to_secs()
374 error = rtcget(rtc, rtc->century, &century); in rtc_to_secs()
377 VM_CTR2(vm, "Invalid RTC century %#x/%d", rtc->century, in rtc_to_secs()
384 VM_CTR3(vm, "Invalid RTC clocktime.date %04d-%02d-%02d", in rtc_to_secs()
386 VM_CTR3(vm, "Invalid RTC clocktime.time %02d:%02d:%02d", in rtc_to_secs()
393 * Stop updating the RTC if the date/time fields programmed by in rtc_to_secs()
396 VM_CTR0(vrtc->vm, "Invalid RTC date/time programming detected"); in rtc_to_secs()
403 struct rtcdev *rtc; in vrtc_time_update() local
409 rtc = &vrtc->rtcdev; in vrtc_time_update()
410 alarm_sec = rtc->alarm_sec; in vrtc_time_update()
411 alarm_min = rtc->alarm_min; in vrtc_time_update()
412 alarm_hour = rtc->alarm_hour; in vrtc_time_update()
415 VM_CTR2(vrtc->vm, "Updating RTC secs from %#lx to %#lx", in vrtc_time_update()
418 VM_CTR2(vrtc->vm, "Updating RTC base uptime from %#lx to %#lx", in vrtc_time_update()
426 * If 'newtime' indicates that RTC updates are disabled then just in vrtc_time_update()
436 * Return an error if RTC updates are halted by the guest. in vrtc_time_update()
439 VM_CTR0(vrtc->vm, "RTC update halted by guest"); in vrtc_time_update()
449 * Otherwise move the RTC time forward directly to 'newtime'. in vrtc_time_update()
458 * Update the RTC date/time fields before checking in vrtc_time_update()
463 if ((alarm_sec >= 0xC0 || alarm_sec == rtc->sec) && in vrtc_time_update()
464 (alarm_min >= 0xC0 || alarm_min == rtc->min) && in vrtc_time_update()
465 (alarm_hour >= 0xC0 || alarm_hour == rtc->hour)) { in vrtc_time_update()
466 vrtc_set_reg_c(vrtc, rtc->reg_c | RTCIR_ALARM); in vrtc_time_update()
472 vrtc_set_reg_c(vrtc, rtc->reg_c | RTCIR_UPDATE); in vrtc_time_update()
530 VM_CTR0(vrtc->vm, "RTC callout stopped"); in vrtc_callout_reset()
535 VM_CTR1(vrtc->vm, "RTC callout frequency %d hz", SBT_1S / freqsbt); in vrtc_callout_reset()
593 struct rtcdev *rtc; in vrtc_set_reg_c() local
599 rtc = &vrtc->rtcdev; in vrtc_set_reg_c()
602 oldirqf = rtc->reg_c & RTCIR_INT; in vrtc_set_reg_c()
611 oldval = rtc->reg_c; in vrtc_set_reg_c()
612 rtc->reg_c = newirqf | newval; in vrtc_set_reg_c()
613 changed = oldval ^ rtc->reg_c; in vrtc_set_reg_c()
615 VM_CTR2(vrtc->vm, "RTC reg_c changed from %#x to %#x", in vrtc_set_reg_c()
616 oldval, rtc->reg_c); in vrtc_set_reg_c()
620 VM_CTR1(vrtc->vm, "RTC irq %d asserted", RTC_IRQ); in vrtc_set_reg_c()
624 VM_CTR1(vrtc->vm, "RTC irq %d deasserted", RTC_IRQ); in vrtc_set_reg_c()
631 struct rtcdev *rtc; in vrtc_set_reg_b() local
639 rtc = &vrtc->rtcdev; in vrtc_set_reg_b()
640 oldval = rtc->reg_b; in vrtc_set_reg_b()
643 rtc->reg_b = newval; in vrtc_set_reg_b()
646 VM_CTR2(vrtc->vm, "RTC reg_b changed from %#x to %#x", in vrtc_set_reg_b()
665 * Force a refresh of the RTC date/time fields so in vrtc_set_reg_b()
673 * that the RTC date/time is in flux. in vrtc_set_reg_b()
676 rtc->reg_b &= ~RTCSB_UINTR; in vrtc_set_reg_b()
698 * The side effect of bits that control the RTC date/time format in vrtc_set_reg_b()
717 VM_CTR2(vrtc->vm, "RTC divider held in reset at %#lx/%#lx", in vrtc_set_reg_a()
723 * maintain the illusion that the RTC date/time was frozen in vrtc_set_reg_a()
727 VM_CTR2(vrtc->vm, "RTC divider out of reset at %#lx/%#lx", in vrtc_set_reg_a()
736 VM_CTR2(vrtc->vm, "RTC reg_a changed from %#x to %#x", in vrtc_set_reg_a()
762 VM_CTR2(vrtc->vm, "Error %d setting RTC time to %#lx", error, in vrtc_set_time()
765 VM_CTR1(vrtc->vm, "RTC time set to %#lx", secs); in vrtc_set_time()
795 * Don't allow writes to RTC control registers or the date/time fields. in vrtc_nvram_write()
799 VM_CTR1(vrtc->vm, "RTC nvram write to invalid offset %d", in vrtc_nvram_write()
807 VM_CTR2(vrtc->vm, "RTC nvram write %#x to offset %#x", value, offset); in vrtc_nvram_write()
822 * Allow all offsets in the RTC to be read. in vrtc_nvram_read()
831 * Update RTC date/time fields if necessary. in vrtc_nvram_read()
871 struct rtcdev *rtc; in vrtc_data_handler() local
877 rtc = &vrtc->rtcdev; in vrtc_data_handler()
894 * Update RTC date/time fields if necessary. in vrtc_data_handler()
896 * This is not just for reads of the RTC. The side-effect of writing in vrtc_data_handler()
897 * the century byte requires other RTC date/time fields (e.g. sec) in vrtc_data_handler()
913 *val = *((uint8_t *)rtc + offset); in vrtc_data_handler()
915 VM_CTR2(vm, "Read value %#x from RTC offset %#x", in vrtc_data_handler()
920 VM_CTR1(vm, "RTC reg_a set to %#x", *val); in vrtc_data_handler()
924 VM_CTR1(vm, "RTC reg_b set to %#x", *val); in vrtc_data_handler()
928 VM_CTR1(vm, "RTC reg_c set to %#x (ignored)", in vrtc_data_handler()
932 VM_CTR1(vm, "RTC reg_d set to %#x (ignored)", in vrtc_data_handler()
942 VM_CTR2(vm, "RTC offset %#x set to %#x", in vrtc_data_handler()
944 *((uint8_t *)rtc + offset) = *val; in vrtc_data_handler()
950 * outside of RTCSB_HALT so re-calculate the RTC date/time. in vrtc_data_handler()
967 struct rtcdev *rtc; in vrtc_reset() local
971 rtc = &vrtc->rtcdev; in vrtc_reset()
972 vrtc_set_reg_b(vrtc, rtc->reg_b & ~(RTCSB_ALL_INTRS | RTCSB_SQWE)); in vrtc_reset()
974 KASSERT(!callout_active(&vrtc->callout), ("rtc callout still active")); in vrtc_reset()
983 struct rtcdev *rtc; in vrtc_init() local
992 rtc = &vrtc->rtcdev; in vrtc_init()
993 rtc->reg_a = 0x20; in vrtc_init()
994 rtc->reg_b = RTCSB_24HR; in vrtc_init()
995 rtc->reg_c = 0; in vrtc_init()
996 rtc->reg_d = RTCSD_PWR; in vrtc_init()
1002 * Initialize RTC time to 00:00:00 Jan 1, 1970. in vrtc_init()