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

Annotation of prex-old/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: #include <sys/time.h>
                     34: #include <sys/ioctl.h>
                     35:
                     36: #include <driver.h>
                     37: #include <cpu.h>
                     38:
                     39: /* Cmos */
                     40: #define CMOS_INDEX     0x70
                     41: #define CMOS_DATA      0x71
                     42:
                     43: /* CMOS address */
                     44: #define CMOS_SEC       0x00
                     45: #define CMOS_MIN       0x02
                     46: #define CMOS_HOUR      0x04
                     47: #define CMOS_DAY       0x07
                     48: #define CMOS_MON       0x08
                     49: #define CMOS_YEAR      0x09
                     50: #define CMOS_STS_A     0x0a
                     51: #define CMOS_UIP         0x80
                     52: #define CMOS_STS_B     0x0b
                     53: #define CMOS_BCD         0x04
                     54:
                     55:
                     56: #define DAYSPERYEAR    (31+28+31+30+31+30+31+31+30+31+30+31)
                     57:
                     58: static int rtc_read(device_t dev, char *buf, size_t *nbyte, int blkno);
                     59: static int rtc_ioctl(device_t dev, int cmd, u_long arg);
                     60: static int rtc_init(void);
                     61:
                     62: /*
                     63:  * Driver structure
                     64:  */
                     65: struct driver rtc_drv = {
                     66:        /* name */      "Realtime Clock",
                     67:        /* order */     4,
                     68:        /* init */      rtc_init,
                     69: };
                     70:
                     71: static struct devio rtc_io = {
                     72:        /* open */      NULL,
                     73:        /* close */     NULL,
                     74:        /* read */      rtc_read,
                     75:        /* write */     NULL,
                     76:        /* ioctl */     rtc_ioctl,
                     77:        /* event */     NULL,
                     78: };
                     79:
                     80: static const int daysinmonth[] =
                     81:     { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
                     82:
                     83: static device_t rtc_dev;       /* Device object */
                     84: static long boot_sec;          /* Time (sec) at system boot */
                     85: static long boot_ticks;                /* Time (sec) at system boot */
                     86:
                     87:
                     88: static u_int
                     89: cmos_read(int index)
                     90: {
                     91:        u_int value;
                     92:
                     93:        irq_lock();
                     94:        outb(index, CMOS_INDEX);
                     95:        value = inb(CMOS_DATA);
                     96:        irq_unlock();
                     97:        return value;
                     98: }
                     99:
                    100: /*
                    101: static void
                    102: cmos_write(int index, int value)
                    103: {
                    104:     irq_lock();
                    105:     outb(index, CMOS_INDEX);
                    106:     outb(value, CMOS_DATA);
                    107:     irq_unlock();
                    108: }
                    109: */
                    110:
                    111: static int
                    112: bcd2bin(int bcd)
                    113: {
                    114:
                    115:        return (bcd & 0x0f) + ((bcd >> 4) & 0xf) * 10;
                    116: }
                    117:
                    118: /*
                    119: static int bin2bcd(int bin)
                    120: {
                    121:     return ((bin / 10) << 4) + (bin % 10);
                    122: }
                    123: */
                    124:
                    125: static int
                    126: is_leap(int year)
                    127: {
                    128:
                    129:        if ((year % 4 == 0) && (year % 100 != 0))
                    130:                return 1;
                    131:        if (year % 400 == 0)
                    132:                return 1;
                    133:        return 0;
                    134: }
                    135:
                    136: /*
                    137:  * Return current seconds (seconds since Epoch 1970/1/1 0:0:0)
                    138:  */
                    139: static u_long
                    140: cmos_gettime(void)
                    141: {
                    142:        unsigned int sec, min, hour, day, mon, year;
                    143:        unsigned int i;
                    144:        unsigned int days;
                    145:
                    146:        /* Wait until data ready */
                    147:        for (i = 0; i < 1000000; i++)
                    148:                if (!(cmos_read(CMOS_STS_A) & CMOS_UIP))
                    149:                        break;
                    150:
                    151:        sec = cmos_read(CMOS_SEC);
                    152:        min = cmos_read(CMOS_MIN);
                    153:        hour = cmos_read(CMOS_HOUR);
                    154:        day = cmos_read(CMOS_DAY);
                    155:        mon = cmos_read(CMOS_MON);
                    156:        year = cmos_read(CMOS_YEAR);
                    157:
                    158:        if (!(cmos_read(CMOS_STS_B) & CMOS_BCD)) {
                    159:                sec = bcd2bin(sec);
                    160:                min = bcd2bin(min);
                    161:                hour = bcd2bin(hour);
                    162:                day = bcd2bin(day);
                    163:                mon = bcd2bin(mon);
                    164:                year = bcd2bin(year);
                    165:        }
                    166:        if (year < 80)
                    167:                year += 2000;
                    168:        else
                    169:                year += 1900;
                    170:
                    171:        printk("rtc: system time was %d/%d/%d %d:%d:%d\n",
                    172:                year, mon, day, hour, min, sec);
                    173:
                    174:        days = 0;
                    175:        for (i = 1970; i < year; i++)
                    176:                days += DAYSPERYEAR + is_leap(i);
                    177:        for (i = 1; i < mon; i++)
                    178:                days += daysinmonth[i - 1];
                    179:        if ((mon > 2) && is_leap(year))
                    180:                days++;
                    181:        days += day - 1;
                    182:
                    183:        sec = (((days * 24 + hour) * 60) + min) * 60 + sec;
                    184:        return sec;
                    185: }
                    186:
                    187: static int
                    188: rtc_read(device_t dev, char *buf, size_t *nbyte, int blkno)
                    189: {
                    190:
                    191:        if (*nbyte < sizeof(u_long))
                    192:                return 0;
                    193:        *(u_long *)buf = cmos_gettime();
                    194:        *nbyte = sizeof(u_long);
                    195:        return 0;
                    196: }
                    197:
                    198: static int
                    199: rtc_ioctl(device_t dev, int cmd, u_long arg)
                    200: {
                    201:        struct timeval tv;
                    202:        int err = 0;
                    203:        long msec;
                    204:
                    205:        switch (cmd) {
                    206:        case RTCIOC_GET_TIME:
                    207:                /*
                    208:                 * Calculate current time (sec/usec) from
                    209:                 * boot time and current tick count.
                    210:                 */
                    211:                msec = tick_to_msec(timer_count() - boot_ticks);
                    212:                tv.tv_sec = boot_sec + (msec / 1000);
                    213:                tv.tv_usec = (msec * 1000) % 1000000;
                    214:                if (umem_copyout(&tv, (int *)arg, sizeof(tv)))
                    215:                        return EFAULT;
                    216:                break;
                    217:        case RTCIOC_SET_TIME:
                    218:                err = EINVAL;
                    219:                break;
                    220:        default:
                    221:                return EINVAL;
                    222:        }
                    223:        return err;
                    224: }
                    225:
                    226: /*
                    227:  * Initialize
                    228:  */
                    229: static int
                    230: rtc_init(void)
                    231: {
                    232:
                    233:        /* Create device object */
                    234:        rtc_dev = device_create(&rtc_io, "rtc", DF_CHR);
                    235:        ASSERT(rtc_dev);
                    236:        boot_sec = cmos_gettime();
                    237:        boot_ticks = timer_count();
                    238:        return 0;
                    239: }

CVSweb