191f5718tmm/*- 2d8596f6pfg * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3d8596f6pfg * 491f5718tmm * Copyright (c) 1996 The NetBSD Foundation, Inc. 591f5718tmm * All rights reserved. 691f5718tmm * 791f5718tmm * This code is derived from software contributed to The NetBSD Foundation 891f5718tmm * by Gordon W. Ross 991f5718tmm * 1091f5718tmm * Redistribution and use in source and binary forms, with or without 1191f5718tmm * modification, are permitted provided that the following conditions 1291f5718tmm * are met: 1391f5718tmm * 1. Redistributions of source code must retain the above copyright 1491f5718tmm * notice, this list of conditions and the following disclaimer. 1591f5718tmm * 2. Redistributions in binary form must reproduce the above copyright 1691f5718tmm * notice, this list of conditions and the following disclaimer in the 1791f5718tmm * documentation and/or other materials provided with the distribution. 1891f5718tmm * 1991f5718tmm * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 2091f5718tmm * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 2191f5718tmm * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 2291f5718tmm * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 2391f5718tmm * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2491f5718tmm * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2591f5718tmm * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2691f5718tmm * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2791f5718tmm * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2891f5718tmm * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2991f5718tmm * POSSIBILITY OF SUCH DAMAGE. 3091f5718tmm * 3191f5718tmm * $NetBSD: clock_subr.h,v 1.7 2000/10/03 13:41:07 tsutsui Exp $ 3291f5718tmm * 338d647daphk * 348d647daphk * This file is the central clearing-house for calendrical issues. 358d647daphk * 368d647daphk * In general the kernel does not know about minutes, hours, days, timezones, 378d647daphk * daylight savings time, leap-years and such. All that is theoretically a 388d647daphk * matter for userland only. 398d647daphk * 408d647daphk * Parts of kernel code does however care: badly designed filesystems store 418d647daphk * timestamps in local time and RTC chips sometimes track time in a local 428d647daphk * timezone instead of UTC and so on. 438d647daphk * 448d647daphk * All that code should go here for service. 458d647daphk * 4691f5718tmm * $FreeBSD$ 4791f5718tmm */ 4891f5718tmm 4991f5718tmm#ifndef _SYS_CLOCK_H_ 5091f5718tmm#define _SYS_CLOCK_H_ 5191f5718tmm 5250c81b8phk#ifdef _KERNEL /* No user serviceable parts */ 5350c81b8phk 5452fd275phkint utc_offset(void); 5552fd275phk 5691f5718tmm/* 579c7cac6ian * Structure to hold the values typically reported by time-of-day clocks, 589c7cac6ian * expressed as binary integers (see below for a BCD version). This can be 599c7cac6ian * passed to the conversion functions to be converted to/from a struct timespec. 609c7cac6ian * 619c7cac6ian * On input, the year is interpreted as follows: 629c7cac6ian * 0 - 69 = 2000 - 2069 639c7cac6ian * 70 - 99 = 1970 - 1999 649c7cac6ian * 100 - 199 = 2000 - 2099 (Supports hardware "century bit".) 659c7cac6ian * 200 - 1969 = Invalid. 669c7cac6ian * 1970 - 9999 = Full 4-digit century+year. 679c7cac6ian * 689c7cac6ian * The dow field is ignored (not even validated) on input, but is always 699c7cac6ian * populated with day-of-week on output. 709c7cac6ian * 719c7cac6ian * clock_ct_to_ts() returns EINVAL if any values are out of range. The year 729c7cac6ian * field will always be 4-digit on output. 7391f5718tmm */ 7491f5718tmmstruct clocktime { 756bce57cimp int year; /* year (4 digit year) */ 7691f5718tmm int mon; /* month (1 - 12) */ 7791f5718tmm int day; /* day (1 - 31) */ 7891f5718tmm int hour; /* hour (0 - 23) */ 7991f5718tmm int min; /* minute (0 - 59) */ 8091f5718tmm int sec; /* second (0 - 59) */ 8191f5718tmm int dow; /* day of week (0 - 6; 0 = Sunday) */ 8291f5718tmm long nsec; /* nano seconds */ 8391f5718tmm}; 8491f5718tmm 857f4e81cianint clock_ct_to_ts(const struct clocktime *, struct timespec *); 867f4e81cianvoid clock_ts_to_ct(const struct timespec *, struct clocktime *); 8791f22a6ian 8891f22a6ian/* 899c7cac6ian * Structure to hold the values typically reported by time-of-day clocks, 909c7cac6ian * expressed as BCD. This can be passed to the conversion functions to be 919c7cac6ian * converted to/from a struct timespec. 929c7cac6ian * 939c7cac6ian * The clock_bcd_to_ts() function interprets the values in the year through sec 949c7cac6ian * fields as BCD numbers, and returns EINVAL if any BCD values are out of range. 959c7cac6ian * After conversion to binary, the values are passed to clock_ct_to_ts() and 969c7cac6ian * undergo further validation as described above. Year may be 2 or 4-digit BCD, 979c7cac6ian * interpreted as described above. The nsec field is binary. If the ampm arg 989c7cac6ian * is true, the incoming hour and ispm values are interpreted as 12-hour am/pm 999c7cac6ian * representation of the hour, otherwise hour is interpreted as 24-hour and ispm 1009c7cac6ian * is ignored. 1019c7cac6ian * 1029c7cac6ian * The clock_ts_to_bcd() function converts the timespec to BCD values stored 1039c7cac6ian * into year through sec. The value in year will be 4-digit BCD (e.g., 1049c7cac6ian * 0x2017). The mon through sec values will be 2-digit BCD. The nsec field will 1059c7cac6ian * be binary, and the range of dow makes its binary and BCD values identical. 1069c7cac6ian * If the ampm arg is true, the hour and ispm fields are set to the 12-hour 1079c7cac6ian * time plus a pm flag, otherwise the hour is set to 24-hour time and ispm is 1089c7cac6ian * set to false. 1099c7cac6ian */ 1109c7cac6ianstruct bcd_clocktime { 1119c7cac6ian uint16_t year; /* year (2 or 4 digit year) */ 1129c7cac6ian uint8_t mon; /* month (1 - 12) */ 1139c7cac6ian uint8_t day; /* day (1 - 31) */ 1149c7cac6ian uint8_t hour; /* hour (0 - 23 or 1 - 12) */ 1159c7cac6ian uint8_t min; /* minute (0 - 59) */ 1169c7cac6ian uint8_t sec; /* second (0 - 59) */ 1179c7cac6ian uint8_t dow; /* day of week (0 - 6; 0 = Sunday) */ 1189c7cac6ian long nsec; /* nanoseconds */ 1199c7cac6ian bool ispm; /* true if hour represents pm time */ 1209c7cac6ian}; 1219c7cac6ian 1227f4e81cianint clock_bcd_to_ts(const struct bcd_clocktime *, struct timespec *, bool ampm); 1237f4e81cianvoid clock_ts_to_bcd(const struct timespec *, struct bcd_clocktime *, bool ampm); 1249c7cac6ian 1259c7cac6ian/* 1264b1f61bian * Time-of-day clock functions and flags. These functions might sleep. 1274b1f61bian * 1284b1f61bian * clock_register and clock_unregister() do what they say. Upon return from 1294b1f61bian * unregister, the clock's methods are not running and will not be called again. 1304b1f61bian * 1314b1f61bian * clock_schedule() requests that a registered clock's clock_settime() calls 1324b1f61bian * happen at the given offset into the second. The default is 0, meaning no 1334b1f61bian * specific scheduling. To schedule the call as soon after top-of-second as 1344b1f61bian * possible, specify 1. Each clock has its own schedule, but taskqueue_thread 1354b1f61bian * is shared by many tasks; the timing of the call is not guaranteed. 13691f22a6ian * 13791f22a6ian * Flags: 13891f22a6ian * 13991f22a6ian * CLOCKF_SETTIME_NO_TS 14091f22a6ian * Do not pass a timespec to clock_settime(), the driver obtains its own time 14191f22a6ian * and applies its own adjustments (this flag implies CLOCKF_SETTIME_NO_ADJ). 14291f22a6ian * 14391f22a6ian * CLOCKF_SETTIME_NO_ADJ 14491f22a6ian * Do not apply utc offset and resolution/accuracy adjustments to the value 14591f22a6ian * passed to clock_settime(), the driver applies them itself. 14691f22a6ian * 14791f22a6ian * CLOCKF_GETTIME_NO_ADJ 14891f22a6ian * Do not apply utc offset and resolution/accuracy adjustments to the value 14991f22a6ian * returned from clock_gettime(), the driver has already applied them. 15091f22a6ian */ 15191f22a6ian 15291f22a6ian#define CLOCKF_SETTIME_NO_TS 0x00000001 15391f22a6ian#define CLOCKF_SETTIME_NO_ADJ 0x00000002 15491f22a6ian#define CLOCKF_GETTIME_NO_ADJ 0x00000004 15591f22a6ian 15691f22a6ianvoid clock_register(device_t _clockdev, long _resolution_us); 15791f22a6ianvoid clock_register_flags(device_t _clockdev, long _resolution_us, int _flags); 1584b1f61bianvoid clock_schedule(device_t clockdev, u_int _offsetns); 15991f22a6ianvoid clock_unregister(device_t _clockdev); 16091f5718tmm 16191f5718tmm/* 16291f5718tmm * BCD to decimal and decimal to BCD. 16391f5718tmm */ 16450c81b8phk#define FROMBCD(x) bcd2bin(x) 16550c81b8phk#define TOBCD(x) bin2bcd(x) 16691f5718tmm 16791f5718tmm/* Some handy constants. */ 16891f5718tmm#define SECDAY (24 * 60 * 60) 16991f5718tmm#define SECYR (SECDAY * 365) 17091f5718tmm 17191f5718tmm/* Traditional POSIX base year */ 17291f5718tmm#define POSIX_BASE_YEAR 1970 17391f5718tmm 1747f4e81cianvoid timespec2fattime(const struct timespec *tsp, int utc, u_int16_t *ddp, 1757f4e81cian u_int16_t *dtp, u_int8_t *dhp); 1767f4e81cianvoid fattime2timespec(unsigned dd, unsigned dt, unsigned dh, int utc, 1777f4e81cian struct timespec *tsp); 178cc74fcaphk 17919e2991ian/* 18019e2991ian * Print a [bcd_]clocktime or timespec, optionally with fractional seconds. The 18119e2991ian * nsdig argument can range from 0-9, and specifies how many decimal digits to 18219e2991ian * display for fractional seconds. 18319e2991ian */ 18419e2991ianvoid clock_print_bcd(const struct bcd_clocktime *bct, int nsdig); 18519e2991ianvoid clock_print_ct(const struct clocktime *ct, int nsdig); 18619e2991ianvoid clock_print_ts(const struct timespec *ts, int nsdig); 18719e2991ian 188e5909c1ian/* 189e5909c1ian * Debugging helpers for RTC clock drivers. Print a [bcd_]clocktime or 190e5909c1ian * timespec, only if rtc clock debugging has been enabled. The rw argument is 191e5909c1ian * one of CLOCK_DBG_READ or CLOCK_DBG_WRITE. 192e5909c1ian */ 193e5909c1ian#define CLOCK_DBG_READ 0x01 194e5909c1ian#define CLOCK_DBG_WRITE 0x02 195e5909c1ianvoid clock_dbgprint_bcd(device_t dev, int rw, const struct bcd_clocktime *bct); 196e5909c1ianvoid clock_dbgprint_ct(device_t dev, int rw, const struct clocktime *ct); 197e5909c1ianvoid clock_dbgprint_err(device_t dev, int rw, int err); 198e5909c1ianvoid clock_dbgprint_ts(device_t dev, int rw, const struct timespec *ts); 199e5909c1ian 20050c81b8phk#endif /* _KERNEL */ 20150c81b8phk 20291f5718tmm#endif /* !_SYS_CLOCK_H_ */ 203