time.c revision 228782
1139825Simp/*- 21541Srgrimes * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> 31541Srgrimes * All rights reserved. 41541Srgrimes * 51541Srgrimes * Redistribution and use in source and binary forms, with or without 61541Srgrimes * modification, are permitted provided that the following conditions 71541Srgrimes * are met: 81541Srgrimes * 1. Redistributions of source code must retain the above copyright 91541Srgrimes * notice, this list of conditions and the following disclaimer. 101541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111541Srgrimes * notice, this list of conditions and the following disclaimer in the 121541Srgrimes * documentation and/or other materials provided with the distribution. 131541Srgrimes * 141541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 151541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 161541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 171541Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 181541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 191541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 201541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 211541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 221541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 231541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 241541Srgrimes * SUCH DAMAGE. 251541Srgrimes */ 261541Srgrimes 271541Srgrimes#include <sys/cdefs.h> 281541Srgrimes__FBSDID("$FreeBSD: head/sys/boot/i386/libi386/time.c 228782 2011-12-21 16:47:01Z ed $"); 291541Srgrimes 3050477Speter#include <stand.h> 311541Srgrimes#include <btxv86.h> 321541Srgrimes#include "bootstrap.h" 331541Srgrimes#include "libi386.h" 341541Srgrimes 351541Srgrimesstatic int bios_seconds(void); 36143063Sjoerg 37143063Sjoerg/* 38143063Sjoerg * Return the BIOS time-of-day value. 3924778Sbde * 4024778Sbde * XXX uses undocumented BCD support from libstand. 4124778Sbde */ 4224778Sbdestatic int 431541Srgrimesbios_seconds(void) 441541Srgrimes{ 451541Srgrimes int hr, minute, sec; 461541Srgrimes 471541Srgrimes v86.ctl = 0; 4824778Sbde v86.addr = 0x1a; /* int 0x1a, function 2 */ 4924778Sbde v86.eax = 0x0200; 501541Srgrimes v86int(); 511541Srgrimes 52 hr = bcd2bin((v86.ecx & 0xff00) >> 8); /* hour in %ch */ 53 minute = bcd2bin(v86.ecx & 0xff); /* minute in %cl */ 54 sec = bcd2bin((v86.edx & 0xff00) >> 8); /* second in %dh */ 55 56 return (hr * 3600 + minute * 60 + sec); 57} 58 59/* 60 * Return the time in seconds since the beginning of the day. 61 * 62 * Some BIOSes (notably qemu) don't correctly read the RTC 63 * registers in an atomic way, sometimes returning bogus values. 64 * Therefore we "debounce" the reading by accepting it only when 65 * we got 8 identical values in succession. 66 * 67 * If we pass midnight, don't wrap back to 0. 68 */ 69time_t 70time(time_t *t) 71{ 72 static time_t lasttime; 73 time_t now, check; 74 int same, try; 75 76 same = try = 0; 77 check = bios_seconds(); 78 do { 79 now = check; 80 check = bios_seconds(); 81 if (check != now) 82 same = 0; 83 } while (++same < 8 && ++try < 1000); 84 85 if (now < lasttime) 86 now += 24 * 3600; 87 lasttime = now; 88 89 if (t != NULL) 90 *t = now; 91 return(now); 92} 93 94/* 95 * Use the BIOS Wait function to pause for (period) microseconds. 96 * 97 * Resolution of this function is variable, but typically around 98 * 1ms. 99 */ 100void 101delay(int period) 102{ 103 v86.ctl = 0; 104 v86.addr = 0x15; /* int 0x15, function 0x86 */ 105 v86.eax = 0x8600; 106 v86.ecx = period >> 16; 107 v86.edx = period & 0xffff; 108 v86int(); 109} 110