diff options
author | Dale Rahn <drahn@cvs.openbsd.org> | 2004-02-01 05:09:50 +0000 |
---|---|---|
committer | Dale Rahn <drahn@cvs.openbsd.org> | 2004-02-01 05:09:50 +0000 |
commit | bad76f195320d5f8fe71dd2cdd09b7e6448ae62f (patch) | |
tree | c56802223bbfc0fdd07d88de003f59f99c2b72cb /sys/arch/arm/footbridge/todclock.c | |
parent | 208090c7a2e143dac12badc41a13eb79a817928e (diff) |
Arm port, NetBSD codebase stripped down, 32bit only support.
Diffstat (limited to 'sys/arch/arm/footbridge/todclock.c')
-rw-r--r-- | sys/arch/arm/footbridge/todclock.c | 348 |
1 files changed, 348 insertions, 0 deletions
diff --git a/sys/arch/arm/footbridge/todclock.c b/sys/arch/arm/footbridge/todclock.c new file mode 100644 index 00000000000..642724d749c --- /dev/null +++ b/sys/arch/arm/footbridge/todclock.c @@ -0,0 +1,348 @@ +/* $OpenBSD: todclock.c,v 1.1 2004/02/01 05:09:49 drahn Exp $ */ +/* $NetBSD: todclock.c,v 1.4 2002/10/02 05:02:30 thorpej Exp $ */ + +/* + * Copyright (c) 1994-1997 Mark Brinicombe. + * Copyright (c) 1994 Brini. + * All rights reserved. + * + * This code is derived from software written for Brini by Mark Brinicombe + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mark Brinicombe. + * 4. The name of the company nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * RiscBSD kernel project + * + * clock.c + * + * Timer related machine specific code + * + * Created : 29/09/94 + */ + +/* Include header files */ + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/time.h> +#include <sys/device.h> + +#include <machine/rtc.h> +#include <arm/footbridge/todclockvar.h> + +#include "todclock.h" + +#if NTODCLOCK > 1 +#error "Can only had 1 todclock device" +#endif + +static int yeartoday __P((int)); + +/* + * softc structure for the todclock device + */ + +struct todclock_softc { + struct device sc_dev; /* device node */ + void *sc_rtc_arg; /* arg to read/write */ + int (*sc_rtc_write) __P((void *, rtc_t *)); /* rtc write function */ + int (*sc_rtc_read) __P((void *, rtc_t *)); /* rtc read function */ +}; + +/* prototypes for functions */ + +static void todclockattach (struct device *parent, struct device *self, + void *aux); +static int todclockmatch (struct device *parent, void *cf, void *aux); + +/* + * We need to remember our softc for functions like inittodr() + * and resettodr() + * since we only ever have one time-of-day device we can just store + * the direct pointer to softc. + */ + +static struct todclock_softc *todclock_sc = NULL; + +/* driver and attach structures */ + +struct cfattach todclock_ca = { + sizeof(struct todclock_softc), todclockmatch, todclockattach +}; + +struct cfdriver todclock_cd = { + NULL, "todclock", DV_DULL +}; + + +/* + * int todclockmatch(struct device *parent, struct cfdata *cf, void *aux) + * + * todclock device probe function. + * just validate the attach args + */ + +int +todclockmatch(parent, cf, aux) + struct device *parent; + void *cf; + void *aux; +{ + struct todclock_attach_args *ta = aux; + + if (todclock_sc != NULL) + return(0); + if (strcmp(ta->ta_name, "todclock") != 0) + return(0); + + if (ta->ta_flags & TODCLOCK_FLAG_FAKE) + return(1); + return(2); +} + +/* + * void todclockattach(struct device *parent, struct device *self, void *aux) + * + * todclock device attach function. + * Initialise the softc structure and do a search for children + */ + +void +todclockattach(parent, self, aux) + struct device *parent; + struct device *self; + void *aux; +{ + struct todclock_softc *sc = (void *)self; + struct todclock_attach_args *ta = aux; + + /* set up our softc */ + todclock_sc = sc; + todclock_sc->sc_rtc_arg = ta->ta_rtc_arg; + todclock_sc->sc_rtc_write = ta->ta_rtc_write; + todclock_sc->sc_rtc_read = ta->ta_rtc_read; + + printf("\n"); + + /* + * Initialise the time of day register. + * This is normally left to the filing system to do but not all + * filing systems call it e.g. cd9660 + */ + + inittodr(0); +} + +static __inline int +yeartoday(year) + int year; +{ + return((year % 4) ? 365 : 366); +} + + +static int month[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; +static int timeset = 0; + +#define SECPERDAY (24*60*60) +#define SECPERNYEAR (365*SECPERDAY) +#define SECPER4YEARS (4*SECPERNYEAR+SECPERDAY) +#define EPOCHYEAR 1970 + +/* + * Globally visable functions + * + * These functions are used from other parts of the kernel. + * These functions use the functions defined in the tod_sc + * to actually read and write the rtc. + * + * The first todclock to be attached will be used for handling + * the time of day. + */ + +/* + * Write back the time of day to the rtc + */ + +void +resettodr() +{ + int s; + time_t year, mon, day, hour, min, sec; + rtc_t rtc; + + /* Have we set the system time in inittodr() */ + if (!timeset) + return; + + /* We need a todclock device and should always have one */ + if (!todclock_sc) + return; + + /* Abort early if there is not actually an RTC write routine */ + if (todclock_sc->sc_rtc_write == NULL) + return; + + sec = time.tv_sec; + sec -= tz.tz_minuteswest * 60; + if (tz.tz_dsttime) + time.tv_sec += 3600; + year = (sec / SECPER4YEARS) * 4; + sec %= SECPER4YEARS; + + /* year now hold the number of years rounded down 4 */ + + while (sec > (yeartoday(EPOCHYEAR+year) * SECPERDAY)) { + sec -= yeartoday(EPOCHYEAR+year)*SECPERDAY; + year++; + } + + /* year is now a correct offset from the EPOCHYEAR */ + + year+=EPOCHYEAR; + mon=0; + if (yeartoday(year) == 366) + month[1]=29; + else + month[1]=28; + while (sec >= month[mon]*SECPERDAY) { + sec -= month[mon]*SECPERDAY; + mon++; + } + + day = sec / SECPERDAY; + sec %= SECPERDAY; + hour = sec / 3600; + sec %= 3600; + min = sec / 60; + sec %= 60; + rtc.rtc_cen = year / 100; + rtc.rtc_year = year % 100; + rtc.rtc_mon = mon+1; + rtc.rtc_day = day+1; + rtc.rtc_hour = hour; + rtc.rtc_min = min; + rtc.rtc_sec = sec; + rtc.rtc_centi = + rtc.rtc_micro = 0; + + printf("resettod: %02d/%02d/%02d%02d %02d:%02d:%02d\n", rtc.rtc_day, + rtc.rtc_mon, rtc.rtc_cen, rtc.rtc_year, rtc.rtc_hour, + rtc.rtc_min, rtc.rtc_sec); + + s = splclock(); + todclock_sc->sc_rtc_write(todclock_sc->sc_rtc_arg, &rtc); + (void)splx(s); +} + +/* + * Initialise the time of day register, based on the time base which is, e.g. + * from a filesystem. + */ + +void +inittodr(base) + time_t base; +{ + time_t n; + int i, days = 0; + int s; + int year; + rtc_t rtc; + + /* + * Default to the suggested time but replace that we one from an + * RTC is we can. + */ + + /* We expect a todclock device */ + + /* Use the suggested time as a fall back */ + time.tv_sec = base; + time.tv_usec = 0; + + /* Can we read an RTC ? */ + if (todclock_sc->sc_rtc_read) { + s = splclock(); + if (todclock_sc->sc_rtc_read(todclock_sc->sc_rtc_arg, &rtc) == 0) { + (void)splx(s); + return; + } + (void)splx(s); + } else + return; + + /* Convert the rtc time into seconds */ + + n = rtc.rtc_sec + 60 * rtc.rtc_min + 3600 * rtc.rtc_hour; + n += (rtc.rtc_day - 1) * 3600 * 24; + year = (rtc.rtc_year + rtc.rtc_cen * 100) - 1900; + + if (yeartoday(year) == 366) + month[1] = 29; + for (i = rtc.rtc_mon - 2; i >= 0; i--) + days += month[i]; + month[1] = 28; + + for (i = 70; i < year; i++) + days += yeartoday(i); + + n += days * 3600 * 24; + + n += tz.tz_minuteswest * 60; + if (tz.tz_dsttime) + time.tv_sec -= 3600; + + time.tv_sec = n; + time.tv_usec = 0; + + /* timeset is used to ensure the time is valid before a resettodr() */ + + timeset = 1; + + /* If the base was 0 then keep quiet */ + + if (base) { + printf("inittodr: %02d:%02d:%02d.%02d%02d %02d/%02d/%02d%02d\n", + rtc.rtc_hour, rtc.rtc_min, rtc.rtc_sec, rtc.rtc_centi, + rtc.rtc_micro, rtc.rtc_day, rtc.rtc_mon, rtc.rtc_cen, + rtc.rtc_year); + + if (n > base + 60) { + days = (n - base) / SECPERDAY; + printf("Clock has gained %d day%c %ld hours %ld minutes %ld secs\n", + days, ((days == 1) ? 0 : 's'), + (long)((n - base) / 3600) % 24, + (long)((n - base) / 60) % 60, + (long) (n - base) % 60); + } + } +} + +/* End of todclock.c */ |