summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/conf/files.i3862
-rw-r--r--sys/i386/conf/GENERIC.hints3
-rw-r--r--sys/i386/isa/clock.c271
-rw-r--r--sys/isa/atrtc.c271
4 files changed, 341 insertions, 206 deletions
diff --git a/sys/conf/files.i386 b/sys/conf/files.i386
index 90da705..b123b8d 100644
--- a/sys/conf/files.i386
+++ b/sys/conf/files.i386
@@ -445,8 +445,10 @@ i4b/layer1/itjc/i4b_itjc_l1fsm.c optional itjc
#
isa/syscons_isa.c optional sc
isa/vga_isa.c optional vga
+kern/clock_if.m standard
kern/imgact_aout.c optional compat_aout
kern/imgact_gzip.c optional gzip
+kern/subr_rtc.c standard
libkern/divdi3.c standard
libkern/ffsl.c standard
libkern/flsl.c standard
diff --git a/sys/i386/conf/GENERIC.hints b/sys/i386/conf/GENERIC.hints
index c5756fe..f97628d 100644
--- a/sys/i386/conf/GENERIC.hints
+++ b/sys/i386/conf/GENERIC.hints
@@ -74,3 +74,6 @@ hint.le.0.disabled="1"
hint.le.0.port="0x280"
hint.le.0.irq="10"
hint.le.0.drq="0"
+hint.atrtc.0.at="isa"
+hint.atrtc.0.port="0x70"
+hint.atrtc.0.irq="8"
diff --git a/sys/i386/isa/clock.c b/sys/i386/isa/clock.c
index 09a9dc4..6573b37 100644
--- a/sys/i386/isa/clock.c
+++ b/sys/i386/isa/clock.c
@@ -206,7 +206,6 @@ timer_spkr_setfreq(int freq)
mtx_unlock_spin(&clock_lock);
}
-
/*
* This routine receives statistical clock interrupts from the RTC.
* As explained above, these occur at 128 interrupts per second.
@@ -396,8 +395,7 @@ DELAY(int n)
*/
int
-rtcin(reg)
- int reg;
+rtcin(int reg)
{
u_char val;
@@ -522,98 +520,6 @@ startrtclock()
}
/*
- * Initialize the time of day register, based on the time base which is, e.g.
- * from a filesystem.
- */
-void
-inittodr(time_t base)
-{
- int s;
- struct timespec ts;
- struct clocktime ct;
-
- if (base) {
- s = splclock();
- ts.tv_sec = base;
- ts.tv_nsec = 0;
- tc_setclock(&ts);
- splx(s);
- }
-
- /* Look if we have a RTC present and the time is valid */
- if (!(rtcin(RTC_STATUSD) & RTCSD_PWR)) {
- printf("Invalid time in clock: check and reset the date!\n");
- return;
- }
-
- /* wait for time update to complete */
- /* If RTCSA_TUP is zero, we have at least 244us before next update */
- s = splhigh();
- while (rtcin(RTC_STATUSA) & RTCSA_TUP) {
- splx(s);
- s = splhigh();
- }
- ct.nsec = 0;
- ct.sec = readrtc(RTC_SEC);
- ct.min = readrtc(RTC_MIN);
- ct.hour = readrtc(RTC_HRS);
- ct.day = readrtc(RTC_DAY);
- ct.dow = readrtc(RTC_WDAY) - 1;
- ct.mon = readrtc(RTC_MONTH);
- ct.year = readrtc(RTC_YEAR);
-#ifdef USE_RTC_CENTURY
- ct.year += readrtc(RTC_CENTURY) * 100;
-#else
- ct.year += 2000;
-#endif
- /* Set dow = -1 because some clocks don't set it correctly. */
- ct.dow = -1;
- if (clock_ct_to_ts(&ct, &ts)) {
- printf("Invalid time in clock: check and reset the date!\n");
- return;
- }
- ts.tv_sec += utc_offset();
- tc_setclock(&ts);
-}
-
-/*
- * Write system time back to RTC
- */
-void
-resettodr()
-{
- struct timespec ts;
- struct clocktime ct;
-
- if (disable_rtc_set)
- return;
-
- getnanotime(&ts);
- ts.tv_sec -= utc_offset();
- clock_ts_to_ct(&ts, &ct);
-
- /* Disable RTC updates and interrupts. */
- writertc(RTC_STATUSB, RTCSB_HALT | RTCSB_24HR);
-
- writertc(RTC_SEC, bin2bcd(ct.sec)); /* Write back Seconds */
- writertc(RTC_MIN, bin2bcd(ct.min)); /* Write back Minutes */
- writertc(RTC_HRS, bin2bcd(ct.hour)); /* Write back Hours */
-
- writertc(RTC_WDAY, ct.dow + 1); /* Write back Weekday */
- writertc(RTC_DAY, bin2bcd(ct.day)); /* Write back Day */
- writertc(RTC_MONTH, bin2bcd(ct.mon)); /* Write back Month */
- writertc(RTC_YEAR, bin2bcd(ct.year % 100)); /* Write back Year */
-#ifdef USE_RTC_CENTURY
- writertc(RTC_CENTURY, bin2bcd(ct.year / 100)); /* ... and Century */
-#endif
-
- /* Reenable RTC updates and interrupts. */
- writertc(RTC_STATUSB, rtc_statusb);
- rtcin(RTC_INTR);
-}
-
-
-/*
* Start both clocks running.
*/
void
@@ -657,7 +563,8 @@ cpu_initclocks()
if (!statclock_disable && !using_lapic_timer) {
diag = rtcin(RTC_DIAG);
if (diag != 0)
- printf("RTC BIOS diagnostic error %b\n", diag, RTCDG_BITS);
+ printf("RTC BIOS diagnostic error %b\n",
+ diag, RTCDG_BITS);
/* Setting stathz to nonzero early helps avoid races. */
stathz = RTC_NOPROFRATE;
@@ -665,7 +572,8 @@ cpu_initclocks()
/* Enable periodic interrupts from the RTC. */
rtc_statusb |= RTCSB_PINTR;
- intr_add_handler("rtc", 8, (driver_filter_t *)rtcintr, NULL, NULL,
+ intr_add_handler("rtc", 8,
+ (driver_filter_t *)rtcintr, NULL, NULL,
INTR_TYPE_CLK, NULL);
writertc(RTC_STATUSB, rtc_statusb);
@@ -742,7 +650,8 @@ i8254_get_timecount(struct timecounter *tc)
count = i8254_max_count - ((high << 8) | low);
if (count < i8254_lastcount ||
(!i8254_ticked && (clkintr_pending ||
- ((count < 20 || (!(eflags & PSL_I) && count < i8254_max_count / 2u)) &&
+ ((count < 20 || (!(eflags & PSL_I) &&
+ count < i8254_max_count / 2u)) &&
i8254_pending != NULL && i8254_pending(i8254_intsrc))))) {
i8254_ticked = 1;
i8254_offset += i8254_max_count;
@@ -755,11 +664,10 @@ i8254_get_timecount(struct timecounter *tc)
#ifdef DEV_ISA
/*
- * Attach to the ISA PnP descriptors for the timer and realtime clock.
+ * Attach to the ISA PnP descriptors for the timer
*/
static struct isa_pnp_id attimer_ids[] = {
{ 0x0001d041 /* PNP0100 */, "AT timer" },
- { 0x000bd041 /* PNP0B00 */, "AT realtime clock" },
{ 0 }
};
@@ -768,7 +676,8 @@ attimer_probe(device_t dev)
{
int result;
- if ((result = ISA_PNP_PROBE(device_get_parent(dev), dev, attimer_ids)) <= 0)
+ result = ISA_PNP_PROBE(device_get_parent(dev), dev, attimer_ids);
+ if (result <= 0)
device_quiet(dev);
return(result);
}
@@ -785,8 +694,8 @@ static device_method_t attimer_methods[] = {
DEVMETHOD(device_attach, attimer_attach),
DEVMETHOD(device_detach, bus_generic_detach),
DEVMETHOD(device_shutdown, bus_generic_shutdown),
- DEVMETHOD(device_suspend, bus_generic_suspend), /* XXX stop statclock? */
- DEVMETHOD(device_resume, bus_generic_resume), /* XXX restart statclock? */
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, bus_generic_resume),
{ 0, 0 }
};
@@ -802,3 +711,159 @@ DRIVER_MODULE(attimer, isa, attimer_driver, attimer_devclass, 0, 0);
DRIVER_MODULE(attimer, acpi, attimer_driver, attimer_devclass, 0, 0);
#endif /* DEV_ISA */
+
+#ifdef DEV_ISA
+
+/**********************************************************************
+ * RTC driver for subr_rtc
+ */
+
+#include "clock_if.h"
+
+#include <sys/rman.h>
+
+struct atrtc_softc {
+ int port_rid, intr_rid;
+ struct resource *port_res;
+ struct resource *intr_res;
+};
+
+/*
+ * Attach to the ISA PnP descriptors for the timer and realtime clock.
+ */
+static struct isa_pnp_id atrtc_ids[] = {
+ { 0x000bd041 /* PNP0B00 */, "AT realtime clock" },
+ { 0 }
+};
+
+static int
+atrtc_probe(device_t dev)
+{
+ int result;
+
+ device_set_desc(dev, "AT Real Time Clock");
+ result = ISA_PNP_PROBE(device_get_parent(dev), dev, atrtc_ids);
+ /* ENXIO if wrong PnP-ID, ENOENT ifno PnP-ID, zero if good PnP-iD */
+ if (result != ENOENT)
+ return(result);
+ /* All PC's have an RTC, and we're hosed without it, so... */
+ return (BUS_PROBE_LOW_PRIORITY);
+}
+
+static int
+atrtc_attach(device_t dev)
+{
+ struct atrtc_softc *sc;
+
+ /*
+ * Not that we need them or anything, but grab our resources
+ * so they show up, correctly attributed, in the big picture.
+ */
+
+ sc = device_get_softc(dev);
+ if (!(sc->port_res = bus_alloc_resource(dev, SYS_RES_IOPORT,
+ &sc->port_rid, IO_RTC, IO_RTC + 1, 2, RF_ACTIVE)))
+ device_printf(dev,"Warning: Couldn't map I/O.\n");
+ if (!(sc->intr_res = bus_alloc_resource(dev, SYS_RES_IRQ,
+ &sc->intr_rid, 8, 8, 1, RF_ACTIVE)))
+ device_printf(dev,"Warning: Couldn't map Interrupt.\n");
+ clock_register(dev, 1000000);
+ return(0);
+}
+
+
+static int
+atrtc_settime(device_t dev __unused, struct timespec *ts)
+{
+ struct clocktime ct;
+
+ clock_ts_to_ct(ts, &ct);
+
+ /* Disable RTC updates and interrupts. */
+ writertc(RTC_STATUSB, RTCSB_HALT | RTCSB_24HR);
+
+ writertc(RTC_SEC, bin2bcd(ct.sec)); /* Write back Seconds */
+ writertc(RTC_MIN, bin2bcd(ct.min)); /* Write back Minutes */
+ writertc(RTC_HRS, bin2bcd(ct.hour)); /* Write back Hours */
+
+ writertc(RTC_WDAY, ct.dow + 1); /* Write back Weekday */
+ writertc(RTC_DAY, bin2bcd(ct.day)); /* Write back Day */
+ writertc(RTC_MONTH, bin2bcd(ct.mon)); /* Write back Month */
+ writertc(RTC_YEAR, bin2bcd(ct.year % 100)); /* Write back Year */
+#ifdef USE_RTC_CENTURY
+ writertc(RTC_CENTURY, bin2bcd(ct.year / 100)); /* ... and Century */
+#endif
+
+ /* Reenable RTC updates and interrupts. */
+ writertc(RTC_STATUSB, rtc_statusb);
+ rtcin(RTC_INTR);
+ return (0);
+}
+
+static int
+atrtc_gettime(device_t dev, struct timespec *ts)
+{
+ struct clocktime ct;
+ int s;
+
+ /* Look if we have a RTC present and the time is valid */
+ if (!(rtcin(RTC_STATUSD) & RTCSD_PWR)) {
+ device_printf(dev, "WARNING: Battery failure indication\n");
+ return (EINVAL);
+ }
+
+ /* wait for time update to complete */
+ /* If RTCSA_TUP is zero, we have at least 244us before next update */
+ s = splhigh();
+ while (rtcin(RTC_STATUSA) & RTCSA_TUP) {
+ splx(s);
+ s = splhigh();
+ }
+ ct.nsec = 0;
+ ct.sec = readrtc(RTC_SEC);
+ ct.min = readrtc(RTC_MIN);
+ ct.hour = readrtc(RTC_HRS);
+ ct.day = readrtc(RTC_DAY);
+ ct.dow = readrtc(RTC_WDAY) - 1;
+ ct.mon = readrtc(RTC_MONTH);
+ ct.year = readrtc(RTC_YEAR);
+#ifdef USE_RTC_CENTURY
+ ct.year += readrtc(RTC_CENTURY) * 100;
+#else
+ ct.year += 2000;
+#endif
+ /* Set dow = -1 because some clocks don't set it correctly. */
+ ct.dow = -1;
+ return (clock_ct_to_ts(&ct, ts));
+}
+
+static device_method_t atrtc_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, atrtc_probe),
+ DEVMETHOD(device_attach, atrtc_attach),
+ DEVMETHOD(device_detach, bus_generic_detach),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ /* XXX stop statclock? */
+ DEVMETHOD(device_resume, bus_generic_resume),
+ /* XXX restart statclock? */
+
+ /* clock interface */
+ DEVMETHOD(clock_gettime, atrtc_gettime),
+ DEVMETHOD(clock_settime, atrtc_settime),
+
+ { 0, 0 }
+};
+
+static driver_t atrtc_driver = {
+ "atrtc",
+ atrtc_methods,
+ sizeof(struct atrtc_softc),
+};
+
+static devclass_t atrtc_devclass;
+
+DRIVER_MODULE(atrtc, isa, atrtc_driver, atrtc_devclass, 0, 0);
+DRIVER_MODULE(atrtc, acpi, atrtc_driver, atrtc_devclass, 0, 0);
+
+#endif /* DEV_ISA */
diff --git a/sys/isa/atrtc.c b/sys/isa/atrtc.c
index 09a9dc4..6573b37 100644
--- a/sys/isa/atrtc.c
+++ b/sys/isa/atrtc.c
@@ -206,7 +206,6 @@ timer_spkr_setfreq(int freq)
mtx_unlock_spin(&clock_lock);
}
-
/*
* This routine receives statistical clock interrupts from the RTC.
* As explained above, these occur at 128 interrupts per second.
@@ -396,8 +395,7 @@ DELAY(int n)
*/
int
-rtcin(reg)
- int reg;
+rtcin(int reg)
{
u_char val;
@@ -522,98 +520,6 @@ startrtclock()
}
/*
- * Initialize the time of day register, based on the time base which is, e.g.
- * from a filesystem.
- */
-void
-inittodr(time_t base)
-{
- int s;
- struct timespec ts;
- struct clocktime ct;
-
- if (base) {
- s = splclock();
- ts.tv_sec = base;
- ts.tv_nsec = 0;
- tc_setclock(&ts);
- splx(s);
- }
-
- /* Look if we have a RTC present and the time is valid */
- if (!(rtcin(RTC_STATUSD) & RTCSD_PWR)) {
- printf("Invalid time in clock: check and reset the date!\n");
- return;
- }
-
- /* wait for time update to complete */
- /* If RTCSA_TUP is zero, we have at least 244us before next update */
- s = splhigh();
- while (rtcin(RTC_STATUSA) & RTCSA_TUP) {
- splx(s);
- s = splhigh();
- }
- ct.nsec = 0;
- ct.sec = readrtc(RTC_SEC);
- ct.min = readrtc(RTC_MIN);
- ct.hour = readrtc(RTC_HRS);
- ct.day = readrtc(RTC_DAY);
- ct.dow = readrtc(RTC_WDAY) - 1;
- ct.mon = readrtc(RTC_MONTH);
- ct.year = readrtc(RTC_YEAR);
-#ifdef USE_RTC_CENTURY
- ct.year += readrtc(RTC_CENTURY) * 100;
-#else
- ct.year += 2000;
-#endif
- /* Set dow = -1 because some clocks don't set it correctly. */
- ct.dow = -1;
- if (clock_ct_to_ts(&ct, &ts)) {
- printf("Invalid time in clock: check and reset the date!\n");
- return;
- }
- ts.tv_sec += utc_offset();
- tc_setclock(&ts);
-}
-
-/*
- * Write system time back to RTC
- */
-void
-resettodr()
-{
- struct timespec ts;
- struct clocktime ct;
-
- if (disable_rtc_set)
- return;
-
- getnanotime(&ts);
- ts.tv_sec -= utc_offset();
- clock_ts_to_ct(&ts, &ct);
-
- /* Disable RTC updates and interrupts. */
- writertc(RTC_STATUSB, RTCSB_HALT | RTCSB_24HR);
-
- writertc(RTC_SEC, bin2bcd(ct.sec)); /* Write back Seconds */
- writertc(RTC_MIN, bin2bcd(ct.min)); /* Write back Minutes */
- writertc(RTC_HRS, bin2bcd(ct.hour)); /* Write back Hours */
-
- writertc(RTC_WDAY, ct.dow + 1); /* Write back Weekday */
- writertc(RTC_DAY, bin2bcd(ct.day)); /* Write back Day */
- writertc(RTC_MONTH, bin2bcd(ct.mon)); /* Write back Month */
- writertc(RTC_YEAR, bin2bcd(ct.year % 100)); /* Write back Year */
-#ifdef USE_RTC_CENTURY
- writertc(RTC_CENTURY, bin2bcd(ct.year / 100)); /* ... and Century */
-#endif
-
- /* Reenable RTC updates and interrupts. */
- writertc(RTC_STATUSB, rtc_statusb);
- rtcin(RTC_INTR);
-}
-
-
-/*
* Start both clocks running.
*/
void
@@ -657,7 +563,8 @@ cpu_initclocks()
if (!statclock_disable && !using_lapic_timer) {
diag = rtcin(RTC_DIAG);
if (diag != 0)
- printf("RTC BIOS diagnostic error %b\n", diag, RTCDG_BITS);
+ printf("RTC BIOS diagnostic error %b\n",
+ diag, RTCDG_BITS);
/* Setting stathz to nonzero early helps avoid races. */
stathz = RTC_NOPROFRATE;
@@ -665,7 +572,8 @@ cpu_initclocks()
/* Enable periodic interrupts from the RTC. */
rtc_statusb |= RTCSB_PINTR;
- intr_add_handler("rtc", 8, (driver_filter_t *)rtcintr, NULL, NULL,
+ intr_add_handler("rtc", 8,
+ (driver_filter_t *)rtcintr, NULL, NULL,
INTR_TYPE_CLK, NULL);
writertc(RTC_STATUSB, rtc_statusb);
@@ -742,7 +650,8 @@ i8254_get_timecount(struct timecounter *tc)
count = i8254_max_count - ((high << 8) | low);
if (count < i8254_lastcount ||
(!i8254_ticked && (clkintr_pending ||
- ((count < 20 || (!(eflags & PSL_I) && count < i8254_max_count / 2u)) &&
+ ((count < 20 || (!(eflags & PSL_I) &&
+ count < i8254_max_count / 2u)) &&
i8254_pending != NULL && i8254_pending(i8254_intsrc))))) {
i8254_ticked = 1;
i8254_offset += i8254_max_count;
@@ -755,11 +664,10 @@ i8254_get_timecount(struct timecounter *tc)
#ifdef DEV_ISA
/*
- * Attach to the ISA PnP descriptors for the timer and realtime clock.
+ * Attach to the ISA PnP descriptors for the timer
*/
static struct isa_pnp_id attimer_ids[] = {
{ 0x0001d041 /* PNP0100 */, "AT timer" },
- { 0x000bd041 /* PNP0B00 */, "AT realtime clock" },
{ 0 }
};
@@ -768,7 +676,8 @@ attimer_probe(device_t dev)
{
int result;
- if ((result = ISA_PNP_PROBE(device_get_parent(dev), dev, attimer_ids)) <= 0)
+ result = ISA_PNP_PROBE(device_get_parent(dev), dev, attimer_ids);
+ if (result <= 0)
device_quiet(dev);
return(result);
}
@@ -785,8 +694,8 @@ static device_method_t attimer_methods[] = {
DEVMETHOD(device_attach, attimer_attach),
DEVMETHOD(device_detach, bus_generic_detach),
DEVMETHOD(device_shutdown, bus_generic_shutdown),
- DEVMETHOD(device_suspend, bus_generic_suspend), /* XXX stop statclock? */
- DEVMETHOD(device_resume, bus_generic_resume), /* XXX restart statclock? */
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, bus_generic_resume),
{ 0, 0 }
};
@@ -802,3 +711,159 @@ DRIVER_MODULE(attimer, isa, attimer_driver, attimer_devclass, 0, 0);
DRIVER_MODULE(attimer, acpi, attimer_driver, attimer_devclass, 0, 0);
#endif /* DEV_ISA */
+
+#ifdef DEV_ISA
+
+/**********************************************************************
+ * RTC driver for subr_rtc
+ */
+
+#include "clock_if.h"
+
+#include <sys/rman.h>
+
+struct atrtc_softc {
+ int port_rid, intr_rid;
+ struct resource *port_res;
+ struct resource *intr_res;
+};
+
+/*
+ * Attach to the ISA PnP descriptors for the timer and realtime clock.
+ */
+static struct isa_pnp_id atrtc_ids[] = {
+ { 0x000bd041 /* PNP0B00 */, "AT realtime clock" },
+ { 0 }
+};
+
+static int
+atrtc_probe(device_t dev)
+{
+ int result;
+
+ device_set_desc(dev, "AT Real Time Clock");
+ result = ISA_PNP_PROBE(device_get_parent(dev), dev, atrtc_ids);
+ /* ENXIO if wrong PnP-ID, ENOENT ifno PnP-ID, zero if good PnP-iD */
+ if (result != ENOENT)
+ return(result);
+ /* All PC's have an RTC, and we're hosed without it, so... */
+ return (BUS_PROBE_LOW_PRIORITY);
+}
+
+static int
+atrtc_attach(device_t dev)
+{
+ struct atrtc_softc *sc;
+
+ /*
+ * Not that we need them or anything, but grab our resources
+ * so they show up, correctly attributed, in the big picture.
+ */
+
+ sc = device_get_softc(dev);
+ if (!(sc->port_res = bus_alloc_resource(dev, SYS_RES_IOPORT,
+ &sc->port_rid, IO_RTC, IO_RTC + 1, 2, RF_ACTIVE)))
+ device_printf(dev,"Warning: Couldn't map I/O.\n");
+ if (!(sc->intr_res = bus_alloc_resource(dev, SYS_RES_IRQ,
+ &sc->intr_rid, 8, 8, 1, RF_ACTIVE)))
+ device_printf(dev,"Warning: Couldn't map Interrupt.\n");
+ clock_register(dev, 1000000);
+ return(0);
+}
+
+
+static int
+atrtc_settime(device_t dev __unused, struct timespec *ts)
+{
+ struct clocktime ct;
+
+ clock_ts_to_ct(ts, &ct);
+
+ /* Disable RTC updates and interrupts. */
+ writertc(RTC_STATUSB, RTCSB_HALT | RTCSB_24HR);
+
+ writertc(RTC_SEC, bin2bcd(ct.sec)); /* Write back Seconds */
+ writertc(RTC_MIN, bin2bcd(ct.min)); /* Write back Minutes */
+ writertc(RTC_HRS, bin2bcd(ct.hour)); /* Write back Hours */
+
+ writertc(RTC_WDAY, ct.dow + 1); /* Write back Weekday */
+ writertc(RTC_DAY, bin2bcd(ct.day)); /* Write back Day */
+ writertc(RTC_MONTH, bin2bcd(ct.mon)); /* Write back Month */
+ writertc(RTC_YEAR, bin2bcd(ct.year % 100)); /* Write back Year */
+#ifdef USE_RTC_CENTURY
+ writertc(RTC_CENTURY, bin2bcd(ct.year / 100)); /* ... and Century */
+#endif
+
+ /* Reenable RTC updates and interrupts. */
+ writertc(RTC_STATUSB, rtc_statusb);
+ rtcin(RTC_INTR);
+ return (0);
+}
+
+static int
+atrtc_gettime(device_t dev, struct timespec *ts)
+{
+ struct clocktime ct;
+ int s;
+
+ /* Look if we have a RTC present and the time is valid */
+ if (!(rtcin(RTC_STATUSD) & RTCSD_PWR)) {
+ device_printf(dev, "WARNING: Battery failure indication\n");
+ return (EINVAL);
+ }
+
+ /* wait for time update to complete */
+ /* If RTCSA_TUP is zero, we have at least 244us before next update */
+ s = splhigh();
+ while (rtcin(RTC_STATUSA) & RTCSA_TUP) {
+ splx(s);
+ s = splhigh();
+ }
+ ct.nsec = 0;
+ ct.sec = readrtc(RTC_SEC);
+ ct.min = readrtc(RTC_MIN);
+ ct.hour = readrtc(RTC_HRS);
+ ct.day = readrtc(RTC_DAY);
+ ct.dow = readrtc(RTC_WDAY) - 1;
+ ct.mon = readrtc(RTC_MONTH);
+ ct.year = readrtc(RTC_YEAR);
+#ifdef USE_RTC_CENTURY
+ ct.year += readrtc(RTC_CENTURY) * 100;
+#else
+ ct.year += 2000;
+#endif
+ /* Set dow = -1 because some clocks don't set it correctly. */
+ ct.dow = -1;
+ return (clock_ct_to_ts(&ct, ts));
+}
+
+static device_method_t atrtc_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, atrtc_probe),
+ DEVMETHOD(device_attach, atrtc_attach),
+ DEVMETHOD(device_detach, bus_generic_detach),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ /* XXX stop statclock? */
+ DEVMETHOD(device_resume, bus_generic_resume),
+ /* XXX restart statclock? */
+
+ /* clock interface */
+ DEVMETHOD(clock_gettime, atrtc_gettime),
+ DEVMETHOD(clock_settime, atrtc_settime),
+
+ { 0, 0 }
+};
+
+static driver_t atrtc_driver = {
+ "atrtc",
+ atrtc_methods,
+ sizeof(struct atrtc_softc),
+};
+
+static devclass_t atrtc_devclass;
+
+DRIVER_MODULE(atrtc, isa, atrtc_driver, atrtc_devclass, 0, 0);
+DRIVER_MODULE(atrtc, acpi, atrtc_driver, atrtc_devclass, 0, 0);
+
+#endif /* DEV_ISA */
OpenPOWER on IntegriCloud