diff options
author | Poul-Henning Kamp <phk@FreeBSD.org> | 2008-04-14 08:00:00 +0000 |
---|---|---|
committer | Poul-Henning Kamp <phk@FreeBSD.org> | 2008-04-14 08:00:00 +0000 |
commit | 36bff1ebfba44f495795cd1a1d62da0a800b8c14 (patch) | |
tree | 465c0207ff0956de1e94a04171037060de3420dc /sys | |
parent | 7e82012aff9888d64a85d19aaed51def9ebbff22 (diff) | |
download | src-36bff1ebfba44f495795cd1a1d62da0a800b8c14.tar.gz src-36bff1ebfba44f495795cd1a1d62da0a800b8c14.zip |
Convert amd64 and i386 to share the atrtc device driver.
Notes
Notes:
svn path=/head/; revision=178193
Diffstat (limited to 'sys')
-rw-r--r-- | sys/amd64/include/clock.h | 2 | ||||
-rw-r--r-- | sys/amd64/isa/clock.c | 254 | ||||
-rw-r--r-- | sys/conf/files.amd64 | 3 | ||||
-rw-r--r-- | sys/conf/files.i386 | 1 | ||||
-rw-r--r-- | sys/dev/acpi_support/acpi_ibm.c | 2 | ||||
-rw-r--r-- | sys/dev/fb/vga.c | 2 | ||||
-rw-r--r-- | sys/dev/nvram/nvram.c | 1 | ||||
-rw-r--r-- | sys/i386/include/clock.h | 2 | ||||
-rw-r--r-- | sys/i386/isa/clock.c | 262 |
9 files changed, 35 insertions, 494 deletions
diff --git a/sys/amd64/include/clock.h b/sys/amd64/include/clock.h index c1f3029023c0..b7fafcf4ddac 100644 --- a/sys/amd64/include/clock.h +++ b/sys/amd64/include/clock.h @@ -27,8 +27,6 @@ void i8254_init(void); * Driver to clock driver interface. */ -int rtcin(int reg); -void writertc(int reg, unsigned char val); void init_TSC(void); void init_TSC_tc(void); diff --git a/sys/amd64/isa/clock.c b/sys/amd64/isa/clock.c index 5cc076ee1383..d66505999b34 100644 --- a/sys/amd64/isa/clock.c +++ b/sys/amd64/isa/clock.c @@ -39,13 +39,6 @@ __FBSDID("$FreeBSD$"); * Routines to handle clock hardware. */ -/* - * inittodr, settodr and support routines written - * by Christoph Robitschko <chmr@edvz.tu-graz.ac.at> - * - * reintroduced and updated by Chris Stenton <chris@gnome.co.uk> 8/10/94 - */ - #include "opt_clock.h" #include "opt_isa.h" @@ -62,7 +55,6 @@ __FBSDID("$FreeBSD$"); #include <sys/module.h> #include <sys/sched.h> #include <sys/sysctl.h> -#include <sys/cons.h> #include <machine/clock.h> #include <machine/cpu.h> @@ -78,13 +70,6 @@ __FBSDID("$FreeBSD$"); #include <isa/isavar.h> #endif -/* - * 32-bit time_t's can't reach leap years before 1904 or after 2036, so we - * can use a simple formula for leap years. - */ -#define LEAPYEAR(y) (((u_int)(y) % 4 == 0) ? 1 : 0) -#define DAYSPERYEAR (31+28+31+30+31+30+31+31+30+31+30+31) - #define TIMER_DIV(x) ((i8254_freq + (x) / 2) / (x)) int clkintr_pending; @@ -98,20 +83,14 @@ u_int i8254_freq = TIMER_FREQ; TUNABLE_INT("hw.i8254.freq", &i8254_freq); int i8254_max_count; static int i8254_real_max_count; -#define RTC_LOCK mtx_lock_spin(&clock_lock) -#define RTC_UNLOCK mtx_unlock_spin(&clock_lock) -static struct mtx clock_lock; -static const u_char daysinmonth[] = {31,28,31,30,31,30,31,31,30,31,30,31}; +struct mtx clock_lock; static struct intsrc *i8254_intsrc; static u_int32_t i8254_lastcount; static u_int32_t i8254_offset; static int (*i8254_pending)(struct intsrc *); static int i8254_ticked; static int using_lapic_timer; -static int rtc_reg = -1; -static u_char rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF; -static u_char rtc_statusb = RTCSB_24HR; /* Values for timerX_state: */ #define RELEASED 0 @@ -239,19 +218,6 @@ rtcintr(struct trapframe *frame) return(flag ? FILTER_HANDLED : FILTER_STRAY); } -#include "opt_ddb.h" -#ifdef DDB -#include <ddb/ddb.h> - -DB_SHOW_COMMAND(rtc, rtc) -{ - printf("%02x/%02x/%02x %02x:%02x:%02x, A = %02x, B = %02x, C = %02x\n", - rtcin(RTC_YEAR), rtcin(RTC_MONTH), rtcin(RTC_DAY), - rtcin(RTC_HRS), rtcin(RTC_MIN), rtcin(RTC_SEC), - rtcin(RTC_STATUSA), rtcin(RTC_STATUSB), rtcin(RTC_INTR)); -} -#endif /* DDB */ - static int getit(void) { @@ -386,50 +352,6 @@ DELAY(int n) #endif } -/* - * RTC support routines - */ - -int -rtcin(reg) - int reg; -{ - u_char val; - - RTC_LOCK; - if (rtc_reg != reg) { - inb(0x84); - outb(IO_RTC, reg); - rtc_reg = reg; - inb(0x84); - } - val = inb(IO_RTC + 1); - RTC_UNLOCK; - return (val); -} - -void -writertc(int reg, u_char val) -{ - - RTC_LOCK; - if (rtc_reg != reg) { - inb(0x84); - outb(IO_RTC, reg); - rtc_reg = reg; - inb(0x84); - } - outb(IO_RTC + 1, val); - inb(0x84); - RTC_UNLOCK; -} - -static __inline int -readrtc(int port) -{ - return(bcd2bin(rtcin(port))); -} - static void set_i8254_freq(u_int freq, int intr_freq) { @@ -468,8 +390,7 @@ void startrtclock() { - writertc(RTC_STATUSA, rtc_statusa); - writertc(RTC_STATUSB, RTCSB_24HR); + atrtc_start(); set_i8254_freq(i8254_freq, hz); tc_init(&i8254_timecounter); @@ -478,140 +399,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) -{ - unsigned long sec, days; - int year, month; - int y, m, s; - struct timespec ts; - - 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)) - goto wrong_time; - - /* 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(); - } - - days = 0; -#ifdef USE_RTC_CENTURY - year = readrtc(RTC_YEAR) + readrtc(RTC_CENTURY) * 100; -#else - year = readrtc(RTC_YEAR) + 1900; - if (year < 1970) - year += 100; -#endif - if (year < 1970) { - splx(s); - goto wrong_time; - } - month = readrtc(RTC_MONTH); - for (m = 1; m < month; m++) - days += daysinmonth[m-1]; - if ((month > 2) && LEAPYEAR(year)) - days ++; - days += readrtc(RTC_DAY) - 1; - for (y = 1970; y < year; y++) - days += DAYSPERYEAR + LEAPYEAR(y); - sec = ((( days * 24 + - readrtc(RTC_HRS)) * 60 + - readrtc(RTC_MIN)) * 60 + - readrtc(RTC_SEC)); - /* sec now contains the number of seconds, since Jan 1 1970, - in the local time zone */ - - sec += utc_offset(); - - y = time_second - sec; - if (y <= -2 || y >= 2) { - /* badly off, adjust it */ - ts.tv_sec = sec; - ts.tv_nsec = 0; - tc_setclock(&ts); - } - splx(s); - return; - -wrong_time: - printf("Invalid time in clock: check and reset the date!\n"); -} - -/* - * Write system time back to RTC - */ -void -resettodr() -{ - unsigned long tm; - int y, m, s; - - if (disable_rtc_set) - return; - - s = splclock(); - tm = time_second; - splx(s); - - /* Disable RTC updates and interrupts. */ - writertc(RTC_STATUSB, RTCSB_HALT | RTCSB_24HR); - - /* Calculate local time to put in RTC */ - - tm -= utc_offset(); - - writertc(RTC_SEC, bin2bcd(tm%60)); tm /= 60; /* Write back Seconds */ - writertc(RTC_MIN, bin2bcd(tm%60)); tm /= 60; /* Write back Minutes */ - writertc(RTC_HRS, bin2bcd(tm%24)); tm /= 24; /* Write back Hours */ - - /* We have now the days since 01-01-1970 in tm */ - writertc(RTC_WDAY, (tm + 4) % 7 + 1); /* Write back Weekday */ - for (y = 1970, m = DAYSPERYEAR + LEAPYEAR(y); - tm >= m; - y++, m = DAYSPERYEAR + LEAPYEAR(y)) - tm -= m; - - /* Now we have the years in y and the day-of-the-year in tm */ - writertc(RTC_YEAR, bin2bcd(y%100)); /* Write back Year */ -#ifdef USE_RTC_CENTURY - writertc(RTC_CENTURY, bin2bcd(y/100)); /* ... and Century */ -#endif - for (m = 0; ; m++) { - int ml; - - ml = daysinmonth[m]; - if (m == 1 && LEAPYEAR(y)) - ml++; - if (tm < ml) - break; - tm -= ml; - } - - writertc(RTC_MONTH, bin2bcd(m + 1)); /* Write back Month */ - writertc(RTC_DAY, bin2bcd(tm + 1)); /* Write back Month Day */ - - /* Reenable RTC updates and interrupts. */ - writertc(RTC_STATUSB, rtc_statusb); - rtcin(RTC_INTR); -} - - -/* * Start both clocks running. */ void @@ -627,8 +414,8 @@ cpu_initclocks() * timecounter to user a simpler algorithm. */ if (!using_lapic_timer) { - intr_add_handler("clk", 0, (driver_filter_t *)clkintr, NULL, NULL, - INTR_TYPE_CLK, NULL); + intr_add_handler("clk", 0, (driver_filter_t *)clkintr, NULL, + NULL, INTR_TYPE_CLK, NULL); i8254_intsrc = intr_lookup_source(0); if (i8254_intsrc != NULL) i8254_pending = @@ -641,8 +428,7 @@ cpu_initclocks() } /* Initialize RTC. */ - writertc(RTC_STATUSA, rtc_statusa); - writertc(RTC_STATUSB, RTCSB_24HR); + atrtc_start(); /* * If the separate statistics clock hasn't been explicility disabled @@ -653,19 +439,18 @@ 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; profhz = RTC_PROFRATE; /* 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); - rtcin(RTC_INTR); + atrtc_enable_intr(); } init_TSC_tc(); @@ -677,8 +462,7 @@ cpu_startprofclock(void) if (using_lapic_timer) return; - rtc_statusa = RTCSA_DIVIDER | RTCSA_PROF; - writertc(RTC_STATUSA, rtc_statusa); + atrtc_rate(RTCSA_PROF); psdiv = pscnt = psratio; } @@ -688,8 +472,7 @@ cpu_stopprofclock(void) if (using_lapic_timer) return; - rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF; - writertc(RTC_STATUSA, rtc_statusa); + atrtc_rate(RTCSA_NOPROF); psdiv = pscnt = 1; } @@ -738,7 +521,8 @@ i8254_get_timecount(struct timecounter *tc) count = i8254_max_count - ((high << 8) | low); if (count < i8254_lastcount || (!i8254_ticked && (clkintr_pending || - ((count < 20 || (!(rflags & PSL_I) && count < i8254_max_count / 2u)) && + ((count < 20 || (!(rflags & PSL_I) && + count < i8254_max_count / 2u)) && i8254_pending != NULL && i8254_pending(i8254_intsrc))))) { i8254_ticked = 1; i8254_offset += i8254_max_count; @@ -751,11 +535,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 } }; @@ -764,7 +547,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); } @@ -781,8 +565,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 } }; diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64 index 782890be02cd..a17f17616489 100644 --- a/sys/conf/files.amd64 +++ b/sys/conf/files.amd64 @@ -207,9 +207,12 @@ dev/syscons/scvgarndr.c optional sc vga dev/syscons/scvtb.c optional sc dev/uart/uart_cpu_amd64.c optional uart dev/wpi/if_wpi.c optional wpi +isa/atrtc.c standard isa/syscons_isa.c optional sc isa/vga_isa.c optional vga +kern/clock_if.m standard kern/link_elf_obj.c standard +kern/subr_rtc.c standard # # IA32 binary support # diff --git a/sys/conf/files.i386 b/sys/conf/files.i386 index b123b8d1e8be..f2de73588228 100644 --- a/sys/conf/files.i386 +++ b/sys/conf/files.i386 @@ -443,6 +443,7 @@ i4b/layer1/itjc/i4b_itjc_isac.c optional itjc i4b/layer1/itjc/i4b_itjc_l1.c optional itjc i4b/layer1/itjc/i4b_itjc_l1fsm.c optional itjc # +isa/atrtc.c standard isa/syscons_isa.c optional sc isa/vga_isa.c optional vga kern/clock_if.m standard diff --git a/sys/dev/acpi_support/acpi_ibm.c b/sys/dev/acpi_support/acpi_ibm.c index 5d7036d079ff..627bcd067584 100644 --- a/sys/dev/acpi_support/acpi_ibm.c +++ b/sys/dev/acpi_support/acpi_ibm.c @@ -48,7 +48,7 @@ __FBSDID("$FreeBSD$"); #include <dev/acpica/acpivar.h> #include <dev/led/led.h> #include <sys/sysctl.h> -#include <machine/clock.h> +#include <isa/rtc.h> #define _COMPONENT ACPI_OEM ACPI_MODULE_NAME("IBM") diff --git a/sys/dev/fb/vga.c b/sys/dev/fb/vga.c index 9383e0a0a768..425aec296ccf 100644 --- a/sys/dev/fb/vga.c +++ b/sys/dev/fb/vga.c @@ -154,7 +154,7 @@ vga_mmap(struct cdev *dev, vga_softc_t *sc, vm_offset_t offset, vm_offset_t *pad /* LOW-LEVEL */ -#include <machine/clock.h> +#include <isa/rtc.h> #ifdef __i386__ #include <machine/pc/vesa.h> #endif diff --git a/sys/dev/nvram/nvram.c b/sys/dev/nvram/nvram.c index fde9d8850ae5..12b6cd431e55 100644 --- a/sys/dev/nvram/nvram.c +++ b/sys/dev/nvram/nvram.c @@ -35,7 +35,6 @@ #include <sys/uio.h> #include <sys/module.h> -#include <machine/clock.h> #include <isa/rtc.h> /* diff --git a/sys/i386/include/clock.h b/sys/i386/include/clock.h index f938e5869308..3817e32d3ec0 100644 --- a/sys/i386/include/clock.h +++ b/sys/i386/include/clock.h @@ -27,8 +27,6 @@ void i8254_init(void); * Driver to clock driver interface. */ -int rtcin(int reg); -void writertc(int reg, unsigned char val); void timer_restore(void); void init_TSC(void); void init_TSC_tc(void); diff --git a/sys/i386/isa/clock.c b/sys/i386/isa/clock.c index 6573b373f1f1..3c44baf37c36 100644 --- a/sys/i386/isa/clock.c +++ b/sys/i386/isa/clock.c @@ -39,13 +39,6 @@ __FBSDID("$FreeBSD$"); * Routines to handle clock hardware. */ -/* - * inittodr, settodr and support routines written - * by Christoph Robitschko <chmr@edvz.tu-graz.ac.at> - * - * reintroduced and updated by Chris Stenton <chris@gnome.co.uk> 8/10/94 - */ - #include "opt_apic.h" #include "opt_clock.h" #include "opt_isa.h" @@ -100,19 +93,14 @@ u_int i8254_freq = TIMER_FREQ; TUNABLE_INT("hw.i8254.freq", &i8254_freq); int i8254_max_count; static int i8254_real_max_count; -#define RTC_LOCK mtx_lock_spin(&clock_lock) -#define RTC_UNLOCK mtx_unlock_spin(&clock_lock) -static struct mtx clock_lock; +struct mtx clock_lock; static struct intsrc *i8254_intsrc; static u_int32_t i8254_lastcount; static u_int32_t i8254_offset; static int (*i8254_pending)(struct intsrc *); static int i8254_ticked; static int using_lapic_timer; -static int rtc_reg = -1; -static u_char rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF; -static u_char rtc_statusb = RTCSB_24HR; /* Values for timerX_state: */ #define RELEASED 0 @@ -230,8 +218,10 @@ timer_spkr_setfreq(int freq) static int rtcintr(struct trapframe *frame) { + int flag = 0; while (rtcin(RTC_INTR) & RTCIR_PERIOD) { + flag = 1; if (profprocs != 0) { if (--pscnt == 0) pscnt = psdiv; @@ -240,22 +230,9 @@ rtcintr(struct trapframe *frame) if (pscnt == psdiv) statclock(TRAPF_USERMODE(frame)); } - return (FILTER_HANDLED); + return(flag ? FILTER_HANDLED : FILTER_STRAY); } -#include "opt_ddb.h" -#ifdef DDB -#include <ddb/ddb.h> - -DB_SHOW_COMMAND(rtc, rtc) -{ - printf("%02x/%02x/%02x %02x:%02x:%02x, A = %02x, B = %02x, C = %02x\n", - rtcin(RTC_YEAR), rtcin(RTC_MONTH), rtcin(RTC_DAY), - rtcin(RTC_HRS), rtcin(RTC_MIN), rtcin(RTC_SEC), - rtcin(RTC_STATUSA), rtcin(RTC_STATUSB), rtcin(RTC_INTR)); -} -#endif /* DDB */ - static int getit(void) { @@ -390,49 +367,6 @@ DELAY(int n) #endif } -/* - * RTC support routines - */ - -int -rtcin(int reg) -{ - u_char val; - - RTC_LOCK; - if (rtc_reg != reg) { - inb(0x84); - outb(IO_RTC, reg); - rtc_reg = reg; - inb(0x84); - } - val = inb(IO_RTC + 1); - RTC_UNLOCK; - return (val); -} - -void -writertc(int reg, u_char val) -{ - - RTC_LOCK; - if (rtc_reg != reg) { - inb(0x84); - outb(IO_RTC, reg); - rtc_reg = reg; - inb(0x84); - } - outb(IO_RTC + 1, val); - inb(0x84); - RTC_UNLOCK; -} - -static __inline int -readrtc(int port) -{ - return(bcd2bin(rtcin(port))); -} - static void set_i8254_freq(u_int freq, int intr_freq) { @@ -469,19 +403,6 @@ i8254_restore(void) mtx_unlock_spin(&clock_lock); } -static void -rtc_restore(void) -{ - - /* Restore all of the RTC's "status" (actually, control) registers. */ - /* XXX locking is needed for RTC access. */ - rtc_reg = -1; - writertc(RTC_STATUSB, RTCSB_24HR); - writertc(RTC_STATUSA, rtc_statusa); - writertc(RTC_STATUSB, rtc_statusb); - rtcin(RTC_INTR); -} - /* * Restore all the timers non-atomically (XXX: should be atomically). * @@ -494,7 +415,7 @@ timer_restore(void) { i8254_restore(); /* restore i8254_freq and hz */ - rtc_restore(); /* reenable RTC interrupts */ + atrtc_restore(); /* reenable RTC interrupts */ } /* This is separate from startrtclock() so that it can be called early. */ @@ -510,8 +431,7 @@ void startrtclock() { - writertc(RTC_STATUSA, rtc_statusa); - writertc(RTC_STATUSB, RTCSB_24HR); + atrtc_start(); set_i8254_freq(i8254_freq, hz); tc_init(&i8254_timecounter); @@ -551,8 +471,7 @@ cpu_initclocks() } /* Initialize RTC. */ - writertc(RTC_STATUSA, rtc_statusa); - writertc(RTC_STATUSB, RTCSB_24HR); + atrtc_start(); /* * If the separate statistics clock hasn't been explicility disabled @@ -571,13 +490,10 @@ cpu_initclocks() profhz = RTC_PROFRATE; /* Enable periodic interrupts from the RTC. */ - rtc_statusb |= RTCSB_PINTR; intr_add_handler("rtc", 8, (driver_filter_t *)rtcintr, NULL, NULL, INTR_TYPE_CLK, NULL); - - writertc(RTC_STATUSB, rtc_statusb); - rtcin(RTC_INTR); + atrtc_enable_intr(); } init_TSC_tc(); @@ -589,8 +505,7 @@ cpu_startprofclock(void) if (using_lapic_timer) return; - rtc_statusa = RTCSA_DIVIDER | RTCSA_PROF; - writertc(RTC_STATUSA, rtc_statusa); + atrtc_rate(RTCSA_PROF); psdiv = pscnt = psratio; } @@ -600,8 +515,7 @@ cpu_stopprofclock(void) if (using_lapic_timer) return; - rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF; - writertc(RTC_STATUSA, rtc_statusa); + atrtc_rate(RTCSA_NOPROF); psdiv = pscnt = 1; } @@ -711,159 +625,3 @@ 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 */ |