xref: /original-bsd/sys/i386/isa/clock.c (revision 95407d66)
1 /*-
2  * Copyright (c) 1990 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * William Jolitz.
7  *
8  * Added stuff to read the cmos clock on startup - Don Ahn
9  *
10  * %sccs.include.386.c%
11  *
12  *	@(#)clock.c	5.4 (Berkeley) 11/18/90
13  */
14 
15 /*
16  * Primitive clock interrupt routines.
17  */
18 #include "param.h"
19 #include "time.h"
20 #include "kernel.h"
21 #include "machine/segments.h"
22 #include "machine/isa/icu.h"
23 #include "machine/isa/isa.h"
24 
25 #define DAYST 119
26 #define DAYEN 303
27 
28 startrtclock() {
29 
30 	/* initialize 8253 clock */
31 	outb (IO_TIMER1+3, 0x36);
32 	outb (IO_TIMER1, 1193182/hz);
33 	outb (IO_TIMER1, (1193182/hz)/256);
34 }
35 
36 /* convert 2 digit BCD number */
37 bcd(i)
38 int i;
39 {
40 	return ((i/16)*10 + (i%16));
41 }
42 
43 /* convert years to seconds (from 1970) */
44 unsigned long
45 ytos(y)
46 int y;
47 {
48 	int i;
49 	unsigned long ret;
50 
51 	ret = 0; y = y - 70;
52 	for(i=0;i<y;i++) {
53 		if (i % 4) ret += 31536000;
54 		else ret += 31622400;
55 	}
56 	return ret;
57 }
58 
59 /* convert months to seconds */
60 unsigned long
61 mtos(m,leap)
62 int m,leap;
63 {
64 	int i;
65 	unsigned long ret;
66 
67 	ret = 0;
68 	for(i=1;i<m;i++) {
69 		switch(i){
70 		case 1: case 3: case 5: case 7: case 8: case 10: case 12:
71 			ret += 2678400; break;
72 		case 4: case 6: case 9: case 11:
73 			ret += 2592000; break;
74 		case 2:
75 			if (leap) ret += 2505600;
76 			else ret += 2419200;
77 		}
78 	}
79 	return ret;
80 }
81 
82 
83 /*
84  * Initialize the time of day register, based on the time base which is, e.g.
85  * from a filesystem.
86  */
87 inittodr(base)
88 	time_t base;
89 {
90 	unsigned long sec;
91 	int leap,day_week,t,yd;
92 
93 	sec = bcd(rtcin(9)); leap = !(sec % 4); sec += ytos(sec); /* year    */
94 	yd = mtos(bcd(rtcin(8)),leap); sec += yd;		/* month   */
95 	t = (bcd(rtcin(7))-1) * 86400; sec += t; yd += t;	/* date    */
96 	day_week = rtcin(6);					/* day     */
97 	sec += bcd(rtcin(4)) * 3600;				/* hour    */
98 	sec += bcd(rtcin(2)) * 60;				/* minutes */
99 	sec += bcd(rtcin(0));					/* seconds */
100 
101 	/* XXX off by one? Need to calculate DST on SUNDAY */
102 	/* Perhaps we should have the RTC hold GMT time to save */
103 	/* us the bother of converting. */
104 	yd = yd / 86400;
105 	if ((yd >= DAYST) && ( yd <= DAYEN)) {
106 		sec -= 3600;
107 	}
108 	sec += tz.tz_minuteswest * 60;
109 
110 	time.tv_sec = sec;
111 }
112 
113 #ifdef garbage
114 /*
115  * Initialze the time of day register, based on the time base which is, e.g.
116  * from a filesystem.
117  */
118 test_inittodr(base)
119 	time_t base;
120 {
121 
122 	outb(IO_RTC,9); /* year    */
123 	printf("%d ",bcd(inb(IO_RTC+1)));
124 	outb(IO_RTC,8); /* month   */
125 	printf("%d ",bcd(inb(IO_RTC+1)));
126 	outb(IO_RTC,7); /* day     */
127 	printf("%d ",bcd(inb(IO_RTC+1)));
128 	outb(IO_RTC,4); /* hour    */
129 	printf("%d ",bcd(inb(IO_RTC+1)));
130 	outb(IO_RTC,2); /* minutes */
131 	printf("%d ",bcd(inb(IO_RTC+1)));
132 	outb(IO_RTC,0); /* seconds */
133 	printf("%d\n",bcd(inb(IO_RTC+1)));
134 
135 	time.tv_sec = base;
136 }
137 #endif
138 
139 /*
140  * retreve a value from realtime clock
141  */
142 u_char rtcin(n) {
143 	u_char val;
144 
145 	outb(IO_RTC,n);
146 	do val = inb(IO_RTC+1) ; while (val != inb(IO_RTC+1));
147 	return (val);
148 }
149 
150 /*
151  * Restart the clock.
152  */
153 resettodr()
154 {
155 }
156 
157 #define V(s)	V/**/s
158 extern V(clk)();
159 enablertclock() {
160 	INTREN(IRQ0);
161 	setidt(ICU_OFFSET+0, &V(clk), SDT_SYS386IGT, SEL_KPL);
162 	splnone();
163 }
164