Lines Matching +full:use +full:- +full:internal +full:- +full:divider

1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
7 * Redistribution and use in source and binary forms, with or without
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
71 uint8_t nvram2[128 - 51];
86 #define VRTC_LOCK(vrtc) mtx_lock(&((vrtc)->mtx))
87 #define VRTC_UNLOCK(vrtc) mtx_unlock(&((vrtc)->mtx))
88 #define VRTC_LOCKED(vrtc) mtx_owned(&((vrtc)->mtx))
92 * - RTC updates are halted by the guest
93 * - RTC date/time fields have invalid values
95 #define VRTC_BROKEN_TIME ((time_t)-1)
100 #define rtc_halted(vrtc) ((vrtc->rtcdev.reg_b & RTCSB_HALT) != 0)
101 #define aintr_enabled(vrtc) (((vrtc)->rtcdev.reg_b & RTCSB_AINTR) != 0)
102 #define pintr_enabled(vrtc) (((vrtc)->rtcdev.reg_b & RTCSB_PINTR) != 0)
103 #define uintr_enabled(vrtc) (((vrtc)->rtcdev.reg_b & RTCSB_UINTR) != 0)
132 * - divider is not held in reset in update_enabled()
133 * - guest has not disabled updates in update_enabled()
134 * - the date/time fields have valid contents in update_enabled()
136 if (!divider_enabled(vrtc->rtcdev.reg_a)) in update_enabled()
142 if (vrtc->base_rtctime == VRTC_BROKEN_TIME) in update_enabled()
156 t = vrtc->base_rtctime; in vrtc_curtime()
157 *basetime = vrtc->base_uptime; in vrtc_curtime()
160 delta = now - vrtc->base_uptime; in vrtc_curtime()
162 "%#lx to %#lx", vrtc->base_uptime, now)); in vrtc_curtime()
177 return ((rtc->reg_b & RTCSB_BIN) ? val : bin2bcd_data[val]); in rtcset()
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()
231 * Convert to the 12-hour format. in secs_to_rtc()
241 * [1 - 11] -> 1 - 11 AM in secs_to_rtc()
242 * [13 - 23] -> 1 - 11 PM 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()
266 if (rtc->reg_b & RTCSB_BIN) { in rtcget()
275 return (-1); in rtcget()
288 struct vm *vm = vrtc->vm; in rtc_to_secs()
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()
319 if ((rtc->reg_b & RTCSB_24HR) == 0) { in rtc_to_secs()
322 * Convert from 12-hour format to internal 24-hour in rtc_to_secs()
325 * 12-hour format ct.hour in rtc_to_secs()
327 * 1 - 11 AM 1 - 11 in rtc_to_secs()
329 * 1 - 11 PM 13 - 23 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()
353 ct.dow = -1; 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()
396 VM_CTR0(vrtc->vm, "Invalid RTC date/time programming detected"); in rtc_to_secs()
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()
414 oldtime = vrtc->base_rtctime; 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()
419 vrtc->base_uptime, newbase); in vrtc_time_update()
420 vrtc->base_uptime = newbase; in vrtc_time_update()
431 vrtc->base_rtctime = VRTC_BROKEN_TIME; in vrtc_time_update()
439 VM_CTR0(vrtc->vm, "RTC update halted by guest"); in vrtc_time_update()
452 vrtc->base_rtctime++; in vrtc_time_update()
454 vrtc->base_rtctime = newtime; in vrtc_time_update()
461 secs_to_rtc(vrtc->base_rtctime, vrtc, 0); 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()
469 } while (vrtc->base_rtctime != newtime); in vrtc_time_update()
472 vrtc_set_reg_c(vrtc, rtc->reg_c | RTCIR_UPDATE); in vrtc_time_update()
504 * If both periodic and alarm interrupts are enabled then use the in vrtc_freq()
510 if (pintr_enabled(vrtc) && divider_enabled(vrtc->rtcdev.reg_a)) { in vrtc_freq()
511 ratesel = vrtc->rtcdev.reg_a & 0xf; in vrtc_freq()
529 if (callout_active(&vrtc->callout)) { in vrtc_callout_reset()
530 VM_CTR0(vrtc->vm, "RTC callout stopped"); in vrtc_callout_reset()
531 callout_stop(&vrtc->callout); in vrtc_callout_reset()
535 VM_CTR1(vrtc->vm, "RTC callout frequency %d hz", SBT_1S / freqsbt); in vrtc_callout_reset()
536 callout_reset_sbt(&vrtc->callout, freqsbt, 0, vrtc_callout_handler, in vrtc_callout_reset()
548 VM_CTR0(vrtc->vm, "vrtc callout fired"); in vrtc_callout_handler()
551 if (callout_pending(&vrtc->callout)) /* callout was reset */ in vrtc_callout_handler()
554 if (!callout_active(&vrtc->callout)) /* callout was stopped */ in vrtc_callout_handler()
557 callout_deactivate(&vrtc->callout); in vrtc_callout_handler()
559 KASSERT((vrtc->rtcdev.reg_b & RTCSB_ALL_INTRS) != 0, in vrtc_callout_handler()
563 vrtc_set_reg_c(vrtc, vrtc->rtcdev.reg_c | RTCIR_PERIOD); in vrtc_callout_handler()
584 active = callout_active(&vrtc->callout) ? 1 : 0; in vrtc_callout_check()
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()
621 vatpic_pulse_irq(vrtc->vm, RTC_IRQ); in vrtc_set_reg_c()
622 vioapic_pulse_irq(vrtc->vm, RTC_IRQ); in vrtc_set_reg_c()
624 VM_CTR1(vrtc->vm, "RTC irq %d deasserted", RTC_IRQ); in vrtc_set_reg_c()
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()
656 return (-1); in vrtc_set_reg_b()
660 KASSERT(curtime == vrtc->base_rtctime, ("%s: mismatch " in vrtc_set_reg_b()
662 __func__, vrtc->base_rtctime, curtime)); in vrtc_set_reg_b()
676 rtc->reg_b &= ~RTCSB_UINTR; in vrtc_set_reg_b()
686 vrtc_set_reg_c(vrtc, vrtc->rtcdev.reg_c); in vrtc_set_reg_b()
713 oldval = vrtc->rtcdev.reg_a; in vrtc_set_reg_a()
717 VM_CTR2(vrtc->vm, "RTC divider held in reset at %#lx/%#lx", in vrtc_set_reg_a()
718 vrtc->base_rtctime, vrtc->base_uptime); in vrtc_set_reg_a()
726 vrtc->base_uptime = sbinuptime(); in vrtc_set_reg_a()
727 VM_CTR2(vrtc->vm, "RTC divider out of reset at %#lx/%#lx", in vrtc_set_reg_a()
728 vrtc->base_rtctime, vrtc->base_uptime); in vrtc_set_reg_a()
733 vrtc->rtcdev.reg_a = newval; in vrtc_set_reg_a()
736 VM_CTR2(vrtc->vm, "RTC reg_a changed from %#x to %#x", in vrtc_set_reg_a()
741 * Side effect of changes to rate select and divider enable bits. 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()
799 VM_CTR1(vrtc->vm, "RTC nvram write to invalid offset %d", in vrtc_nvram_write()
805 ptr = (uint8_t *)(&vrtc->rtcdev); in vrtc_nvram_write()
807 VM_CTR2(vrtc->vm, "RTC nvram write %#x to offset %#x", value, offset); in vrtc_nvram_write()
838 ptr = (uint8_t *)(&vrtc->rtcdev); in vrtc_nvram_read()
853 return (-1); in vrtc_addr_handler()
861 vrtc->addr = *val & 0x7f; in vrtc_addr_handler()
877 rtc = &vrtc->rtcdev; in vrtc_data_handler()
880 return (-1); in vrtc_data_handler()
883 offset = vrtc->addr; in vrtc_data_handler()
886 return (-1); in vrtc_data_handler()
896 * This is not just for reads of the RTC. The side-effect of writing in vrtc_data_handler()
910 *val = vrtc->rtcdev.reg_c; in vrtc_data_handler()
950 * outside of RTCSB_HALT so re-calculate the RTC date/time. in vrtc_data_handler()
957 error = -1; in vrtc_data_handler()
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()
987 vrtc->vm = vm; in vrtc_init()
988 mtx_init(&vrtc->mtx, "vrtc lock", NULL, MTX_DEF); in vrtc_init()
989 callout_init(&vrtc->callout, 1); in vrtc_init()
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()
999 vrtc->addr = RTC_STATUSD; in vrtc_init()
1007 vrtc->base_rtctime = VRTC_BROKEN_TIME; in vrtc_init()
1019 callout_drain(&vrtc->callout); in vrtc_cleanup()
1020 mtx_destroy(&vrtc->mtx); in vrtc_cleanup()
1032 SNAPSHOT_VAR_OR_LEAVE(vrtc->addr, meta, ret, done); in vrtc_snapshot()
1033 if (meta->op == VM_SNAPSHOT_RESTORE) in vrtc_snapshot()
1034 vrtc->base_uptime = sbinuptime(); in vrtc_snapshot()
1035 SNAPSHOT_VAR_OR_LEAVE(vrtc->base_rtctime, meta, ret, done); in vrtc_snapshot()
1037 SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.sec, meta, ret, done); in vrtc_snapshot()
1038 SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.alarm_sec, meta, ret, done); in vrtc_snapshot()
1039 SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.min, meta, ret, done); in vrtc_snapshot()
1040 SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.alarm_min, meta, ret, done); in vrtc_snapshot()
1041 SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.hour, meta, ret, done); in vrtc_snapshot()
1042 SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.alarm_hour, meta, ret, done); in vrtc_snapshot()
1043 SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.day_of_week, meta, ret, done); in vrtc_snapshot()
1044 SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.day_of_month, meta, ret, done); in vrtc_snapshot()
1045 SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.month, meta, ret, done); in vrtc_snapshot()
1046 SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.year, meta, ret, done); in vrtc_snapshot()
1047 SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.reg_a, meta, ret, done); in vrtc_snapshot()
1048 SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.reg_b, meta, ret, done); in vrtc_snapshot()
1049 SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.reg_c, meta, ret, done); in vrtc_snapshot()
1050 SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.reg_d, meta, ret, done); in vrtc_snapshot()
1051 SNAPSHOT_BUF_OR_LEAVE(vrtc->rtcdev.nvram, sizeof(vrtc->rtcdev.nvram), in vrtc_snapshot()
1053 SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.century, meta, ret, done); in vrtc_snapshot()
1054 SNAPSHOT_BUF_OR_LEAVE(vrtc->rtcdev.nvram2, sizeof(vrtc->rtcdev.nvram2), in vrtc_snapshot()