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 * 8 * Added stuff to read the cmos clock on startup - Don Ahn 9 * 10 * %sccs.include.386.c% 11 * 12 * @(#)clock.c 5.4 (Berkeley) 11/18/90 13 */ 14 15 /* 16 * Primitive clock interrupt routines. 17 */ 18 #include "param.h" 19 #include "time.h" 20 #include "kernel.h" 21 #include "machine/segments.h" 22 #include "machine/isa/icu.h" 23 #include "machine/isa/isa.h" 24 25 #define DAYST 119 26 #define DAYEN 303 27 28 startrtclock() { 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 36 /* convert 2 digit BCD number */ 37 bcd(i) 38 int i; 39 { 40 return ((i/16)*10 + (i%16)); 41 } 42 43 /* convert years to seconds (from 1970) */ 44 unsigned long 45 ytos(y) 46 int y; 47 { 48 int i; 49 unsigned long ret; 50 51 ret = 0; y = y - 70; 52 for(i=0;i<y;i++) { 53 if (i % 4) ret += 31536000; 54 else ret += 31622400; 55 } 56 return ret; 57 } 58 59 /* convert months to seconds */ 60 unsigned long 61 mtos(m,leap) 62 int m,leap; 63 { 64 int i; 65 unsigned long ret; 66 67 ret = 0; 68 for(i=1;i<m;i++) { 69 switch(i){ 70 case 1: case 3: case 5: case 7: case 8: case 10: case 12: 71 ret += 2678400; break; 72 case 4: case 6: case 9: case 11: 73 ret += 2592000; break; 74 case 2: 75 if (leap) ret += 2505600; 76 else ret += 2419200; 77 } 78 } 79 return ret; 80 } 81 82 83 /* 84 * Initialize the time of day register, based on the time base which is, e.g. 85 * from a filesystem. 86 */ 87 inittodr(base) 88 time_t base; 89 { 90 unsigned long sec; 91 int leap,day_week,t,yd; 92 93 sec = bcd(rtcin(9)); leap = !(sec % 4); sec += ytos(sec); /* year */ 94 yd = mtos(bcd(rtcin(8)),leap); sec += yd; /* month */ 95 t = (bcd(rtcin(7))-1) * 86400; sec += t; yd += t; /* date */ 96 day_week = rtcin(6); /* day */ 97 sec += bcd(rtcin(4)) * 3600; /* hour */ 98 sec += bcd(rtcin(2)) * 60; /* minutes */ 99 sec += bcd(rtcin(0)); /* seconds */ 100 101 /* XXX off by one? Need to calculate DST on SUNDAY */ 102 /* Perhaps we should have the RTC hold GMT time to save */ 103 /* us the bother of converting. */ 104 yd = yd / 86400; 105 if ((yd >= DAYST) && ( yd <= DAYEN)) { 106 sec -= 3600; 107 } 108 sec += tz.tz_minuteswest * 60; 109 110 time.tv_sec = sec; 111 } 112 113 #ifdef garbage 114 /* 115 * Initialze the time of day register, based on the time base which is, e.g. 116 * from a filesystem. 117 */ 118 test_inittodr(base) 119 time_t base; 120 { 121 122 outb(IO_RTC,9); /* year */ 123 printf("%d ",bcd(inb(IO_RTC+1))); 124 outb(IO_RTC,8); /* month */ 125 printf("%d ",bcd(inb(IO_RTC+1))); 126 outb(IO_RTC,7); /* day */ 127 printf("%d ",bcd(inb(IO_RTC+1))); 128 outb(IO_RTC,4); /* hour */ 129 printf("%d ",bcd(inb(IO_RTC+1))); 130 outb(IO_RTC,2); /* minutes */ 131 printf("%d ",bcd(inb(IO_RTC+1))); 132 outb(IO_RTC,0); /* seconds */ 133 printf("%d\n",bcd(inb(IO_RTC+1))); 134 135 time.tv_sec = base; 136 } 137 #endif 138 139 /* 140 * retreve a value from realtime clock 141 */ 142 u_char rtcin(n) { 143 u_char val; 144 145 outb(IO_RTC,n); 146 do val = inb(IO_RTC+1) ; while (val != inb(IO_RTC+1)); 147 return (val); 148 } 149 150 /* 151 * Restart the clock. 152 */ 153 resettodr() 154 { 155 } 156 157 #define V(s) V/**/s 158 extern V(clk)(); 159 enablertclock() { 160 INTREN(IRQ0); 161 setidt(ICU_OFFSET+0, &V(clk), SDT_SYS386IGT, SEL_KPL); 162 splnone(); 163 } 164