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