date and time created 91/05/09 21:40:17 by william
[unix-history] / usr / src / sys / i386 / isa / clock.c
CommitLineData
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 29startrtclock() {
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);
45printf("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
68reprimefailsafe(){
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 */
78bcd(i)
79int i;
80{
81 return ((i/16)*10 + (i%16));
82}
83
84/* convert years to seconds (from 1970) */
85unsigned long
86ytos(y)
87int 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 */
101unsigned long
102mtos(m,leap)
103int 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 */
128inittodr(base)
129 time_t base;
130{
cc60f649
DA
131 unsigned long sec;
132 int leap,day_week,t,yd;
8dfab1b8
WN
133int 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 */
172test_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 */
197u_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 */
217resettodr()
218{
219}
220
8dfab1b8 221#define V(s) __CONCAT(V, s)
4686adac 222extern V(clk)();
f21663b5
WN
223enablertclock() {
224 INTREN(IRQ0);
4686adac 225 setidt(ICU_OFFSET+0, &V(clk), SDT_SYS386IGT, SEL_KPL);
f21663b5
WN
226 splnone();
227}