xref: /csrg-svn/sys/i386/isa/clock.c (revision 45532)
141052Swilliam /*-
241052Swilliam  * Copyright (c) 1990 The Regents of the University of California.
341052Swilliam  * All rights reserved.
441052Swilliam  *
541052Swilliam  * This code is derived from software contributed to Berkeley by
641052Swilliam  * William Jolitz.
741052Swilliam  *
843590Sdonahn  * Added stuff to read the cmos clock on startup - Don Ahn
943590Sdonahn  *
1041052Swilliam  * %sccs.include.386.c%
1141052Swilliam  *
12*45532Sbill  *	@(#)clock.c	5.3 (Berkeley) 11/08/90
1341052Swilliam  */
1441052Swilliam 
1541052Swilliam /*
1641052Swilliam  * Primitive clock interrupt routines.
1741052Swilliam  */
1841052Swilliam #include "param.h"
1941052Swilliam #include "time.h"
2041052Swilliam #include "kernel.h"
2141052Swilliam #include "icu.h"
22*45532Sbill #include "isa.h"
2341052Swilliam 
2443590Sdonahn #define DAYST 119
2543590Sdonahn #define DAYEN 303
2643590Sdonahn 
2741052Swilliam startrtclock() {
2841052Swilliam 
2941052Swilliam 	/* initialize 8253 clock */
30*45532Sbill 	outb (IO_TIMER0+3, 0x36);
31*45532Sbill 	outb (IO_TIMER0, 1193182/hz);
32*45532Sbill 	outb (IO_TIMER0, (1193182/hz)/256);
3341052Swilliam }
3441052Swilliam 
3543590Sdonahn /* convert 2 digit BCD number */
3643590Sdonahn bcd(i)
3743590Sdonahn int i;
3843590Sdonahn {
3943590Sdonahn 	return ((i/16)*10 + (i%16));
4043590Sdonahn }
4143590Sdonahn 
4243590Sdonahn /* convert years to seconds (from 1970) */
4343590Sdonahn unsigned long
4443590Sdonahn ytos(y)
4543590Sdonahn int y;
4643590Sdonahn {
4743590Sdonahn 	int i;
4843590Sdonahn 	unsigned long ret;
4943590Sdonahn 
5043590Sdonahn 	ret = 0; y = y - 70;
5143590Sdonahn 	for(i=0;i<y;i++) {
5243590Sdonahn 		if (i % 4) ret += 31536000;
5343590Sdonahn 		else ret += 31622400;
5443590Sdonahn 	}
5543590Sdonahn 	return ret;
5643590Sdonahn }
5743590Sdonahn 
5843590Sdonahn /* convert months to seconds */
5943590Sdonahn unsigned long
6043590Sdonahn mtos(m,leap)
6143590Sdonahn int m,leap;
6243590Sdonahn {
6343590Sdonahn 	int i;
6443590Sdonahn 	unsigned long ret;
6543590Sdonahn 
6643590Sdonahn 	ret = 0;
6743590Sdonahn 	for(i=1;i<m;i++) {
6843590Sdonahn 		switch(i){
6943590Sdonahn 		case 1: case 3: case 5: case 7: case 8: case 10: case 12:
7043590Sdonahn 			ret += 2678400; break;
7143590Sdonahn 		case 4: case 6: case 9: case 11:
7243590Sdonahn 			ret += 2592000; break;
7343590Sdonahn 		case 2:
7443590Sdonahn 			if (leap) ret += 2505600;
7543590Sdonahn 			else ret += 2419200;
7643590Sdonahn 		}
7743590Sdonahn 	}
7843590Sdonahn 	return ret;
7943590Sdonahn }
8043590Sdonahn 
8143590Sdonahn 
8241052Swilliam /*
83*45532Sbill  * Initialize the time of day register, based on the time base which is, e.g.
8441052Swilliam  * from a filesystem.
8541052Swilliam  */
8641052Swilliam inittodr(base)
8741052Swilliam 	time_t base;
8841052Swilliam {
8943590Sdonahn 	unsigned long sec;
9043590Sdonahn 	int leap,day_week,t,yd;
9141052Swilliam 
92*45532Sbill 	sec = bcd(rtcin(9)); leap = !(sec % 4); sec += ytos(sec); /* year    */
93*45532Sbill 	yd = mtos(bcd(rtcin(8)),leap); sec += yd;		/* month   */
94*45532Sbill 	t = (bcd(rtcin(7))-1) * 86400; sec += t; yd += t;	/* date    */
95*45532Sbill 	day_week = rtcin(6);					/* day     */
96*45532Sbill 	sec += bcd(rtcin(4)) * 3600;				/* hour    */
97*45532Sbill 	sec += bcd(rtcin(2)) * 60;				/* minutes */
98*45532Sbill 	sec += bcd(rtcin(0));					/* seconds */
9943590Sdonahn 
10043590Sdonahn 	/* XXX off by one? Need to calculate DST on SUNDAY */
10143590Sdonahn 	/* Perhaps we should have the RTC hold GMT time to save */
10243590Sdonahn 	/* us the bother of converting. */
10343590Sdonahn 	yd = yd / 86400;
10443590Sdonahn 	if ((yd >= DAYST) && ( yd <= DAYEN)) {
10543590Sdonahn 		sec -= 3600;
10643590Sdonahn 	}
10743590Sdonahn 	sec += tz.tz_minuteswest * 60;
10843590Sdonahn 
10943590Sdonahn 	time.tv_sec = sec;
11043590Sdonahn }
11143590Sdonahn 
112*45532Sbill #ifdef garbage
11343590Sdonahn /*
11443590Sdonahn  * Initialze the time of day register, based on the time base which is, e.g.
11543590Sdonahn  * from a filesystem.
11643590Sdonahn  */
11743590Sdonahn test_inittodr(base)
11843590Sdonahn 	time_t base;
11943590Sdonahn {
12043590Sdonahn 
121*45532Sbill 	outb(IO_RTC,9); /* year    */
122*45532Sbill 	printf("%d ",bcd(inb(IO_RTC+1)));
123*45532Sbill 	outb(IO_RTC,8); /* month   */
124*45532Sbill 	printf("%d ",bcd(inb(IO_RTC+1)));
125*45532Sbill 	outb(IO_RTC,7); /* day     */
126*45532Sbill 	printf("%d ",bcd(inb(IO_RTC+1)));
127*45532Sbill 	outb(IO_RTC,4); /* hour    */
128*45532Sbill 	printf("%d ",bcd(inb(IO_RTC+1)));
129*45532Sbill 	outb(IO_RTC,2); /* minutes */
130*45532Sbill 	printf("%d ",bcd(inb(IO_RTC+1)));
131*45532Sbill 	outb(IO_RTC,0); /* seconds */
132*45532Sbill 	printf("%d\n",bcd(inb(IO_RTC+1)));
13343590Sdonahn 
13441052Swilliam 	time.tv_sec = base;
13541052Swilliam }
136*45532Sbill #endif
13741052Swilliam 
138*45532Sbill /*
139*45532Sbill  * retreve a value from realtime clock
140*45532Sbill  */
141*45532Sbill u_char rtcin(n) {
142*45532Sbill 	u_char val;
14343590Sdonahn 
144*45532Sbill 	outb(IO_RTC,n);
145*45532Sbill 	do val = inb(IO_RTC+1) ; while (val != inb(IO_RTC+1));
146*45532Sbill 	return (val);
147*45532Sbill }
148*45532Sbill 
14941052Swilliam /*
15041052Swilliam  * Restart the clock.
15141052Swilliam  */
15241052Swilliam resettodr()
15341052Swilliam {
15441052Swilliam }
15541052Swilliam 
15641052Swilliam enablertclock() {
15741052Swilliam 	INTREN(IRQ0);
15841052Swilliam 	splnone();
15941052Swilliam }
160