xref: /original-bsd/sys/i386/isa/clock.c (revision a95f03a8)
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.3 (Berkeley) 10/11/92
11  */
12 
13 /*
14  * Primitive clock interrupt routines.
15  */
16 #include <sys/param.h>
17 #include <sys/time.h>
18 #include <sys/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 	/* initialize brain-dead battery powered clock */
36 	outb (IO_RTC, RTC_STATUSA);
37 	outb (IO_RTC+1, 0x26);
38 	outb (IO_RTC, RTC_STATUSB);
39 	outb (IO_RTC+1, 2);
40 
41 	outb (IO_RTC, RTC_DIAG);
42 	if (s = inb (IO_RTC+1))
43 		printf("RTC BIOS diagnostic error %b\n", s, RTCDG_BITS);
44 	outb (IO_RTC, RTC_DIAG);
45 	outb (IO_RTC+1, 0);
46 }
47 
48 /* convert 2 digit BCD number */
49 bcd(i)
50 int i;
51 {
52 	return ((i/16)*10 + (i%16));
53 }
54 
55 /* convert years to seconds (from 1970) */
56 unsigned long
57 ytos(y)
58 int y;
59 {
60 	int i;
61 	unsigned long ret;
62 
63 	ret = 0; y = y - 70;
64 	for(i=0;i<y;i++) {
65 		if (i % 4) ret += 365*24*60*60;
66 		else ret += 366*24*60*60;
67 	}
68 	return ret;
69 }
70 
71 /* convert months to seconds */
72 unsigned long
73 mtos(m,leap)
74 int m,leap;
75 {
76 	int i;
77 	unsigned long ret;
78 
79 	ret = 0;
80 	for(i=1;i<m;i++) {
81 		switch(i){
82 		case 1: case 3: case 5: case 7: case 8: case 10: case 12:
83 			ret += 31*24*60*60; break;
84 		case 4: case 6: case 9: case 11:
85 			ret += 30*24*60*60; break;
86 		case 2:
87 			if (leap) ret += 29*24*60*60;
88 			else ret += 28*24*60*60;
89 		}
90 	}
91 	return ret;
92 }
93 
94 
95 /*
96  * Initialize the time of day register, based on the time base which is, e.g.
97  * from a filesystem.
98  */
99 inittodr(base)
100 	time_t base;
101 {
102 	unsigned long sec;
103 	int leap,day_week,t,yd;
104 	int sa,s;
105 
106 	/* do we have a realtime clock present? (otherwise we loop below) */
107 	sa = rtcin(RTC_STATUSA);
108 	if (sa == 0xff || sa == 0) return;
109 
110 	/* ready for a read? */
111 	while ((sa&RTCSA_TUP) == RTCSA_TUP)
112 		sa = rtcin(RTC_STATUSA);
113 
114 	sec = bcd(rtcin(RTC_YEAR));
115 	leap = !(sec % 4); sec += ytos(sec); /* year    */
116 	yd = mtos(bcd(rtcin(RTC_MONTH)),leap); sec += yd;	/* month   */
117 	t = (bcd(rtcin(RTC_DAY))-1) * 24*60*60; sec += t; yd += t; /* date    */
118 	day_week = rtcin(RTC_WDAY);				/* day     */
119 	sec += bcd(rtcin(RTC_HRS)) * 60*60;			/* hour    */
120 	sec += bcd(rtcin(RTC_MIN)) * 60;			/* minutes */
121 	sec += bcd(rtcin(RTC_SEC));				/* seconds */
122 	sec -= 24*60*60; /* XXX why ??? */
123 
124 #ifdef notdef
125 	/* XXX off by one? Need to calculate DST on SUNDAY */
126 	/* Perhaps we should have the RTC hold GMT time to save */
127 	/* us the bother of converting. */
128 	yd = yd / 24*60*60;
129 	if ((yd >= DAYST) && ( yd <= DAYEN)) {
130 		sec -= 60*60;
131 	}
132 #endif
133 	sec += tz.tz_minuteswest * 60;
134 
135 	time.tv_sec = sec;
136 }
137 
138 #ifdef garbage
139 /*
140  * Initialze the time of day register, based on the time base which is, e.g.
141  * from a filesystem.
142  */
143 test_inittodr(base)
144 	time_t base;
145 {
146 
147 	outb(IO_RTC,9); /* year    */
148 	printf("%d ",bcd(inb(IO_RTC+1)));
149 	outb(IO_RTC,8); /* month   */
150 	printf("%d ",bcd(inb(IO_RTC+1)));
151 	outb(IO_RTC,7); /* day     */
152 	printf("%d ",bcd(inb(IO_RTC+1)));
153 	outb(IO_RTC,4); /* hour    */
154 	printf("%d ",bcd(inb(IO_RTC+1)));
155 	outb(IO_RTC,2); /* minutes */
156 	printf("%d ",bcd(inb(IO_RTC+1)));
157 	outb(IO_RTC,0); /* seconds */
158 	printf("%d\n",bcd(inb(IO_RTC+1)));
159 
160 	time.tv_sec = base;
161 }
162 #endif
163 
164 /*
165  * Restart the clock.
166  */
167 resettodr()
168 {
169 }
170 
171 /*
172  * Wire clock interrupt in.
173  */
174 #define V(s)	__CONCAT(V, s)
175 extern V(clk)();
176 enablertclock() {
177 	INTREN(IRQ0);
178 	setidt(ICU_OFFSET+0, &V(clk), SDT_SYS386IGT, SEL_KPL);
179 	splnone();
180 }
181