1 /* $NetBSD: rtclock.c,v 1.1.1.1 1996/05/05 12:17:03 oki Exp $ */ 2 3 /* 4 * Copyright 1993, 1994 Masaru Oki 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Masaru Oki. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 * X680x0 internal real time clock interface 35 * alarm is not supported. 36 */ 37 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 #include <sys/buf.h> 41 #include <sys/malloc.h> 42 #include <sys/proc.h> 43 #include <sys/reboot.h> 44 #include <sys/file.h> 45 46 #include <x68k/dev/rtclock_var.h> 47 #include <x68k/x68k/iodevice.h> 48 49 static u_long rtgettod __P((void)); 50 static int rtsettod __P((long)); 51 52 /* 53 * x68k/clock.c calls thru this vector, if it is set, to read 54 * the realtime clock. 55 */ 56 u_long (*gettod) __P((void)); 57 int (*settod)(); 58 59 static volatile union rtc *rtc_addr = 0; 60 61 int 62 rtclockinit() 63 { 64 rtc_addr = &IODEVbase->io_rtc; 65 66 if (rtgettod()) { 67 gettod = rtgettod; 68 settod = rtsettod; 69 } else { 70 return 0; 71 } 72 return 1; 73 } 74 75 static int month_days[12] = { 76 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 77 }; 78 79 static u_long 80 rtgettod() 81 { 82 register int i; 83 register u_long tmp; 84 int year, month, day, hour, min, sec; 85 86 /* hold clock */ 87 RTC_WRITE(rtc_addr, mode, RTC_HOLD_CLOCK); 88 89 /* read it */ 90 sec = RTC_REG(sec10) * 10 + RTC_REG(sec); 91 min = RTC_REG(min10) * 10 + RTC_REG(min); 92 hour = RTC_REG(hour10) * 10 + RTC_REG(hour); 93 day = RTC_REG(day10) * 10 + RTC_REG(day); 94 month = RTC_REG(mon10) * 10 + RTC_REG(mon); 95 year = RTC_REG(year10) * 10 + RTC_REG(year) + 1980; 96 97 /* let it run again.. */ 98 RTC_WRITE(rtc_addr, mode, RTC_FREE_CLOCK); 99 100 range_test(hour, 0, 23); 101 range_test(day, 1, 31); 102 range_test(month, 1, 12); 103 range_test(year, STARTOFTIME, 2000); 104 105 tmp = 0; 106 107 for (i = STARTOFTIME; i < year; i++) 108 tmp += days_in_year(i); 109 if (leapyear(year) && month > FEBRUARY) 110 tmp++; 111 112 for (i = 1; i < month; i++) 113 tmp += days_in_month(i); 114 115 tmp += (day - 1); 116 117 tmp = ((tmp * 24 + hour) * 60 + min + TIMEZONE) * 60 + sec; 118 119 return tmp; 120 } 121 122 static int 123 rtsettod (tim) 124 long tim; 125 { 126 /* 127 * I don't know if setting the clock is analogous 128 * to reading it, I don't have demo-code for setting. 129 * just give it a try.. 130 */ 131 register int i; 132 register long hms, day; 133 u_char sec1, sec2; 134 u_char min1, min2; 135 u_char hour1, hour2; 136 u_char day1, day2; 137 u_char mon1, mon2; 138 u_char year1, year2; 139 140 /* 141 * there seem to be problems with the bitfield addressing 142 * currently used.. 143 */ 144 if (!rtc_addr) 145 return 0; 146 147 tim -= (TIMEZONE * 60); 148 149 /* prepare values to be written to clock */ 150 day = tim / SECDAY; 151 hms = tim % SECDAY; 152 153 hour2 = hms / 3600; 154 hour1 = hour2 / 10; 155 hour2 %= 10; 156 157 min2 = (hms % 3600) / 60; 158 min1 = min2 / 10; 159 min2 %= 10; 160 161 sec2 = (hms % 3600) % 60; 162 sec1 = sec2 / 10; 163 sec2 %= 10; 164 165 /* Number of years in days */ 166 for (i = STARTOFTIME - 1980; day >= days_in_year(i); i++) 167 day -= days_in_year(i); 168 year1 = i / 10; 169 year2 = i % 10; 170 171 /* Number of months in days left */ 172 if (leapyear(i)) 173 days_in_month(FEBRUARY) = 29; 174 for (i = 1; day >= days_in_month(i); i++) 175 day -= days_in_month(i); 176 days_in_month(FEBRUARY) = 28; 177 178 mon1 = i / 10; 179 mon2 = i % 10; 180 181 /* Days are what is left over (+1) from all that. */ 182 day ++; 183 day1 = day / 10; 184 day2 = day % 10; 185 186 RTC_WRITE(rtc_addr, mode, RTC_HOLD_CLOCK); 187 RTC_WRITE(rtc_addr, sec10, sec1); 188 RTC_WRITE(rtc_addr, sec, sec2); 189 RTC_WRITE(rtc_addr, min10, min1); 190 RTC_WRITE(rtc_addr, min, min2); 191 RTC_WRITE(rtc_addr, hour10, hour1); 192 RTC_WRITE(rtc_addr, hour, hour2); 193 RTC_WRITE(rtc_addr, day10, day1); 194 RTC_WRITE(rtc_addr, day, day2); 195 RTC_WRITE(rtc_addr, mon10, mon1); 196 RTC_WRITE(rtc_addr, mon, mon2); 197 RTC_WRITE(rtc_addr, year10, year1); 198 RTC_WRITE(rtc_addr, year, year2); 199 RTC_WRITE(rtc_addr, mode, RTC_FREE_CLOCK); 200 201 return 1; 202 } 203