Page MenuHomeFreeBSD

D13730.diff
No OneTemporary

D13730.diff

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

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)

Event Timeline