a2kbbc.c revision 1.2
11.2Skleink/* $NetBSD: a2kbbc.c,v 1.2 1997/07/22 23:12:13 kleink Exp $ */ 21.1Sis 31.1Sis/* 41.1Sis * Copyright (c) 1988 University of Utah. 51.1Sis * Copyright (c) 1982, 1990 The Regents of the University of California. 61.1Sis * All rights reserved. 71.1Sis * 81.1Sis * This code is derived from software contributed to Berkeley by 91.1Sis * the Systems Programming Group of the University of Utah Computer 101.1Sis * Science Department. 111.1Sis * 121.1Sis * Redistribution and use in source and binary forms, with or without 131.1Sis * modification, are permitted provided that the following conditions 141.1Sis * are met: 151.1Sis * 1. Redistributions of source code must retain the above copyright 161.1Sis * notice, this list of conditions and the following disclaimer. 171.1Sis * 2. Redistributions in binary form must reproduce the above copyright 181.1Sis * notice, this list of conditions and the following disclaimer in the 191.1Sis * documentation and/or other materials provided with the distribution. 201.1Sis * 3. All advertising materials mentioning features or use of this software 211.1Sis * must display the following acknowledgement: 221.1Sis * This product includes software developed by the University of 231.1Sis * California, Berkeley and its contributors. 241.1Sis * 4. Neither the name of the University nor the names of its contributors 251.1Sis * may be used to endorse or promote products derived from this software 261.1Sis * without specific prior written permission. 271.1Sis * 281.1Sis * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 291.1Sis * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 301.1Sis * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 311.1Sis * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 321.1Sis * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 331.1Sis * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 341.1Sis * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 351.1Sis * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 361.1Sis * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 371.1Sis * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 381.1Sis * SUCH DAMAGE. 391.1Sis * 401.1Sis * from: Utah $Hdr: clock.c 1.18 91/01/21$ 411.1Sis * 421.1Sis * @(#)clock.c 7.6 (Berkeley) 5/7/91 431.1Sis */ 441.1Sis 451.1Sis#include <sys/param.h> 461.1Sis#include <sys/kernel.h> 471.1Sis#include <sys/device.h> 481.1Sis#include <sys/systm.h> 491.1Sis#include <machine/psl.h> 501.1Sis#include <machine/cpu.h> 511.1Sis#include <amiga/amiga/device.h> 521.1Sis#include <amiga/amiga/custom.h> 531.1Sis#include <amiga/amiga/cia.h> 541.1Sis#include <amiga/dev/rtc.h> 551.1Sis#include <amiga/dev/zbusvar.h> 561.1Sis 571.1Sis#include <dev/clock_subr.h> 581.1Sis 591.1Sisint a2kbbc_match __P((struct device *, struct cfdata *, void *)); 601.1Sisvoid a2kbbc_attach __P((struct device *, struct device *, void *)); 611.1Sis 621.1Sisstruct cfattach a2kbbc_ca = { 631.1Sis sizeof(struct device), a2kbbc_match, a2kbbc_attach 641.1Sis}; 651.1Sis 661.1Sisstruct cfdriver a2kbbc_cd = { 671.1Sis NULL, "a2kbbc", DV_DULL, NULL, 0 681.1Sis}; 691.1Sis 701.1Sisvoid *a2kclockaddr; 711.1Sistime_t a2gettod __P((void)); 721.1Sisint a2settod __P((time_t)); 731.1Sis 741.1Sisint 751.1Sisa2kbbc_match(pdp, cfp, auxp) 761.1Sis struct device *pdp; 771.1Sis struct cfdata *cfp; 781.1Sis void *auxp; 791.1Sis{ 801.1Sis if (!matchname("a2kbbc", auxp)) 811.2Skleink return (0); 821.1Sis 831.2Skleink if (cfp->cf_unit != 0) 841.2Skleink return (0); /* only one of us please */ 851.1Sis 861.1Sis if (is_a1200() || is_a3000() || is_a4000() || is_draco()) 871.2Skleink return (0); 881.1Sis 891.1Sis a2kclockaddr = (void *)ztwomap(0xdc0000); 901.1Sis if (a2gettod() == 0) 911.2Skleink return (0); 921.1Sis 931.2Skleink return (1); 941.1Sis} 951.1Sis 961.1Sis/* 971.1Sis * Attach us to the rtc function pointers. 981.1Sis */ 991.1Sisvoid 1001.1Sisa2kbbc_attach(pdp, dp, auxp) 1011.1Sis struct device *pdp, *dp; 1021.1Sis void *auxp; 1031.1Sis{ 1041.1Sis printf("\n"); 1051.1Sis a2kclockaddr = (void *)ztwomap(0xdc0000); 1061.1Sis 1071.1Sis gettod = a2gettod; 1081.1Sis settod = a2settod; 1091.1Sis} 1101.1Sis 1111.1Sistime_t 1121.1Sisa2gettod() 1131.1Sis{ 1141.1Sis struct rtclock2000 *rt; 1151.1Sis struct clock_ymdhms dt; 1161.1Sis time_t secs; 1171.1Sis int i; 1181.1Sis 1191.1Sis rt = a2kclockaddr; 1201.1Sis 1211.1Sis /* 1221.1Sis * hold clock 1231.1Sis */ 1241.1Sis rt->control1 |= A2CONTROL1_HOLD; 1251.1Sis i = 0x1000; 1261.1Sis while (rt->control1 & A2CONTROL1_BUSY && i--) 1271.1Sis ; 1281.1Sis if (rt->control1 & A2CONTROL1_BUSY) 1291.1Sis return (0); /* Give up and say it's not there */ 1301.1Sis 1311.1Sis /* Copy the info. Careful about the order! */ 1321.1Sis dt.dt_sec = rt->second1 * 10 + rt->second2; 1331.1Sis dt.dt_min = rt->minute1 * 10 + rt->minute2; 1341.1Sis dt.dt_hour = (rt->hour1 & 3) * 10 + rt->hour2; 1351.1Sis dt.dt_day = rt->day1 * 10 + rt->day2; 1361.1Sis dt.dt_mon = rt->month1 * 10 + rt->month2; 1371.1Sis dt.dt_year = rt->year1 * 10 + rt->year2; 1381.1Sis dt.dt_wday = rt->weekday; 1391.1Sis 1401.1Sis /* 1411.1Sis * The oki clock chip has a register to put the clock into 1421.1Sis * 12/24h mode. 1431.1Sis * 1441.1Sis * clockmode | A2HOUR1_PM 1451.1Sis * 24h 12h | am = 0, pm = 1 1461.1Sis * --------------------------------- 1471.1Sis * 0 12 | 0 1481.1Sis * 1 1 | 0 1491.1Sis * .. .. | 0 1501.1Sis * 11 11 | 0 1511.1Sis * 12 12 | 1 1521.1Sis * 13 1 | 1 1531.1Sis * .. .. | 1 1541.1Sis * 23 11 | 1 1551.1Sis * 1561.1Sis */ 1571.1Sis 1581.1Sis if ((rt->control3 & A2CONTROL3_24HMODE) == 0) { 1591.1Sis if ((rt->hour1 & A2HOUR1_PM) == 0 && dt.dt_hour == 12) 1601.1Sis dt.dt_hour = 0; 1611.1Sis else if ((rt->hour1 & A2HOUR1_PM) && dt.dt_hour != 12) 1621.1Sis dt.dt_hour += 12; 1631.1Sis } 1641.1Sis 1651.1Sis /* 1661.1Sis * release the clock 1671.1Sis */ 1681.1Sis rt->control1 &= ~A2CONTROL1_HOLD; 1691.1Sis 1701.1Sis dt.dt_year += CLOCK_BASE_YEAR; 1711.1Sis 1721.1Sis if ((dt.dt_hour > 23) || 1731.1Sis (dt.dt_day > 31) || 1741.1Sis (dt.dt_mon > 12) || 1751.1Sis (dt.dt_year < STARTOFTIME) || (dt.dt_year > 2036)) 1761.1Sis return (0); 1771.1Sis 1781.1Sis secs = clock_ymdhms_to_secs(&dt); 1791.1Sis return (secs); 1801.1Sis} 1811.1Sis 1821.1Sisint 1831.1Sisa2settod(secs) 1841.1Sis time_t secs; 1851.1Sis{ 1861.1Sis struct rtclock2000 *rt; 1871.1Sis struct clock_ymdhms dt; 1881.1Sis int ampm, i; 1891.1Sis 1901.1Sis rt = a2kclockaddr; 1911.1Sis /* 1921.1Sis * there seem to be problems with the bitfield addressing 1931.1Sis * currently used.. 1941.1Sis */ 1951.1Sis if (! rt) 1961.1Sis return (0); 1971.1Sis 1981.1Sis clock_secs_to_ymdhms(secs, &dt); 1991.1Sis dt.dt_year -= CLOCK_BASE_YEAR; 2001.1Sis 2011.1Sis /* 2021.1Sis * hold clock 2031.1Sis */ 2041.1Sis rt->control1 |= A2CONTROL1_HOLD; 2051.1Sis i = 0x1000; 2061.1Sis while (rt->control1 & A2CONTROL1_BUSY && i--) 2071.1Sis ; 2081.1Sis if (rt->control1 & A2CONTROL1_BUSY) 2091.1Sis return (0); /* Give up and say it's not there */ 2101.1Sis 2111.1Sis ampm = 0; 2121.1Sis if ((rt->control3 & A2CONTROL3_24HMODE) == 0) { 2131.1Sis if (dt.dt_hour >= 12) { 2141.1Sis ampm = A2HOUR1_PM; 2151.1Sis if (dt.dt_hour != 12) 2161.1Sis dt.dt_hour -= 12; 2171.1Sis } else if (dt.dt_hour == 0) { 2181.1Sis dt.dt_hour = 12; 2191.1Sis } 2201.1Sis } 2211.1Sis rt->hour1 = (dt.dt_hour / 10) | ampm; 2221.1Sis rt->hour2 = dt.dt_hour % 10; 2231.1Sis rt->second1 = dt.dt_sec / 10; 2241.1Sis rt->second2 = dt.dt_sec % 10; 2251.1Sis rt->minute1 = dt.dt_min / 10; 2261.1Sis rt->minute2 = dt.dt_min % 10; 2271.1Sis rt->day1 = dt.dt_day / 10; 2281.1Sis rt->day2 = dt.dt_day % 10; 2291.1Sis rt->month1 = dt.dt_mon / 10; 2301.1Sis rt->month2 = dt.dt_mon % 10; 2311.1Sis rt->year1 = dt.dt_year / 10; 2321.1Sis rt->year2 = dt.dt_year % 10; 2331.1Sis rt->weekday = dt.dt_wday; 2341.1Sis 2351.1Sis /* 2361.1Sis * release the clock 2371.1Sis */ 2381.1Sis rt->control2 &= ~A2CONTROL1_HOLD; 2391.1Sis 2401.1Sis return (1); 2411.1Sis} 242