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
133 * - guest has not disabled updates
134 * - the date/time fields have valid contents
136 if (!divider_enabled(vrtc->rtcdev.reg_a))
142 if (vrtc->base_rtctime == VRTC_BROKEN_TIME)
156 t = vrtc->base_rtctime;
157 *basetime = vrtc->base_uptime;
160 delta = now - vrtc->base_uptime;
162 "%#lx to %#lx", vrtc->base_uptime, now));
177 return ((rtc->reg_b & RTCSB_BIN) ? val : bin2bcd_data[val]);
223 rtc = &vrtc->rtcdev;
224 rtc->sec = rtcset(rtc, ct.sec);
225 rtc->min = rtcset(rtc, ct.min);
227 if (rtc->reg_b & RTCSB_24HR) {
231 * Convert to the 12-hour format.
241 * [1 - 11] -> 1 - 11 AM
242 * [13 - 23] -> 1 - 11 PM
249 rtc->hour = rtcset(rtc, hour);
251 if ((rtc->reg_b & RTCSB_24HR) == 0 && ct.hour >= 12)
252 rtc->hour |= 0x80; /* set MSB to indicate PM */
254 rtc->day_of_week = rtcset(rtc, ct.dow + 1);
255 rtc->day_of_month = rtcset(rtc, ct.day);
256 rtc->month = rtcset(rtc, ct.mon);
257 rtc->year = rtcset(rtc, ct.year % 100);
258 rtc->century = rtcset(rtc, ct.year / 100);
266 if (rtc->reg_b & RTCSB_BIN) {
275 return (-1);
288 struct vm *vm = vrtc->vm;
294 rtc = &vrtc->rtcdev;
298 error = rtcget(rtc, rtc->sec, &ct.sec);
300 VM_CTR2(vm, "Invalid RTC sec %#x/%d", rtc->sec, ct.sec);
304 error = rtcget(rtc, rtc->min, &ct.min);
306 VM_CTR2(vm, "Invalid RTC min %#x/%d", rtc->min, ct.min);
311 hour = rtc->hour;
312 if ((rtc->reg_b & RTCSB_24HR) == 0) {
319 if ((rtc->reg_b & RTCSB_24HR) == 0) {
322 * Convert from 12-hour format to internal 24-hour
325 * 12-hour format ct.hour
327 * 1 - 11 AM 1 - 11
329 * 1 - 11 PM 13 - 23
336 VM_CTR2(vm, "Invalid RTC 12-hour format %#x/%d",
337 rtc->hour, ct.hour);
343 VM_CTR2(vm, "Invalid RTC hour %#x/%d", rtc->hour, ct.hour);
348 * Ignore 'rtc->dow' because some guests like Linux don't bother
353 ct.dow = -1;
355 error = rtcget(rtc, rtc->day_of_month, &ct.day);
357 VM_CTR2(vm, "Invalid RTC mday %#x/%d", rtc->day_of_month,
362 error = rtcget(rtc, rtc->month, &ct.mon);
364 VM_CTR2(vm, "Invalid RTC month %#x/%d", rtc->month, ct.mon);
368 error = rtcget(rtc, rtc->year, &year);
370 VM_CTR2(vm, "Invalid RTC year %#x/%d", rtc->year, year);
374 error = rtcget(rtc, rtc->century, ¢ury);
377 VM_CTR2(vm, "Invalid RTC century %#x/%d", rtc->century,
384 VM_CTR3(vm, "Invalid RTC clocktime.date %04d-%02d-%02d",
396 VM_CTR0(vrtc->vm, "Invalid RTC date/time programming detected");
409 rtc = &vrtc->rtcdev;
410 alarm_sec = rtc->alarm_sec;
411 alarm_min = rtc->alarm_min;
412 alarm_hour = rtc->alarm_hour;
414 oldtime = vrtc->base_rtctime;
415 VM_CTR2(vrtc->vm, "Updating RTC secs from %#lx to %#lx",
418 VM_CTR2(vrtc->vm, "Updating RTC base uptime from %#lx to %#lx",
419 vrtc->base_uptime, newbase);
420 vrtc->base_uptime = newbase;
431 vrtc->base_rtctime = VRTC_BROKEN_TIME;
439 VM_CTR0(vrtc->vm, "RTC update halted by guest");
452 vrtc->base_rtctime++;
454 vrtc->base_rtctime = newtime;
461 secs_to_rtc(vrtc->base_rtctime, vrtc, 0);
463 if ((alarm_sec >= 0xC0 || alarm_sec == rtc->sec) &&
464 (alarm_min >= 0xC0 || alarm_min == rtc->min) &&
465 (alarm_hour >= 0xC0 || alarm_hour == rtc->hour)) {
466 vrtc_set_reg_c(vrtc, rtc->reg_c | RTCIR_ALARM);
469 } while (vrtc->base_rtctime != newtime);
472 vrtc_set_reg_c(vrtc, rtc->reg_c | RTCIR_UPDATE);
504 * If both periodic and alarm interrupts are enabled then use the
510 if (pintr_enabled(vrtc) && divider_enabled(vrtc->rtcdev.reg_a)) {
511 ratesel = vrtc->rtcdev.reg_a & 0xf;
529 if (callout_active(&vrtc->callout)) {
530 VM_CTR0(vrtc->vm, "RTC callout stopped");
531 callout_stop(&vrtc->callout);
535 VM_CTR1(vrtc->vm, "RTC callout frequency %d hz", SBT_1S / freqsbt);
536 callout_reset_sbt(&vrtc->callout, freqsbt, 0, vrtc_callout_handler,
548 VM_CTR0(vrtc->vm, "vrtc callout fired");
551 if (callout_pending(&vrtc->callout)) /* callout was reset */
554 if (!callout_active(&vrtc->callout)) /* callout was stopped */
557 callout_deactivate(&vrtc->callout);
559 KASSERT((vrtc->rtcdev.reg_b & RTCSB_ALL_INTRS) != 0,
563 vrtc_set_reg_c(vrtc, vrtc->rtcdev.reg_c | RTCIR_PERIOD);
584 active = callout_active(&vrtc->callout) ? 1 : 0;
599 rtc = &vrtc->rtcdev;
602 oldirqf = rtc->reg_c & RTCIR_INT;
611 oldval = rtc->reg_c;
612 rtc->reg_c = newirqf | newval;
613 changed = oldval ^ rtc->reg_c;
615 VM_CTR2(vrtc->vm, "RTC reg_c changed from %#x to %#x",
616 oldval, rtc->reg_c);
620 VM_CTR1(vrtc->vm, "RTC irq %d asserted", RTC_IRQ);
621 vatpic_pulse_irq(vrtc->vm, RTC_IRQ);
622 vioapic_pulse_irq(vrtc->vm, RTC_IRQ);
624 VM_CTR1(vrtc->vm, "RTC irq %d deasserted", RTC_IRQ);
639 rtc = &vrtc->rtcdev;
640 oldval = rtc->reg_b;
643 rtc->reg_b = newval;
646 VM_CTR2(vrtc->vm, "RTC reg_b changed from %#x to %#x",
656 return (-1);
660 KASSERT(curtime == vrtc->base_rtctime, ("%s: mismatch "
662 __func__, vrtc->base_rtctime, curtime));
676 rtc->reg_b &= ~RTCSB_UINTR;
686 vrtc_set_reg_c(vrtc, vrtc->rtcdev.reg_c);
713 oldval = vrtc->rtcdev.reg_a;
717 VM_CTR2(vrtc->vm, "RTC divider held in reset at %#lx/%#lx",
718 vrtc->base_rtctime, vrtc->base_uptime);
726 vrtc->base_uptime = sbinuptime();
727 VM_CTR2(vrtc->vm, "RTC divider out of reset at %#lx/%#lx",
728 vrtc->base_rtctime, vrtc->base_uptime);
733 vrtc->rtcdev.reg_a = newval;
736 VM_CTR2(vrtc->vm, "RTC reg_a changed from %#x to %#x",
741 * Side effect of changes to rate select and divider enable bits.
762 VM_CTR2(vrtc->vm, "Error %d setting RTC time to %#lx", error,
765 VM_CTR1(vrtc->vm, "RTC time set to %#lx", secs);
799 VM_CTR1(vrtc->vm, "RTC nvram write to invalid offset %d",
805 ptr = (uint8_t *)(&vrtc->rtcdev);
807 VM_CTR2(vrtc->vm, "RTC nvram write %#x to offset %#x", value, offset);
838 ptr = (uint8_t *)(&vrtc->rtcdev);
853 return (-1);
861 vrtc->addr = *val & 0x7f;
877 rtc = &vrtc->rtcdev;
880 return (-1);
883 offset = vrtc->addr;
886 return (-1);
896 * This is not just for reads of the RTC. The side-effect of writing
910 *val = vrtc->rtcdev.reg_c;
950 * outside of RTCSB_HALT so re-calculate the RTC date/time.
957 error = -1;
971 rtc = &vrtc->rtcdev;
972 vrtc_set_reg_b(vrtc, rtc->reg_b & ~(RTCSB_ALL_INTRS | RTCSB_SQWE));
974 KASSERT(!callout_active(&vrtc->callout), ("rtc callout still active"));
987 vrtc->vm = vm;
988 mtx_init(&vrtc->mtx, "vrtc lock", NULL, MTX_DEF);
989 callout_init(&vrtc->callout, 1);
992 rtc = &vrtc->rtcdev;
993 rtc->reg_a = 0x20;
994 rtc->reg_b = RTCSB_24HR;
995 rtc->reg_c = 0;
996 rtc->reg_d = RTCSD_PWR;
999 vrtc->addr = RTC_STATUSD;
1007 vrtc->base_rtctime = VRTC_BROKEN_TIME;
1019 callout_drain(&vrtc->callout);
1020 mtx_destroy(&vrtc->mtx);
1032 SNAPSHOT_VAR_OR_LEAVE(vrtc->addr, meta, ret, done);
1033 if (meta->op == VM_SNAPSHOT_RESTORE)
1034 vrtc->base_uptime = sbinuptime();
1035 SNAPSHOT_VAR_OR_LEAVE(vrtc->base_rtctime, meta, ret, done);
1037 SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.sec, meta, ret, done);
1038 SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.alarm_sec, meta, ret, done);
1039 SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.min, meta, ret, done);
1040 SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.alarm_min, meta, ret, done);
1041 SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.hour, meta, ret, done);
1042 SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.alarm_hour, meta, ret, done);
1043 SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.day_of_week, meta, ret, done);
1044 SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.day_of_month, meta, ret, done);
1045 SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.month, meta, ret, done);
1046 SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.year, meta, ret, done);
1047 SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.reg_a, meta, ret, done);
1048 SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.reg_b, meta, ret, done);
1049 SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.reg_c, meta, ret, done);
1050 SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.reg_d, meta, ret, done);
1051 SNAPSHOT_BUF_OR_LEAVE(vrtc->rtcdev.nvram, sizeof(vrtc->rtcdev.nvram),
1053 SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.century, meta, ret, done);
1054 SNAPSHOT_BUF_OR_LEAVE(vrtc->rtcdev.nvram2, sizeof(vrtc->rtcdev.nvram2),