1 /* $NetBSD: rtclock.c,v 1.2 1997/01/15 01:29:25 perry 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 #include <sys/kernel.h> 46 47 #include <x68k/dev/rtclock_var.h> 48 #include <x68k/x68k/iodevice.h> 49 50 static u_long rtgettod __P((void)); 51 static int rtsettod __P((long)); 52 53 /* 54 * x68k/clock.c calls thru this vector, if it is set, to read 55 * the realtime clock. 56 */ 57 u_long (*gettod) __P((void)); 58 int (*settod)(); 59 60 static volatile union rtc *rtc_addr = 0; 61 62 int 63 rtclockinit() 64 { 65 rtc_addr = &IODEVbase->io_rtc; 66 67 if (rtgettod()) { 68 gettod = rtgettod; 69 settod = rtsettod; 70 } else { 71 return 0; 72 } 73 return 1; 74 } 75 76 static int month_days[12] = { 77 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 78 }; 79 80 static u_long 81 rtgettod() 82 { 83 register int i; 84 register u_long tmp; 85 int year, month, day, hour, min, sec; 86 87 /* hold clock */ 88 RTC_WRITE(rtc_addr, mode, RTC_HOLD_CLOCK); 89 90 /* read it */ 91 sec = RTC_REG(sec10) * 10 + RTC_REG(sec); 92 min = RTC_REG(min10) * 10 + RTC_REG(min); 93 hour = RTC_REG(hour10) * 10 + RTC_REG(hour); 94 day = RTC_REG(day10) * 10 + RTC_REG(day); 95 month = RTC_REG(mon10) * 10 + RTC_REG(mon); 96 year = RTC_REG(year10) * 10 + RTC_REG(year) + 1980; 97 98 /* let it run again.. */ 99 RTC_WRITE(rtc_addr, mode, RTC_FREE_CLOCK); 100 101 range_test(hour, 0, 23); 102 range_test(day, 1, 31); 103 range_test(month, 1, 12); 104 range_test(year, STARTOFTIME, 2000); 105 106 tmp = 0; 107 108 for (i = STARTOFTIME; i < year; i++) 109 tmp += days_in_year(i); 110 if (leapyear(year) && month > FEBRUARY) 111 tmp++; 112 113 for (i = 1; i < month; i++) 114 tmp += days_in_month(i); 115 116 tmp += (day - 1); 117 118 tmp = ((tmp * 24 + hour) * 60 + min + rtc_offset) * 60 + sec; 119 120 return tmp; 121 } 122 123 static int 124 rtsettod (tim) 125 long tim; 126 { 127 /* 128 * I don't know if setting the clock is analogous 129 * to reading it, I don't have demo-code for setting. 130 * just give it a try.. 131 */ 132 register int i; 133 register long hms, day; 134 u_char sec1, sec2; 135 u_char min1, min2; 136 u_char hour1, hour2; 137 u_char day1, day2; 138 u_char mon1, mon2; 139 u_char year1, year2; 140 141 /* 142 * there seem to be problems with the bitfield addressing 143 * currently used.. 144 */ 145 if (!rtc_addr) 146 return 0; 147 148 tim -= (rtc_offset * 60); 149 150 /* prepare values to be written to clock */ 151 day = tim / SECDAY; 152 hms = tim % SECDAY; 153 154 hour2 = hms / 3600; 155 hour1 = hour2 / 10; 156 hour2 %= 10; 157 158 min2 = (hms % 3600) / 60; 159 min1 = min2 / 10; 160 min2 %= 10; 161 162 sec2 = (hms % 3600) % 60; 163 sec1 = sec2 / 10; 164 sec2 %= 10; 165 166 /* Number of years in days */ 167 for (i = STARTOFTIME - 1980; day >= days_in_year(i); i++) 168 day -= days_in_year(i); 169 year1 = i / 10; 170 year2 = i % 10; 171 172 /* Number of months in days left */ 173 if (leapyear(i)) 174 days_in_month(FEBRUARY) = 29; 175 for (i = 1; day >= days_in_month(i); i++) 176 day -= days_in_month(i); 177 days_in_month(FEBRUARY) = 28; 178 179 mon1 = i / 10; 180 mon2 = i % 10; 181 182 /* Days are what is left over (+1) from all that. */ 183 day ++; 184 day1 = day / 10; 185 day2 = day % 10; 186 187 RTC_WRITE(rtc_addr, mode, RTC_HOLD_CLOCK); 188 RTC_WRITE(rtc_addr, sec10, sec1); 189 RTC_WRITE(rtc_addr, sec, sec2); 190 RTC_WRITE(rtc_addr, min10, min1); 191 RTC_WRITE(rtc_addr, min, min2); 192 RTC_WRITE(rtc_addr, hour10, hour1); 193 RTC_WRITE(rtc_addr, hour, hour2); 194 RTC_WRITE(rtc_addr, day10, day1); 195 RTC_WRITE(rtc_addr, day, day2); 196 RTC_WRITE(rtc_addr, mon10, mon1); 197 RTC_WRITE(rtc_addr, mon, mon2); 198 RTC_WRITE(rtc_addr, year10, year1); 199 RTC_WRITE(rtc_addr, year, year2); 200 RTC_WRITE(rtc_addr, mode, RTC_FREE_CLOCK); 201 202 return 1; 203 } 204