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