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 | |
d4a75cc0 | 6 | * William Jolitz and Don Ahn. |
f21663b5 | 7 | * |
d4a75cc0 | 8 | * %sccs.include.redist.c% |
cc60f649 | 9 | * |
187497c9 | 10 | * @(#)clock.c 7.2 (Berkeley) %G% |
f21663b5 WN |
11 | */ |
12 | ||
13 | /* | |
14 | * Primitive clock interrupt routines. | |
15 | */ | |
16 | #include "param.h" | |
17 | #include "time.h" | |
18 | #include "kernel.h" | |
4686adac | 19 | #include "machine/segments.h" |
8dfab1b8 WN |
20 | #include "i386/isa/icu.h" |
21 | #include "i386/isa/isa.h" | |
22 | #include "i386/isa/rtc.h" | |
f21663b5 | 23 | |
cc60f649 DA |
24 | #define DAYST 119 |
25 | #define DAYEN 303 | |
26 | ||
f21663b5 | 27 | startrtclock() { |
8dfab1b8 | 28 | int s; |
f21663b5 WN |
29 | |
30 | /* initialize 8253 clock */ | |
4686adac BJ |
31 | outb (IO_TIMER1+3, 0x36); |
32 | outb (IO_TIMER1, 1193182/hz); | |
33 | outb (IO_TIMER1, (1193182/hz)/256); | |
8dfab1b8 | 34 | |
8dfab1b8 WN |
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 | ||
8dfab1b8 WN |
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); | |
f21663b5 WN |
46 | } |
47 | ||
cc60f649 DA |
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++) { | |
8dfab1b8 WN |
65 | if (i % 4) ret += 365*24*60*60; |
66 | else ret += 366*24*60*60; | |
cc60f649 DA |
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: | |
8dfab1b8 | 83 | ret += 31*24*60*60; break; |
cc60f649 | 84 | case 4: case 6: case 9: case 11: |
8dfab1b8 | 85 | ret += 30*24*60*60; break; |
cc60f649 | 86 | case 2: |
8dfab1b8 WN |
87 | if (leap) ret += 29*24*60*60; |
88 | else ret += 28*24*60*60; | |
cc60f649 DA |
89 | } |
90 | } | |
91 | return ret; | |
92 | } | |
93 | ||
94 | ||
f21663b5 | 95 | /* |
5b97e489 | 96 | * Initialize the time of day register, based on the time base which is, e.g. |
f21663b5 WN |
97 | * from a filesystem. |
98 | */ | |
99 | inittodr(base) | |
100 | time_t base; | |
101 | { | |
cc60f649 DA |
102 | unsigned long sec; |
103 | int leap,day_week,t,yd; | |
187497c9 | 104 | int sa,s; |
8dfab1b8 WN |
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 | |
cc60f649 DA |
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. */ | |
8dfab1b8 | 128 | yd = yd / 24*60*60; |
cc60f649 | 129 | if ((yd >= DAYST) && ( yd <= DAYEN)) { |
8dfab1b8 | 130 | sec -= 60*60; |
cc60f649 | 131 | } |
8dfab1b8 | 132 | #endif |
cc60f649 DA |
133 | sec += tz.tz_minuteswest * 60; |
134 | ||
135 | time.tv_sec = sec; | |
136 | } | |
137 | ||
5b97e489 | 138 | #ifdef garbage |
cc60f649 DA |
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 | ||
5b97e489 BJ |
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))); | |
f21663b5 WN |
159 | |
160 | time.tv_sec = base; | |
161 | } | |
5b97e489 | 162 | #endif |
f21663b5 WN |
163 | |
164 | /* | |
165 | * Restart the clock. | |
166 | */ | |
167 | resettodr() | |
168 | { | |
169 | } | |
170 | ||
187497c9 WN |
171 | /* |
172 | * Wire clock interrupt in. | |
173 | */ | |
8dfab1b8 | 174 | #define V(s) __CONCAT(V, s) |
4686adac | 175 | extern V(clk)(); |
f21663b5 WN |
176 | enablertclock() { |
177 | INTREN(IRQ0); | |
4686adac | 178 | setidt(ICU_OFFSET+0, &V(clk), SDT_SYS386IGT, SEL_KPL); |
f21663b5 WN |
179 | splnone(); |
180 | } |