Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F103549444
D13730.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
D13730.diff
View Options
Index: sys/kern/subr_clock.c
===================================================================
--- sys/kern/subr_clock.c
+++ sys/kern/subr_clock.c
@@ -199,6 +199,55 @@
return (0);
}
+int
+clock_bcd_to_ts(struct bcd_clocktime *bct, struct timespec *ts, bool ampm)
+{
+ struct clocktime ct;
+ int bcent, byear;
+
+ /*
+ * Year may come in as 2-digit or 4-digit BCD. Split the value into
+ * separate BCD century and year values for validation and conversion.
+ */
+ bcent = bct->year >> 8;
+ byear = bct->year & 0xff;
+
+ /*
+ * Ensure that all values are valid BCD numbers, to avoid assertions in
+ * the BCD-to-binary conversion routines. clock_ct_to_ts() will further
+ * validate the field ranges (such as 0 <= min <= 59) during conversion.
+ */
+ if (!validbcd(bcent) || !validbcd(byear) || !validbcd(bct->mon) ||
+ !validbcd(bct->day) || !validbcd(bct->hour) ||
+ !validbcd(bct->min) || !validbcd(bct->sec)) {
+ if (ct_debug)
+ printf("clock_bcd_to_ts: bad BCD: "
+ "[%04x-%02x-%02x %02x:%02x:%02x]\n",
+ bct->year, bct->mon, bct->day,
+ bct->hour, bct->min, bct->sec);
+ return (EINVAL);
+ }
+
+ ct.year = FROMBCD(byear) + FROMBCD(bcent) * 100;
+ ct.mon = FROMBCD(bct->mon);
+ ct.day = FROMBCD(bct->day);
+ ct.hour = FROMBCD(bct->hour);
+ ct.min = FROMBCD(bct->min);
+ ct.sec = FROMBCD(bct->sec);
+ ct.dow = bct->dow;
+ ct.nsec = bct->nsec;
+
+ /* If asked to handle am/pm, convert from 12hr+pmflag to 24hr. */
+ if (ampm) {
+ if (ct.hour == 12)
+ ct.hour = 0;
+ if (bct->ispm)
+ ct.hour += 12;
+ }
+
+ return (clock_ct_to_ts(&ct, ts));
+}
+
void
clock_ts_to_ct(struct timespec *ts, struct clocktime *ct)
{
@@ -260,6 +309,34 @@
("seconds %d not in 0-60", ct->sec));
}
+void
+clock_ts_to_bcd(struct timespec *ts, struct bcd_clocktime *bct, bool ampm)
+{
+ struct clocktime ct;
+
+ clock_ts_to_ct(ts, &ct);
+
+ /* If asked to handle am/pm, convert from 24hr to 12hr+pmflag. */
+ bct->ispm = false;
+ if (ampm) {
+ if (ct.hour >= 12) {
+ ct.hour -= 12;
+ bct->ispm = true;
+ }
+ if (ct.hour == 0)
+ ct.hour = 12;
+ }
+
+ bct->year = TOBCD(ct.year % 100) | (TOBCD(ct.year / 100) << 8);
+ bct->mon = TOBCD(ct.mon);
+ bct->day = TOBCD(ct.day);
+ bct->hour = TOBCD(ct.hour);
+ bct->min = TOBCD(ct.min);
+ bct->sec = TOBCD(ct.sec);
+ bct->dow = ct.dow;
+ bct->nsec = ct.nsec;
+}
+
int
utc_offset(void)
{
Index: sys/sys/clock.h
===================================================================
--- sys/sys/clock.h
+++ sys/sys/clock.h
@@ -60,9 +60,22 @@
int utc_offset(void);
/*
- * Structure to hold the values typically reported by time-of-day clocks.
- * This can be passed to the generic conversion functions to be converted
- * to a struct timespec.
+ * Structure to hold the values typically reported by time-of-day clocks,
+ * expressed as binary integers (see below for a BCD version). This can be
+ * passed to the conversion functions to be converted to/from a struct timespec.
+ *
+ * On input, the year is interpreted as follows:
+ * 0 - 69 = 2000 - 2069
+ * 70 - 99 = 1970 - 1999
+ * 100 - 199 = 2000 - 2099 (Supports hardware "century bit".)
+ * 200 - 1969 = Invalid.
+ * 1970 - 9999 = Full 4-digit century+year.
+ *
+ * The dow field is ignored (not even validated) on input, but is always
+ * populated with day-of-week on output.
+ *
+ * clock_ct_to_ts() returns EINVAL if any values are out of range. The year
+ * field will always be 4-digit on output.
*/
struct clocktime {
int year; /* year (4 digit year) */
@@ -79,6 +92,43 @@
void clock_ts_to_ct(struct timespec *, struct clocktime *);
/*
+ * Structure to hold the values typically reported by time-of-day clocks,
+ * expressed as BCD. This can be passed to the conversion functions to be
+ * converted to/from a struct timespec.
+ *
+ * The clock_bcd_to_ts() function interprets the values in the year through sec
+ * fields as BCD numbers, and returns EINVAL if any BCD values are out of range.
+ * After conversion to binary, the values are passed to clock_ct_to_ts() and
+ * undergo further validation as described above. Year may be 2 or 4-digit BCD,
+ * interpreted as described above. The nsec field is binary. If the ampm arg
+ * is true, the incoming hour and ispm values are interpreted as 12-hour am/pm
+ * representation of the hour, otherwise hour is interpreted as 24-hour and ispm
+ * is ignored.
+ *
+ * The clock_ts_to_bcd() function converts the timespec to BCD values stored
+ * into year through sec. The value in year will be 4-digit BCD (e.g.,
+ * 0x2017). The mon through sec values will be 2-digit BCD. The nsec field will
+ * be binary, and the range of dow makes its binary and BCD values identical.
+ * If the ampm arg is true, the hour and ispm fields are set to the 12-hour
+ * time plus a pm flag, otherwise the hour is set to 24-hour time and ispm is
+ * set to false.
+ */
+struct bcd_clocktime {
+ uint16_t year; /* year (2 or 4 digit year) */
+ uint8_t mon; /* month (1 - 12) */
+ uint8_t day; /* day (1 - 31) */
+ uint8_t hour; /* hour (0 - 23 or 1 - 12) */
+ uint8_t min; /* minute (0 - 59) */
+ uint8_t sec; /* second (0 - 59) */
+ uint8_t dow; /* day of week (0 - 6; 0 = Sunday) */
+ long nsec; /* nanoseconds */
+ bool ispm; /* true if hour represents pm time */
+};
+
+int clock_bcd_to_ts(struct bcd_clocktime *, struct timespec *, bool ampm);
+void clock_ts_to_bcd(struct timespec *, struct bcd_clocktime *, bool ampm);
+
+/*
* Time-of-day clock functions and flags. These functions might sleep.
*
* clock_register and clock_unregister() do what they say. Upon return from
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Nov 27, 9:50 AM (13 h, 50 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14882920
Default Alt Text
D13730.diff (5 KB)
Attached To
Mode
D13730: Add RTC clock conversions for BCD values, with non-panic validation.
Attached
Detach File
Event Timeline
Log In to Comment