xref: /csrg-svn/sys/i386/isa/clock.c (revision 49617)
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 and Don Ahn.
7  *
8  * %sccs.include.redist.c%
9  *
10  *	@(#)clock.c	7.1 (Berkeley) 05/09/91
11  */
12 
13 /*
14  * Primitive clock interrupt routines.
15  */
16 #include "param.h"
17 #include "time.h"
18 #include "kernel.h"
19 #include "machine/segments.h"
20 #include "i386/isa/icu.h"
21 #include "i386/isa/isa.h"
22 #include "i386/isa/rtc.h"
23 
24 #define DAYST 119
25 #define DAYEN 303
26 
27 startrtclock() {
28 	int s;
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 #ifdef notdef
36 	/* NMI fail safe 1/4 sec  */
37 	/* initialize 8253 clock */
38 	outb(0x461,0);
39 	outb (IO_TIMER2+3, 0x30);
40 	outb (IO_TIMER2, 298300*40);
41 	outb (IO_TIMER2, (298300*40)/256);
42 	outb(0x461,4);
43 printf("armed ");
44 #endif
45 
46 	/* initialize brain-dead battery powered clock */
47 	outb (IO_RTC, RTC_STATUSA);
48 	outb (IO_RTC+1, 0x26);
49 	outb (IO_RTC, RTC_STATUSB);
50 	outb (IO_RTC+1, 2);
51 
52 	/*outb (IO_RTC, RTC_STATUSD);
53 	if((inb(IO_RTC+1) & 0x80) == 0)
54 		printf("rtc lost power\n");
55 	outb (IO_RTC, RTC_STATUSD);
56 	outb (IO_RTC+1, 0x80);*/
57 
58 	outb (IO_RTC, RTC_DIAG);
59 	if (s = inb (IO_RTC+1))
60 		printf("RTC BIOS diagnostic error %b\n", s, RTCDG_BITS);
61 	outb (IO_RTC, RTC_DIAG);
62 	outb (IO_RTC+1, 0);
63 }
64 
65 #ifdef ARGOx
66 reprimefailsafe(){
67 	outb(0x461,0);
68 	outb (IO_TIMER2+3, 0x30);
69 	outb (IO_TIMER2, 298300*40);
70 	outb (IO_TIMER2, (298300*40)/256);
71 	outb(0x461,4);
72 }
73 #endif
74 
75 /* convert 2 digit BCD number */
76 bcd(i)
77 int i;
78 {
79 	return ((i/16)*10 + (i%16));
80 }
81 
82 /* convert years to seconds (from 1970) */
83 unsigned long
84 ytos(y)
85 int y;
86 {
87 	int i;
88 	unsigned long ret;
89 
90 	ret = 0; y = y - 70;
91 	for(i=0;i<y;i++) {
92 		if (i % 4) ret += 365*24*60*60;
93 		else ret += 366*24*60*60;
94 	}
95 	return ret;
96 }
97 
98 /* convert months to seconds */
99 unsigned long
100 mtos(m,leap)
101 int m,leap;
102 {
103 	int i;
104 	unsigned long ret;
105 
106 	ret = 0;
107 	for(i=1;i<m;i++) {
108 		switch(i){
109 		case 1: case 3: case 5: case 7: case 8: case 10: case 12:
110 			ret += 31*24*60*60; break;
111 		case 4: case 6: case 9: case 11:
112 			ret += 30*24*60*60; break;
113 		case 2:
114 			if (leap) ret += 29*24*60*60;
115 			else ret += 28*24*60*60;
116 		}
117 	}
118 	return ret;
119 }
120 
121 
122 /*
123  * Initialize the time of day register, based on the time base which is, e.g.
124  * from a filesystem.
125  */
126 inittodr(base)
127 	time_t base;
128 {
129 	unsigned long sec;
130 	int leap,day_week,t,yd;
131 int sa,s;
132 
133 	/* do we have a realtime clock present? (otherwise we loop below) */
134 	sa = rtcin(RTC_STATUSA);
135 	if (sa == 0xff || sa == 0) return;
136 
137 	/* ready for a read? */
138 	while ((sa&RTCSA_TUP) == RTCSA_TUP)
139 		sa = rtcin(RTC_STATUSA);
140 
141 	sec = bcd(rtcin(RTC_YEAR));
142 	leap = !(sec % 4); sec += ytos(sec); /* year    */
143 	yd = mtos(bcd(rtcin(RTC_MONTH)),leap); sec += yd;	/* month   */
144 	t = (bcd(rtcin(RTC_DAY))-1) * 24*60*60; sec += t; yd += t; /* date    */
145 	day_week = rtcin(RTC_WDAY);				/* day     */
146 	sec += bcd(rtcin(RTC_HRS)) * 60*60;			/* hour    */
147 	sec += bcd(rtcin(RTC_MIN)) * 60;			/* minutes */
148 	sec += bcd(rtcin(RTC_SEC));				/* seconds */
149 	sec -= 24*60*60; /* XXX why ??? */
150 
151 #ifdef notdef
152 	/* XXX off by one? Need to calculate DST on SUNDAY */
153 	/* Perhaps we should have the RTC hold GMT time to save */
154 	/* us the bother of converting. */
155 	yd = yd / 24*60*60;
156 	if ((yd >= DAYST) && ( yd <= DAYEN)) {
157 		sec -= 60*60;
158 	}
159 #endif
160 	sec += tz.tz_minuteswest * 60;
161 
162 	time.tv_sec = sec;
163 }
164 
165 #ifdef garbage
166 /*
167  * Initialze the time of day register, based on the time base which is, e.g.
168  * from a filesystem.
169  */
170 test_inittodr(base)
171 	time_t base;
172 {
173 
174 	outb(IO_RTC,9); /* year    */
175 	printf("%d ",bcd(inb(IO_RTC+1)));
176 	outb(IO_RTC,8); /* month   */
177 	printf("%d ",bcd(inb(IO_RTC+1)));
178 	outb(IO_RTC,7); /* day     */
179 	printf("%d ",bcd(inb(IO_RTC+1)));
180 	outb(IO_RTC,4); /* hour    */
181 	printf("%d ",bcd(inb(IO_RTC+1)));
182 	outb(IO_RTC,2); /* minutes */
183 	printf("%d ",bcd(inb(IO_RTC+1)));
184 	outb(IO_RTC,0); /* seconds */
185 	printf("%d\n",bcd(inb(IO_RTC+1)));
186 
187 	time.tv_sec = base;
188 }
189 #endif
190 
191 #ifdef notdef
192 /*
193  * retreve a value from realtime clock
194  */
195 u_char rtcin(n) {
196 	u_char val;
197 
198 	/*outb(IO_RTC, RTC_STATUSA);
199 	do val = inb(IO_RTC+1) ; while (val&0x80);*/
200 
201 	outb(IO_RTC,n);
202 	DELAY(100);
203 	if (inb(IO_RTC) != n) {
204 		outb(IO_RTC,n);
205 		DELAY(100);
206 	}
207 	do val = inb(IO_RTC+1) ; while (val != inb(IO_RTC+1));
208 	return (val);
209 }
210 #endif
211 
212 /*
213  * Restart the clock.
214  */
215 resettodr()
216 {
217 }
218 
219 #define V(s)	__CONCAT(V, s)
220 extern V(clk)();
221 enablertclock() {
222 	INTREN(IRQ0);
223 	setidt(ICU_OFFSET+0, &V(clk), SDT_SYS386IGT, SEL_KPL);
224 	splnone();
225 }
226