| 868 | } |
| 869 | |
| 870 | int |
| 871 | vrtc_data_handler(struct vm *vm, int vcpuid, bool in, int port, int bytes, |
| 872 | uint32_t *val) |
| 873 | { |
| 874 | struct vrtc *vrtc; |
| 875 | struct rtcdev *rtc; |
| 876 | sbintime_t basetime; |
| 877 | time_t curtime; |
| 878 | int error, offset; |
| 879 | |
| 880 | vrtc = vm_rtc(vm); |
| 881 | rtc = &vrtc->rtcdev; |
| 882 | |
| 883 | if (bytes != 1) |
| 884 | return (-1); |
| 885 | |
| 886 | VRTC_LOCK(vrtc); |
| 887 | offset = vrtc->addr; |
| 888 | if (offset >= sizeof(struct rtcdev)) { |
| 889 | VRTC_UNLOCK(vrtc); |
| 890 | return (-1); |
| 891 | } |
| 892 | |
| 893 | error = 0; |
| 894 | curtime = vrtc_curtime(vrtc, &basetime); |
| 895 | vrtc_time_update(vrtc, curtime, basetime); |
| 896 | |
| 897 | /* |
| 898 | * Update RTC date/time fields if necessary. |
| 899 | * |
| 900 | * This is not just for reads of the RTC. The side-effect of writing |
| 901 | * the century byte requires other RTC date/time fields (e.g. sec) |
| 902 | * to be updated here. |
| 903 | */ |
| 904 | if (offset < 10 || offset == RTC_CENTURY) |
| 905 | secs_to_rtc(curtime, vrtc, 0); |
| 906 | |
| 907 | if (in) { |
| 908 | if (offset == 12) { |
| 909 | /* |
| 910 | * XXX |
| 911 | * reg_c interrupt flags are updated only if the |
| 912 | * corresponding interrupt enable bit in reg_b is set. |
| 913 | */ |
| 914 | *val = vrtc->rtcdev.reg_c; |
| 915 | vrtc_set_reg_c(vrtc, 0); |
| 916 | } else { |
| 917 | *val = *((uint8_t *)rtc + offset); |
| 918 | } |
| 919 | VCPU_CTR2(vm, vcpuid, "Read value %#x from RTC offset %#x", |
| 920 | *val, offset); |
| 921 | } else { |
| 922 | switch (offset) { |
| 923 | case 10: |
| 924 | VCPU_CTR1(vm, vcpuid, "RTC reg_a set to %#x", *val); |
| 925 | vrtc_set_reg_a(vrtc, *val); |
| 926 | break; |
| 927 | case 11: |
nothing calls this directly
no test coverage detected