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