Prex Home / Browse Source - Prex Version: 0.9.0

root/bsp/drv/dev/rtc/rtc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. leapyear
  2. rtc_ymdhms_to_secs
  3. rtc_secs_to_ymdhms
  4. rtc_ioctl
  5. rtc_attach
  6. rtc_init

   1 /*
   2  * Copyright (c) 1988 University of Utah.
   3  * Copyright (c) 1982, 1990, 1993
   4  *      The Regents of the University of California.  All rights reserved.
   5  *
   6  * This code is derived from software contributed to Berkeley by
   7  * the Systems Programming Group of the University of Utah Computer
   8  * Science Department.
   9  *
  10  * Redistribution and use in source and binary forms, with or without
  11  * modification, are permitted provided that the following conditions
  12  * are met:
  13  * 1. Redistributions of source code must retain the above copyright
  14  *    notice, this list of conditions and the following disclaimer.
  15  * 2. Redistributions in binary form must reproduce the above copyright
  16  *    notice, this list of conditions and the following disclaimer in the
  17  *    documentation and/or other materials provided with the distribution.
  18  * 3. Neither the name of the University nor the names of its contributors
  19  *    may be used to endorse or promote products derived from this software
  20  *    without specific prior written permission.
  21  *
  22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  32  * SUCH DAMAGE.
  33  *
  34  * from: Utah $Hdr: clock.c 1.18 91/01/21$
  35  *
  36  *      @(#)clock.c     8.2 (Berkeley) 1/12/94
  37  */
  38 
  39 /* Modified for Prex by Kohsuke Ohtani */
  40 
  41 /*
  42  * rtc.c - machine independent RTC driver
  43  */
  44 
  45 #include <sys/time.h>
  46 #include <sys/ioctl.h>
  47 
  48 #include <driver.h>
  49 #include <rtc.h>
  50 
  51 #define FEBRUARY        2
  52 #define days_in_year(a)         (leapyear(a) ? 366 : 365)
  53 #define days_in_month(a)        (month_days[(a) - 1])
  54 
  55 struct rtc_softc {
  56         device_t        dev;            /* device object */
  57         struct rtc_ops  *ops;           /* rtc operations */
  58         void            *aux;           /* cookie data */
  59         time_t          boot_sec;       /* Time (sec) at system boot */
  60         u_long          boot_ticks;     /* Time (ticks) at system boot */
  61 };
  62 
  63 static int rtc_ioctl(device_t, u_long, void *);
  64 static int rtc_init(struct driver *);
  65 
  66 static struct devops rtc_devops = {
  67         /* open */      no_open,
  68         /* close */     no_close,
  69         /* read */      no_read,
  70         /* write */     no_write,
  71         /* ioctl */     rtc_ioctl,
  72         /* devctl */    no_devctl,
  73 };
  74 
  75 struct driver rtc_driver = {
  76         /* name */      "rtc",
  77         /* devops */    &rtc_devops,
  78         /* devsz */     sizeof(struct rtc_softc),
  79         /* flags */     0,
  80         /* probe */     NULL,
  81         /* init */      rtc_init,
  82         /* shutdown */  NULL,
  83 };
  84 
  85 static const int month_days[12] = {
  86         31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  87 };
  88 
  89 static int
  90 leapyear(u_int year)
  91 {
  92         int rv = 0;
  93 
  94         if ((year & 3) == 0) {
  95                 rv = 1;
  96                 if ((year % 100) == 0) {
  97                         rv = 0;
  98                         if ((year % 400) == 0)
  99                                 rv = 1;
 100                 }
 101         }
 102         return (rv);
 103 }
 104 
 105 time_t
 106 rtc_ymdhms_to_secs(struct clock_ymdhms *dt)
 107 {
 108         time_t secs;
 109         u_int i, year, days;
 110 
 111         year = dt->year;
 112 
 113         /*
 114          * Compute days since start of time.
 115          * First from years, then from months.
 116          */
 117         days = 0;
 118         for (i = POSIX_BASE_YEAR; i < year; i++)
 119                 days += days_in_year(i);
 120         if (leapyear(year) && dt->mon > FEBRUARY)
 121                 days++;
 122 
 123         /* Months */
 124         for (i = 1; i < dt->mon; i++)
 125                 days += days_in_month(i);
 126         days += (dt->day - 1);
 127 
 128         /* Add hours, minutes, seconds. */
 129         secs = (time_t)(((days * 24 + dt->hour) * 60 + dt->min)
 130                         * 60 + dt->sec);
 131 
 132         return (secs);
 133 }
 134 
 135 /* This function uses a copy of month_days[] */
 136 #undef  days_in_month
 137 #define days_in_month(a)        (mthdays[(a) - 1])
 138 
 139 void
 140 rtc_secs_to_ymdhms(time_t secs, struct clock_ymdhms *dt)
 141 {
 142         u_int mthdays[12];
 143         u_int i, days;
 144         u_int rsec;     /* remainder seconds */
 145 
 146         memcpy(mthdays, month_days, sizeof(mthdays));
 147 
 148         days = secs / SECDAY;
 149         rsec = secs % SECDAY;
 150 
 151         /* Day of week (Note: 1/1/1970 was a Thursday) */
 152         dt->dow = (days + 4) % 7;
 153 
 154         /* Subtract out whole years, counting them in i. */
 155         for (i = POSIX_BASE_YEAR; days >= days_in_year(i); i++)
 156                 days -= days_in_year(i);
 157         dt->year = (u_short)i;
 158 
 159         /* Subtract out whole months, counting them in i. */
 160         if (leapyear(i))
 161                 days_in_month(FEBRUARY) = 29;
 162         for (i = 1; days >= days_in_month(i); i++)
 163                 days -= days_in_month(i);
 164         dt->mon = i;
 165 
 166         /* Days are what is left over (+1) from all that. */
 167         dt->day = days + 1;
 168 
 169         /* Hours, minutes, seconds are easy */
 170         dt->hour = rsec / 3600;
 171         rsec = rsec % 3600;
 172         dt->min  = rsec / 60;
 173         rsec = rsec % 60;
 174         dt->sec  = rsec;
 175 }
 176 
 177 static int
 178 rtc_ioctl(device_t dev, u_long cmd, void *arg)
 179 {
 180         struct rtc_softc *sc = device_private(dev);
 181         struct timeval tv;
 182         int error = 0;
 183         u_long msec;
 184 
 185         switch (cmd) {
 186         case RTCIOC_GET_TIME:
 187                 /*
 188                  * Calculate current time (sec/usec) from
 189                  * boot time and current tick count.
 190                  */
 191                 msec = hztoms(timer_ticks() - sc->boot_ticks);
 192                 tv.tv_sec = sc->boot_sec + (msec / 1000);
 193                 tv.tv_usec = (long)((msec * 1000) % 1000000);
 194                 if (copyout(&tv, arg, sizeof(tv)))
 195                         return EFAULT;
 196                 break;
 197 
 198         case RTCIOC_SET_TIME:
 199                 /*
 200                  * TODO: We need new capability to set time.
 201                  */
 202                 error = EINVAL;
 203                 break;
 204         default:
 205                 return EINVAL;
 206         }
 207         return error;
 208 }
 209 
 210 void
 211 rtc_attach(struct rtc_ops *ops, void *aux)
 212 {
 213         struct rtc_softc *sc;
 214         device_t dev;
 215         struct timeval tv;
 216 
 217         dev = device_create(&rtc_driver, "rtc", D_CHR);
 218 
 219         sc = device_private(dev);
 220         sc->dev = dev;
 221         sc->ops = ops;
 222         sc->aux = aux;
 223 
 224         /* Save boot time for later use. */
 225         ops->gettime(aux, &tv);
 226         sc->boot_sec = tv.tv_sec;
 227         sc->boot_ticks = timer_ticks();
 228 }
 229 
 230 static int
 231 rtc_init(struct driver *self)
 232 {
 233 
 234         return 0;
 235 }

/* [<][>][^][v][top][bottom][index][help] */