Author: neel
Date: Sat Mar 28 02:55:16 2015
New Revision: 280775
URL: https://svnweb.freebsd.org/changeset/base/280775

Log:
  Fix the RTC device model to operate correctly in 12-hour mode. The following
  table documents the values in the RTC 'hour' field in the two modes:
  
  Hour-of-the-day               12-hour mode    24-hour mode
  12    AM              12              0
  [1-11]        AM              [1-11]          [1-11]
  12    PM              0x80 | 12       12
  [1-11]        PM              0x80 | [1-11]   [13-23]
  
  Reported by:  Julian Hsiao (mad...@nyanisore.net)
  MFC after:    1 week

Modified:
  head/sys/amd64/vmm/io/vrtc.c

Modified: head/sys/amd64/vmm/io/vrtc.c
==============================================================================
--- head/sys/amd64/vmm/io/vrtc.c        Sat Mar 28 02:36:49 2015        
(r280774)
+++ head/sys/amd64/vmm/io/vrtc.c        Sat Mar 28 02:55:16 2015        
(r280775)
@@ -214,9 +214,27 @@ secs_to_rtc(time_t rtctime, struct vrtc 
        rtc->sec = rtcset(rtc, ct.sec);
        rtc->min = rtcset(rtc, ct.min);
 
-       hour = ct.hour;
-       if ((rtc->reg_b & RTCSB_24HR) == 0)
-               hour = (hour % 12) + 1;     /* convert to a 12-hour format */
+       if (rtc->reg_b & RTCSB_24HR) {
+               hour = ct.hour;
+       } else {
+               /*
+                * Convert to the 12-hour format.
+                */
+               switch (ct.hour) {
+               case 0:                 /* 12 AM */
+               case 12:                /* 12 PM */
+                       hour = 12;
+                       break;
+               default:
+                       /*
+                        * The remaining 'ct.hour' values are interpreted as:
+                        * [1  - 11] ->  1 - 11 AM
+                        * [13 - 23] ->  1 - 11 PM
+                        */
+                       hour = ct.hour % 12;
+                       break;
+               }
+       }
 
        rtc->hour = rtcset(rtc, hour);
 
@@ -287,9 +305,26 @@ rtc_to_secs(struct vrtc *vrtc)
        }
        error = rtcget(rtc, hour, &ct.hour);
        if ((rtc->reg_b & RTCSB_24HR) == 0) {
-               ct.hour -= 1;
-               if (pm)
-                       ct.hour += 12;
+               if (ct.hour >= 1 && ct.hour <= 12) {
+                       /*
+                        * Convert from 12-hour format to internal 24-hour
+                        * representation as follows:
+                        *
+                        *    12-hour format            ct.hour
+                        *      12      AM              0
+                        *      1 - 11  AM              1 - 11
+                        *      12      PM              12
+                        *      1 - 11  PM              13 - 23
+                        */
+                       if (ct.hour == 12)
+                               ct.hour = 0;
+                       if (pm)
+                               ct.hour += 12;
+               } else {
+                       VM_CTR2(vm, "Invalid RTC 12-hour format %#x/%d",
+                           rtc->hour, ct.hour);
+                       goto fail;
+               }
        }
 
        if (error || ct.hour < 0 || ct.hour > 23) {
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to