[BACK]Return to rtc.c CVS log [TXT][DIR] Up to [local] / prex / dev / i386 / pc

Annotation of prex/dev/i386/pc/rtc.c, Revision 1.1.1.1

1.1       nbrk        1: /*-
                      2:  * Copyright (c) 2005, Kohsuke Ohtani
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms, with or without
                      6:  * modification, are permitted provided that the following conditions
                      7:  * are met:
                      8:  * 1. Redistributions of source code must retain the above copyright
                      9:  *    notice, this list of conditions and the following disclaimer.
                     10:  * 2. Redistributions in binary form must reproduce the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer in the
                     12:  *    documentation and/or other materials provided with the distribution.
                     13:  * 3. Neither the name of the author nor the names of any co-contributors
                     14:  *    may be used to endorse or promote products derived from this software
                     15:  *    without specific prior written permission.
                     16:  *
                     17:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
                     18:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     19:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     20:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
                     21:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     22:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     23:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     24:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     25:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     26:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     27:  * SUCH DAMAGE.
                     28:  */
                     29:
                     30: /*
                     31:  * rtc.c - Real time clock driver
                     32:  */
                     33:
                     34: #include <sys/time.h>
                     35: #include <sys/ioctl.h>
                     36:
                     37: #include <driver.h>
                     38: #include <cpufunc.h>
                     39:
                     40: /* Cmos */
                     41: #define CMOS_INDEX     0x70
                     42: #define CMOS_DATA      0x71
                     43:
                     44: /* CMOS address */
                     45: #define CMOS_SEC       0x00
                     46: #define CMOS_MIN       0x02
                     47: #define CMOS_HOUR      0x04
                     48: #define CMOS_DAY       0x07
                     49: #define CMOS_MON       0x08
                     50: #define CMOS_YEAR      0x09
                     51: #define CMOS_STS_A     0x0a
                     52: #define CMOS_UIP         0x80
                     53: #define CMOS_STS_B     0x0b
                     54: #define CMOS_BCD         0x04
                     55:
                     56:
                     57: #define DAYSPERYEAR    (31+28+31+30+31+30+31+31+30+31+30+31)
                     58:
                     59: static int rtc_read(device_t dev, char *buf, size_t *nbyte, int blkno);
                     60: static int rtc_ioctl(device_t dev, u_long cmd, void *arg);
                     61: static int rtc_init(void);
                     62:
                     63: /*
                     64:  * Driver structure
                     65:  */
                     66: struct driver rtc_drv = {
                     67:        /* name */      "Realtime Clock",
                     68:        /* order */     4,
                     69:        /* init */      rtc_init,
                     70: };
                     71:
                     72: /*
                     73:  * Device I/O table
                     74:  */
                     75: static struct devio rtc_io = {
                     76:        /* open */      NULL,
                     77:        /* close */     NULL,
                     78:        /* read */      rtc_read,
                     79:        /* write */     NULL,
                     80:        /* ioctl */     rtc_ioctl,
                     81:        /* event */     NULL,
                     82: };
                     83:
                     84: static const int daysinmonth[] =
                     85:     { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
                     86:
                     87: static device_t rtc_dev;       /* Device object */
                     88: static u_long boot_sec;                /* Time (sec) at system boot */
                     89: static u_long boot_ticks;      /* Time (ticks) at system boot */
                     90:
                     91:
                     92: static u_int
                     93: cmos_read(int index)
                     94: {
                     95:        u_int value;
                     96:
                     97:        irq_lock();
                     98:        outb(index, CMOS_INDEX);
                     99:        value = inb(CMOS_DATA);
                    100:        irq_unlock();
                    101:        return value;
                    102: }
                    103:
                    104: /*
                    105: static void
                    106: cmos_write(int index, int value)
                    107: {
                    108:     irq_lock();
                    109:     outb(index, CMOS_INDEX);
                    110:     outb(value, CMOS_DATA);
                    111:     irq_unlock();
                    112: }
                    113: */
                    114:
                    115: static u_int
                    116: bcd2bin(u_int bcd)
                    117: {
                    118:
                    119:        return (bcd & 0x0f) + ((bcd >> 4) & 0xf) * 10;
                    120: }
                    121:
                    122: /*
                    123: static int bin2bcd(int bin)
                    124: {
                    125:     return ((bin / 10) << 4) + (bin % 10);
                    126: }
                    127: */
                    128:
                    129: static int
                    130: is_leap(u_int year)
                    131: {
                    132:
                    133:        if ((year % 4 == 0) && (year % 100 != 0))
                    134:                return 1;
                    135:        if (year % 400 == 0)
                    136:                return 1;
                    137:        return 0;
                    138: }
                    139:
                    140: /*
                    141:  * Return current seconds (seconds since Epoch 1970/1/1 0:0:0)
                    142:  */
                    143: static u_long
                    144: cmos_gettime(void)
                    145: {
                    146:        u_int sec, min, hour, day, mon, year;
                    147:        u_int i;
                    148:        u_int days;
                    149:
                    150:        /* Wait until data ready */
                    151:        for (i = 0; i < 1000000; i++)
                    152:                if (!(cmos_read(CMOS_STS_A) & CMOS_UIP))
                    153:                        break;
                    154:
                    155:        sec = cmos_read(CMOS_SEC);
                    156:        min = cmos_read(CMOS_MIN);
                    157:        hour = cmos_read(CMOS_HOUR);
                    158:        day = cmos_read(CMOS_DAY);
                    159:        mon = cmos_read(CMOS_MON);
                    160:        year = cmos_read(CMOS_YEAR);
                    161:
                    162:        if (!(cmos_read(CMOS_STS_B) & CMOS_BCD)) {
                    163:                sec = bcd2bin(sec);
                    164:                min = bcd2bin(min);
                    165:                hour = bcd2bin(hour);
                    166:                day = bcd2bin(day);
                    167:                mon = bcd2bin(mon);
                    168:                year = bcd2bin(year);
                    169:        }
                    170:        if (year < 80)
                    171:                year += 2000;
                    172:        else
                    173:                year += 1900;
                    174: #ifdef DEBUG
                    175:        printf("rtc: system time was %d/%d/%d %d:%d:%d\n",
                    176:                year, mon, day, hour, min, sec);
                    177: #endif
                    178:
                    179:        days = 0;
                    180:        for (i = 1970; i < year; i++)
                    181:                days += DAYSPERYEAR + is_leap(i);
                    182:        for (i = 1; i < mon; i++)
                    183:                days += daysinmonth[i - 1];
                    184:        if ((mon > 2) && is_leap(year))
                    185:                days++;
                    186:        days += day - 1;
                    187:
                    188:        sec = (((days * 24 + hour) * 60) + min) * 60 + sec;
                    189:        return sec;
                    190: }
                    191:
                    192: static int
                    193: rtc_read(device_t dev, char *buf, size_t *nbyte, int blkno)
                    194: {
                    195:        u_long time;
                    196:
                    197:        if (*nbyte < sizeof(u_long))
                    198:                return 0;
                    199:
                    200:        time = cmos_gettime();
                    201:        if (umem_copyout(&time, buf, sizeof(u_long)))
                    202:                return EFAULT;
                    203:        *nbyte = sizeof(u_long);
                    204:        return 0;
                    205: }
                    206:
                    207: static int
                    208: rtc_ioctl(device_t dev, u_long cmd, void *arg)
                    209: {
                    210:        struct timeval tv;
                    211:        int err = 0;
                    212:        u_long msec;
                    213:
                    214:        switch (cmd) {
                    215:        case RTCIOC_GET_TIME:
                    216:                /*
                    217:                 * Calculate current time (sec/usec) from
                    218:                 * boot time and current tick count.
                    219:                 */
                    220:                msec = tick_to_msec(timer_count() - boot_ticks);
                    221:                tv.tv_sec = (long)(boot_sec + (msec / 1000));
                    222:                tv.tv_usec = (long)((msec * 1000) % 1000000);
                    223:                if (umem_copyout(&tv, arg, sizeof(tv)))
                    224:                        return EFAULT;
                    225:                break;
                    226:        case RTCIOC_SET_TIME:
                    227:                err = EINVAL;
                    228:                break;
                    229:        default:
                    230:                return EINVAL;
                    231:        }
                    232:        return err;
                    233: }
                    234:
                    235: /*
                    236:  * Initialize
                    237:  */
                    238: static int
                    239: rtc_init(void)
                    240: {
                    241:
                    242:        /* Create device object */
                    243:        rtc_dev = device_create(&rtc_io, "rtc", DF_CHR);
                    244:        ASSERT(rtc_dev);
                    245:        boot_sec = cmos_gettime();
                    246:        boot_ticks = timer_count();
                    247:        return 0;
                    248: }

CVSweb