aboutsummaryrefslogtreecommitdiff
path: root/sys/sys/clock.h
diff options
context:
space:
mode:
authorIan Lepore <ian@FreeBSD.org>2018-01-14 17:01:37 +0000
committerIan Lepore <ian@FreeBSD.org>2018-01-14 17:01:37 +0000
commit862993757a9c45a9c87b1c0b02a9513d44171601 (patch)
tree97eeaafc7eeb4582e945e4aa0a04de3368ee903f /sys/sys/clock.h
parent3922493a2155b51de406efc762ff1be186ad4ee1 (diff)
downloadsrc-862993757a9c45a9c87b1c0b02a9513d44171601.tar.gz
src-862993757a9c45a9c87b1c0b02a9513d44171601.zip
Add RTC clock conversions for BCD values, with non-panic validation.
RTC clock hardware frequently uses BCD numbers. Currently the low-level bcd2bin() and bin2bcd() functions will KASSERT if given out-of-range BCD values. Every RTC driver must implement its own code for validating the unreliable data coming from the hardware to avoid a potential kernel panic. This change introduces two new functions, clock_bcd_to_ts() and clock_ts_to_bcd(). The former validates its inputs and returns EINVAL if any values are out of range. The latter guarantees the returned data will be valid BCD in a known format (4-digit years, etc). A new bcd_clocktime structure is used with the new functions. It is similar to the original clocktime structure, but defines the fields holding BCD values as uint8_t (uint16_t for year), and adds a PM flag for handling hours using AM/PM mode. PR: 224813 Differential Revision: https://reviews.freebsd.org/D13730 (no reviewers)
Notes
Notes: svn path=/head/; revision=327971
Diffstat (limited to 'sys/sys/clock.h')
-rw-r--r--sys/sys/clock.h56
1 files changed, 53 insertions, 3 deletions
diff --git a/sys/sys/clock.h b/sys/sys/clock.h
index 5c09ba824461..1a59950761c9 100644
--- a/sys/sys/clock.h
+++ b/sys/sys/clock.h
@@ -60,9 +60,22 @@ extern int tz_dsttime;
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 @@ int clock_ct_to_ts(struct clocktime *, struct timespec *);
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