141052Swilliam /*- 241052Swilliam * Copyright (c) 1990 The Regents of the University of California. 341052Swilliam * All rights reserved. 441052Swilliam * 541052Swilliam * This code is derived from software contributed to Berkeley by 641052Swilliam * William Jolitz. 741052Swilliam * 843590Sdonahn * Added stuff to read the cmos clock on startup - Don Ahn 943590Sdonahn * 1041052Swilliam * %sccs.include.386.c% 1141052Swilliam * 12*45532Sbill * @(#)clock.c 5.3 (Berkeley) 11/08/90 1341052Swilliam */ 1441052Swilliam 1541052Swilliam /* 1641052Swilliam * Primitive clock interrupt routines. 1741052Swilliam */ 1841052Swilliam #include "param.h" 1941052Swilliam #include "time.h" 2041052Swilliam #include "kernel.h" 2141052Swilliam #include "icu.h" 22*45532Sbill #include "isa.h" 2341052Swilliam 2443590Sdonahn #define DAYST 119 2543590Sdonahn #define DAYEN 303 2643590Sdonahn 2741052Swilliam startrtclock() { 2841052Swilliam 2941052Swilliam /* initialize 8253 clock */ 30*45532Sbill outb (IO_TIMER0+3, 0x36); 31*45532Sbill outb (IO_TIMER0, 1193182/hz); 32*45532Sbill outb (IO_TIMER0, (1193182/hz)/256); 3341052Swilliam } 3441052Swilliam 3543590Sdonahn /* convert 2 digit BCD number */ 3643590Sdonahn bcd(i) 3743590Sdonahn int i; 3843590Sdonahn { 3943590Sdonahn return ((i/16)*10 + (i%16)); 4043590Sdonahn } 4143590Sdonahn 4243590Sdonahn /* convert years to seconds (from 1970) */ 4343590Sdonahn unsigned long 4443590Sdonahn ytos(y) 4543590Sdonahn int y; 4643590Sdonahn { 4743590Sdonahn int i; 4843590Sdonahn unsigned long ret; 4943590Sdonahn 5043590Sdonahn ret = 0; y = y - 70; 5143590Sdonahn for(i=0;i<y;i++) { 5243590Sdonahn if (i % 4) ret += 31536000; 5343590Sdonahn else ret += 31622400; 5443590Sdonahn } 5543590Sdonahn return ret; 5643590Sdonahn } 5743590Sdonahn 5843590Sdonahn /* convert months to seconds */ 5943590Sdonahn unsigned long 6043590Sdonahn mtos(m,leap) 6143590Sdonahn int m,leap; 6243590Sdonahn { 6343590Sdonahn int i; 6443590Sdonahn unsigned long ret; 6543590Sdonahn 6643590Sdonahn ret = 0; 6743590Sdonahn for(i=1;i<m;i++) { 6843590Sdonahn switch(i){ 6943590Sdonahn case 1: case 3: case 5: case 7: case 8: case 10: case 12: 7043590Sdonahn ret += 2678400; break; 7143590Sdonahn case 4: case 6: case 9: case 11: 7243590Sdonahn ret += 2592000; break; 7343590Sdonahn case 2: 7443590Sdonahn if (leap) ret += 2505600; 7543590Sdonahn else ret += 2419200; 7643590Sdonahn } 7743590Sdonahn } 7843590Sdonahn return ret; 7943590Sdonahn } 8043590Sdonahn 8143590Sdonahn 8241052Swilliam /* 83*45532Sbill * Initialize the time of day register, based on the time base which is, e.g. 8441052Swilliam * from a filesystem. 8541052Swilliam */ 8641052Swilliam inittodr(base) 8741052Swilliam time_t base; 8841052Swilliam { 8943590Sdonahn unsigned long sec; 9043590Sdonahn int leap,day_week,t,yd; 9141052Swilliam 92*45532Sbill sec = bcd(rtcin(9)); leap = !(sec % 4); sec += ytos(sec); /* year */ 93*45532Sbill yd = mtos(bcd(rtcin(8)),leap); sec += yd; /* month */ 94*45532Sbill t = (bcd(rtcin(7))-1) * 86400; sec += t; yd += t; /* date */ 95*45532Sbill day_week = rtcin(6); /* day */ 96*45532Sbill sec += bcd(rtcin(4)) * 3600; /* hour */ 97*45532Sbill sec += bcd(rtcin(2)) * 60; /* minutes */ 98*45532Sbill sec += bcd(rtcin(0)); /* seconds */ 9943590Sdonahn 10043590Sdonahn /* XXX off by one? Need to calculate DST on SUNDAY */ 10143590Sdonahn /* Perhaps we should have the RTC hold GMT time to save */ 10243590Sdonahn /* us the bother of converting. */ 10343590Sdonahn yd = yd / 86400; 10443590Sdonahn if ((yd >= DAYST) && ( yd <= DAYEN)) { 10543590Sdonahn sec -= 3600; 10643590Sdonahn } 10743590Sdonahn sec += tz.tz_minuteswest * 60; 10843590Sdonahn 10943590Sdonahn time.tv_sec = sec; 11043590Sdonahn } 11143590Sdonahn 112*45532Sbill #ifdef garbage 11343590Sdonahn /* 11443590Sdonahn * Initialze the time of day register, based on the time base which is, e.g. 11543590Sdonahn * from a filesystem. 11643590Sdonahn */ 11743590Sdonahn test_inittodr(base) 11843590Sdonahn time_t base; 11943590Sdonahn { 12043590Sdonahn 121*45532Sbill outb(IO_RTC,9); /* year */ 122*45532Sbill printf("%d ",bcd(inb(IO_RTC+1))); 123*45532Sbill outb(IO_RTC,8); /* month */ 124*45532Sbill printf("%d ",bcd(inb(IO_RTC+1))); 125*45532Sbill outb(IO_RTC,7); /* day */ 126*45532Sbill printf("%d ",bcd(inb(IO_RTC+1))); 127*45532Sbill outb(IO_RTC,4); /* hour */ 128*45532Sbill printf("%d ",bcd(inb(IO_RTC+1))); 129*45532Sbill outb(IO_RTC,2); /* minutes */ 130*45532Sbill printf("%d ",bcd(inb(IO_RTC+1))); 131*45532Sbill outb(IO_RTC,0); /* seconds */ 132*45532Sbill printf("%d\n",bcd(inb(IO_RTC+1))); 13343590Sdonahn 13441052Swilliam time.tv_sec = base; 13541052Swilliam } 136*45532Sbill #endif 13741052Swilliam 138*45532Sbill /* 139*45532Sbill * retreve a value from realtime clock 140*45532Sbill */ 141*45532Sbill u_char rtcin(n) { 142*45532Sbill u_char val; 14343590Sdonahn 144*45532Sbill outb(IO_RTC,n); 145*45532Sbill do val = inb(IO_RTC+1) ; while (val != inb(IO_RTC+1)); 146*45532Sbill return (val); 147*45532Sbill } 148*45532Sbill 14941052Swilliam /* 15041052Swilliam * Restart the clock. 15141052Swilliam */ 15241052Swilliam resettodr() 15341052Swilliam { 15441052Swilliam } 15541052Swilliam 15641052Swilliam enablertclock() { 15741052Swilliam INTREN(IRQ0); 15841052Swilliam splnone(); 15941052Swilliam } 160