int mc146818_getsecs(device_t dev, int *secp) { struct mc146818_softc *sc; int sec, timeout; sc = device_get_softc(dev); timeout = 1000000; /* XXX how long should we wait? */ for (;;) { if (!((*sc->sc_mcread)(dev, MC_REGA) & MC_REGA_UIP)) { sec = FROMREG((*sc->sc_mcread)(dev, MC_SEC)); break; } if (--timeout == 0) { device_printf(dev, "mc146818_getsecs: timeout\n"); return (EBUSY); } } #undef FROMREG *secp = sec; return (0); }
/* * Get time of day and convert it to a struct timespec. * Return 0 on success, an error number otherwise. */ int mc146818_gettime(device_t dev, struct timespec *ts) { struct mc146818_softc *sc; struct clocktime ct; int timeout, cent, year; sc = device_get_softc(dev); timeout = 1000000; /* XXX how long should we wait? */ /* * XXX: Use a spinlock to mutex register access and increase the * likelihood that all registers are read before an update * occurs. */ /* * If MC_REGA_UIP is 0 we have at least 244us before the next * update. If it's 1 an update is imminent. */ for (;;) { if (!((*sc->sc_mcread)(dev, MC_REGA) & MC_REGA_UIP)) break; if (--timeout < 0) { device_printf(dev, "mc146818_gettime: timeout\n"); return (EBUSY); } } #define FROMREG(x) ((sc->sc_flag & MC146818_BCD) ? FROMBCD(x) : (x)) ct.nsec = 0; ct.sec = FROMREG((*sc->sc_mcread)(dev, MC_SEC)); ct.min = FROMREG((*sc->sc_mcread)(dev, MC_MIN)); ct.hour = FROMREG((*sc->sc_mcread)(dev, MC_HOUR)); ct.dow = FROMREG((*sc->sc_mcread)(dev, MC_DOW)) - 1; ct.day = FROMREG((*sc->sc_mcread)(dev, MC_DOM)); ct.mon = FROMREG((*sc->sc_mcread)(dev, MC_MONTH)); year = FROMREG((*sc->sc_mcread)(dev, MC_YEAR)); if (sc->sc_getcent) { cent = (*sc->sc_getcent)(dev); year += cent * 100; } year += sc->sc_year0; if (year < POSIX_BASE_YEAR && !(sc->sc_flag & MC146818_NO_CENT_ADJUST)) year += 100; ct.year = year; return (clock_ct_to_ts(&ct, ts)); }
/* * Get time of day and convert it to a struct timespec. * Return 0 on success, an error number otherwise. */ int mc146818_gettime(device_t dev, struct timespec *ts) { struct mc146818_softc *sc; struct clocktime ct; int timeout, cent, year; sc = device_get_softc(dev); timeout = 1000000; /* XXX how long should we wait? */ /* * If MC_REGA_UIP is 0 we have at least 244us before the next * update. If it's 1 an update is imminent. */ for (;;) { mtx_lock_spin(&sc->sc_mtx); if (!((*sc->sc_mcread)(dev, MC_REGA) & MC_REGA_UIP)) break; mtx_unlock_spin(&sc->sc_mtx); if (--timeout < 0) { device_printf(dev, "%s: timeout\n", __func__); return (EBUSY); } } #define FROMREG(x) ((sc->sc_flag & MC146818_BCD) ? FROMBCD(x) : (x)) ct.nsec = 0; ct.sec = FROMREG((*sc->sc_mcread)(dev, MC_SEC)); ct.min = FROMREG((*sc->sc_mcread)(dev, MC_MIN)); ct.hour = FROMREG((*sc->sc_mcread)(dev, MC_HOUR)); /* Map dow from 1 - 7 to 0 - 6. */ ct.dow = FROMREG((*sc->sc_mcread)(dev, MC_DOW)) - 1; ct.day = FROMREG((*sc->sc_mcread)(dev, MC_DOM)); ct.mon = FROMREG((*sc->sc_mcread)(dev, MC_MONTH)); year = FROMREG((*sc->sc_mcread)(dev, MC_YEAR)); year += sc->sc_year0; if (sc->sc_flag & MC146818_NO_CENT_ADJUST) { cent = (*sc->sc_getcent)(dev); year += cent * 100; } else if (year < POSIX_BASE_YEAR) year += 100; mtx_unlock_spin(&sc->sc_mtx); ct.year = year; return (clock_ct_to_ts(&ct, ts)); }
/* * Get time-of-day and convert to a `struct timespec' * Return 0 on success; an error number otherwise. */ int mk48txx_gettime(device_t dev, struct timespec *ts) { struct mk48txx_softc *sc; bus_size_t clkoff; struct clocktime ct; int year; uint8_t csr; sc = device_get_softc(dev); clkoff = sc->sc_clkoffset; mtx_lock(&sc->sc_mtx); /* enable read (stop time) */ csr = (*sc->sc_nvrd)(dev, clkoff + MK48TXX_ICSR); csr |= MK48TXX_CSR_READ; (*sc->sc_nvwr)(dev, clkoff + MK48TXX_ICSR, csr); #define FROMREG(reg, mask) ((*sc->sc_nvrd)(dev, clkoff + (reg)) & (mask)) ct.nsec = 0; ct.sec = FROMBCD(FROMREG(MK48TXX_ISEC, MK48TXX_SEC_MASK)); ct.min = FROMBCD(FROMREG(MK48TXX_IMIN, MK48TXX_MIN_MASK)); ct.hour = FROMBCD(FROMREG(MK48TXX_IHOUR, MK48TXX_HOUR_MASK)); ct.day = FROMBCD(FROMREG(MK48TXX_IDAY, MK48TXX_DAY_MASK)); #if 0 /* Map dow from 1 - 7 to 0 - 6; FROMBCD() isn't necessary here. */ ct.dow = FROMREG(MK48TXX_IWDAY, MK48TXX_WDAY_MASK) - 1; #else /* * Set dow = -1 because some drivers (for example the NetBSD and * OpenBSD mk48txx(4)) don't set it correctly. */ ct.dow = -1; #endif ct.mon = FROMBCD(FROMREG(MK48TXX_IMON, MK48TXX_MON_MASK)); year = FROMBCD(FROMREG(MK48TXX_IYEAR, MK48TXX_YEAR_MASK)); year += sc->sc_year0; if (sc->sc_flag & MK48TXX_NO_CENT_ADJUST) year += (FROMREG(MK48TXX_IWDAY, MK48TXX_WDAY_CB) >> MK48TXX_WDAY_CB_SHIFT) * 100; else if (year < POSIX_BASE_YEAR)