* Copyright (c) 1990 The Regents of the University of California.
* This code is derived from software contributed to Berkeley by
* William Jolitz and Don Ahn.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 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 the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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
* from: @(#)clock.c 7.2 (Berkeley) 5/12/91
* Primitive clock interrupt routines.
#include "machine/segments.h"
#include "i386/isa/icu.h"
#include "i386/isa/isa.h"
#include "i386/isa/rtc.h"
#include "i386/isa/timerreg.h"
/* X-tals being what they are, it's nice to be able to fudge this one... */
/* Note, the name changed here from XTALSPEED to TIMER_FREQ rgrimes 4/26/93 */
#define TIMER_FREQ 1193182 /* XXX - should be in isa.h */
findcpuspeed(); /* use the clock (while it's free)
/* initialize 8253 clock */
outb(TIMER_MODE
, TIMER_SEL0
|TIMER_RATEGEN
|TIMER_16BIT
);
/* Correct rounding will buy us a better precision in timekeeping */
outb (IO_TIMER1
, (TIMER_FREQ
+hz
/2)/hz
);
outb (IO_TIMER1
, ((TIMER_FREQ
+hz
/2)/hz
)/256);
/* initialize brain-dead battery powered clock */
outb (IO_RTC
, RTC_STATUSA
);
outb (IO_RTC
, RTC_STATUSB
);
printf("RTC BIOS diagnostic error %b\n", s
, RTCDG_BITS
);
unsigned int delaycount
; /* calibrated loop variable (1 millisecond) */
#define FIRST_GUESS 0x2000
/* Put counter in count down mode */
delaycount
= FIRST_GUESS
;
/* Read the value left in the counter */
low
= inb(IO_TIMER1
); /* least siginifcant */
remainder
= inb(IO_TIMER1
); /* most significant */
remainder
= (remainder
<<8) + low
;
/* Formula for delaycount is :
* (loopcount * timer clock speed)/ (counter ticks * 1000)
delaycount
= (FIRST_GUESS
* (TIMER_FREQ
/1000)) / (0xffff-remainder
);
/* convert 2 digit BCD number */
return ((i
/16)*10 + (i
%16));
/* convert years to seconds (from 1970) */
for(i
= 1970; i
< y
; i
++) {
if (i
% 4) ret
+= 365*24*60*60;
else ret
+= 366*24*60*60;
/* convert months to seconds */
case 1: case 3: case 5: case 7: case 8: case 10: case 12:
ret
+= 31*24*60*60; break;
case 4: case 6: case 9: case 11:
ret
+= 30*24*60*60; break;
if (leap
) ret
+= 29*24*60*60;
* Initialize the time of day register, based on the time base which is, e.g.
/* do we have a realtime clock present? (otherwise we loop below) */
if (sa
== 0xff || sa
== 0) return;
while ((sa
&RTCSA_TUP
) == RTCSA_TUP
)
sec
= bcd(rtcin(RTC_YEAR
)) + 1900;
leap
= !(sec
% 4); sec
= ytos(sec
); /* year */
yd
= mtos(bcd(rtcin(RTC_MONTH
)),leap
); sec
+= yd
; /* month */
t
= (bcd(rtcin(RTC_DAY
))-1) * 24*60*60; sec
+= t
; yd
+= t
; /* date */
day_week
= rtcin(RTC_WDAY
); /* day */
sec
+= bcd(rtcin(RTC_HRS
)) * 60*60; /* hour */
sec
+= bcd(rtcin(RTC_MIN
)) * 60; /* minutes */
sec
+= bcd(rtcin(RTC_SEC
)); /* seconds */
/* XXX off by one? Need to calculate DST on SUNDAY */
/* Perhaps we should have the RTC hold GMT time to save */
/* us the bother of converting. */
if ((yd
>= DAYST
) && ( yd
<= DAYEN
)) {
sec
+= tz
.tz_minuteswest
* 60;
* Initialze the time of day register, based on the time base which is, e.g.
outb(IO_RTC
,9); /* year */
printf("%d ",bcd(inb(IO_RTC
+1)));
outb(IO_RTC
,8); /* month */
printf("%d ",bcd(inb(IO_RTC
+1)));
outb(IO_RTC
,7); /* day */
printf("%d ",bcd(inb(IO_RTC
+1)));
outb(IO_RTC
,4); /* hour */
printf("%d ",bcd(inb(IO_RTC
+1)));
outb(IO_RTC
,2); /* minutes */
printf("%d ",bcd(inb(IO_RTC
+1)));
outb(IO_RTC
,0); /* seconds */
printf("%d\n",bcd(inb(IO_RTC
+1)));
* Wire clock interrupt in.
#define V(s) __CONCAT(V, s)
setidt(ICU_OFFSET
+0, &V(clk
), SDT_SYS386IGT
, SEL_KPL
);
* Delay for some number of milliseconds.