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