/* $OpenBSD: time.c,v 1.9 1997/09/02 20:51:21 mickey Exp $ */ /* * Copyright (c) 1997 Michael Shalayeff * Copyright (c) 1997 Tobias Weingartner * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Tobias Weingartner. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include #include #include #include "libsa.h" #include "biosdev.h" #define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0) /* * Convert from bcd (packed) to int */ static __inline u_int8_t bcdtoint(register u_int8_t c) { return ((c & 0xf0) / 8) * 5 + (c & 0x0f); } /* * Quick compute of time in seconds since the Epoch */ static __inline time_t compute(year, month, day, hour, min, sec) int year; u_int8_t month, day, hour, min, sec; { /* Number of days per month */ static const u_short monthcount[] = { 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; register time_t tt; /* Compute days */ tt = (year - 1970) * 365 + monthcount[month] + day; /* Compute for leap year */ for(month <= 2? year--:0;year >= 1970;year--) if(isleap(year)) tt++; /* Plus the time */ tt = sec + 60 * (min + 60 * (tt * 24 + hour)); return tt; } static int bios_time_date(int f, register u_int8_t *b) { __asm __volatile(DOINT(0x1a) "\n\t" "setc %b0\n\t" "movb %%ch, 0(%2)\n\t" "movb %%cl, 1(%2)\n\t" "movb %%dh, 2(%2)\n\t" "movb %%dl, 3(%2)\n\t" : "=a" (f) : "0" (f), "p" (b) : "%ecx", "%edx", "cc"); if (f & 0xff) return -1; else { b[0] = bcdtoint(b[0]); b[1] = bcdtoint(b[1]); b[2] = bcdtoint(b[2]); b[3] = bcdtoint(b[3]); return 0; } } static __inline int biosdate(register u_int8_t *b) { return bios_time_date(4 << 8, b); } static __inline int biostime(register u_int8_t *b) { return bios_time_date(2 << 8, b); } /* * Return time since epoch */ time_t getsecs(void) { u_int8_t timebuf[4], datebuf[4]; /* Query BIOS for time & date */ if(!biostime(timebuf) && !biosdate(datebuf)) { #ifdef notdef int dst; dst = timebuf[3]; #endif /* Convert to seconds since Epoch */ return compute(datebuf[0] * 100 + datebuf[1], datebuf[2], datebuf[3], timebuf[0], timebuf[1], timebuf[2]); } else errno = EIO; return(1); } /* * Return time since epoch */ void time_print(void) { u_int8_t timebuf[4], datebuf[4]; /* Query BIOS for time & date */ if(!biostime(timebuf) && !biosdate(datebuf)) { #ifdef notdef int dst; dst = timebuf[3]; #endif /* Convert to sane values */ printf("%d/%d/%d - %d:%d:%d\n", datebuf[3], datebuf[2], datebuf[0] * 100 + datebuf[1], timebuf[0], timebuf[1], timebuf[2]); } else printf("no idea (in BIOS)\n"); return; } u_int sleep(i) u_int i; { register time_t t; /* loop for that number of seconds, polling BIOS, so that it may handle interrupts */ for (t = getsecs() + i; getsecs() < t; cnischar()); return 0; }