Initial import from FreeBSD RELENG_4:
[dragonfly.git] / sys / dev / misc / dec / mcclock.c
1 /* $FreeBSD: src/sys/dev/dec/mcclock.c,v 1.5.2.2 2001/12/17 14:03:15 gallatin Exp $ */
2 /* $NetBSD: mcclock.c,v 1.11 1998/04/19 07:50:25 jonathan Exp $ */
3
4 /*
5  * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
6  * All rights reserved.
7  *
8  * Author: Chris G. Demetriou
9  *
10  * Permission to use, copy, modify and distribute this software and
11  * its documentation is hereby granted, provided that both the copyright
12  * notice and this permission notice appear in all copies of the
13  * software, derivative works or modified versions, and any portions
14  * thereof, and that both notices appear in supporting documentation.
15  *
16  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
17  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
18  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
19  *
20  * Carnegie Mellon requests users of this software to return to
21  *
22  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
23  *  School of Computer Science
24  *  Carnegie Mellon University
25  *  Pittsburgh PA 15213-3890
26  *
27  * any improvements or extensions that they make and grant Carnegie the
28  * rights to redistribute these changes.
29  */
30
31 #include <sys/param.h>
32 #include <sys/kernel.h>
33 #include <sys/systm.h>
34 #include <sys/bus.h>
35
36 #include <machine/clockvar.h>
37 #include <dev/dec/mcclockvar.h>
38 #include <dev/dec/mc146818reg.h>
39
40 /*
41  * XXX rate is machine-dependent.
42  */
43 #ifdef __alpha__
44 #define MC_DEFAULTRATE MC_RATE_1024_Hz
45 #endif
46 #ifdef __pmax__
47 #define MC_DEFAULTRATE MC_RATE_256_Hz
48 #endif
49
50 void
51 mcclock_attach(device_t dev)
52 {
53         /* Turn interrupts off, just in case. */
54         MCCLOCK_WRITE(dev, MC_REGB, MC_REGB_BINARY | MC_REGB_24HR);
55
56         clockattach(dev);
57 }
58
59 void
60 mcclock_init(device_t dev)
61 {
62         MCCLOCK_WRITE(dev, MC_REGA, MC_BASE_32_KHz | MC_DEFAULTRATE);
63         MCCLOCK_WRITE(dev, MC_REGB,
64             MC_REGB_PIE | MC_REGB_SQWE | MC_REGB_BINARY | MC_REGB_24HR);
65 }
66
67 /*
68  * Get the time of day, based on the clock's value and/or the base value.
69  */
70 void
71 mcclock_get(device_t dev, time_t base, struct clocktime *ct)
72 {
73         mc_todregs regs;
74         int s;
75
76         s = splclock();
77         MC146818_GETTOD(dev, &regs)
78         splx(s);
79
80         ct->sec = regs[MC_SEC];
81         ct->min = regs[MC_MIN];
82         ct->hour = regs[MC_HOUR];
83         ct->dow = regs[MC_DOW];
84         ct->day = regs[MC_DOM];
85         ct->mon = regs[MC_MONTH];
86         ct->year = regs[MC_YEAR];
87 }
88
89 /*
90  * Reset the TODR based on the time value.
91  */
92 void
93 mcclock_set(device_t dev, struct clocktime *ct)
94 {
95         mc_todregs regs;
96         int s;
97
98         s = splclock();
99         MC146818_GETTOD(dev, &regs);
100         splx(s);
101
102         regs[MC_SEC] = ct->sec;
103         regs[MC_MIN] = ct->min;
104         regs[MC_HOUR] = ct->hour;
105         regs[MC_DOW] = ct->dow;
106         regs[MC_DOM] = ct->day;
107         regs[MC_MONTH] = ct->mon;
108         regs[MC_YEAR] = ct->year;
109
110         s = splclock();
111         MC146818_PUTTOD(dev, &regs);
112         splx(s);
113 }
114
115 int
116 mcclock_getsecs(device_t dev, int *secp)
117 {
118         int timeout = 100000000;
119         int sec;
120         int s;
121
122         s = splclock();
123         for (;;) {
124                 if (!(MCCLOCK_READ(dev, MC_REGA) & MC_REGA_UIP)) {
125                         sec = MCCLOCK_READ(dev, MC_SEC);
126                         break;
127                 }
128                 if (--timeout == 0)
129                         goto fail;
130         }
131
132         splx(s);
133         *secp = sec;
134         return 0;
135
136  fail:
137         splx(s);
138         return ETIMEDOUT;
139 }