Add static inline rtcin_locked() and rtcout_locked() functions for doing a

related series of operations without doing a lock/unlock for each byte.
Use them when reading and writing the entire set of time registers.

The original rtcin() and writertc() functions which do lock/unlock on each
byte still exist, because they are public and called by outside code.
This commit is contained in:
Ian Lepore 2018-01-16 03:02:41 +00:00
parent e170090541
commit e5ef01427c

View File

@ -76,19 +76,40 @@ static u_char rtc_statusb = RTCSB_24HR;
* RTC support routines * RTC support routines
*/ */
int static inline u_char
rtcin(int reg) rtcin_locked(int reg)
{ {
u_char val;
RTC_LOCK;
if (rtc_reg != reg) { if (rtc_reg != reg) {
inb(0x84); inb(0x84);
outb(IO_RTC, reg); outb(IO_RTC, reg);
rtc_reg = reg; rtc_reg = reg;
inb(0x84); inb(0x84);
} }
val = inb(IO_RTC + 1); return (inb(IO_RTC + 1));
}
static inline void
rtcout_locked(int reg, u_char val)
{
if (rtc_reg != reg) {
inb(0x84);
outb(IO_RTC, reg);
rtc_reg = reg;
inb(0x84);
}
outb(IO_RTC + 1, val);
inb(0x84);
}
int
rtcin(int reg)
{
u_char val;
RTC_LOCK;
val = rtcin_locked(reg);
RTC_UNLOCK; RTC_UNLOCK;
return (val); return (val);
} }
@ -98,14 +119,7 @@ writertc(int reg, u_char val)
{ {
RTC_LOCK; RTC_LOCK;
if (rtc_reg != reg) { rtcout_locked(reg, val);
inb(0x84);
outb(IO_RTC, reg);
rtc_reg = reg;
inb(0x84);
}
outb(IO_RTC + 1, val);
inb(0x84);
RTC_UNLOCK; RTC_UNLOCK;
} }
@ -163,25 +177,28 @@ atrtc_set(struct timespec *ts)
clock_ts_to_bcd(ts, &ct, false); clock_ts_to_bcd(ts, &ct, false);
mtx_lock(&atrtc_time_lock); mtx_lock(&atrtc_time_lock);
RTC_LOCK;
/* Disable RTC updates and interrupts. */ /* Disable RTC updates and interrupts. */
writertc(RTC_STATUSB, RTCSB_HALT | RTCSB_24HR); rtcout_locked(RTC_STATUSB, RTCSB_HALT | RTCSB_24HR);
writertc(RTC_SEC, ct.sec); /* Write back Seconds */ /* Write all the time registers. */
writertc(RTC_MIN, ct.min); /* Write back Minutes */ rtcout_locked(RTC_SEC, ct.sec);
writertc(RTC_HRS, ct.hour); /* Write back Hours */ rtcout_locked(RTC_MIN, ct.min);
writertc(RTC_WDAY, ct.dow + 1); /* Write back Weekday */ rtcout_locked(RTC_HRS, ct.hour);
writertc(RTC_DAY, ct.day); /* Write back Day */ rtcout_locked(RTC_WDAY, ct.dow + 1);
writertc(RTC_MONTH, ct.mon); /* Write back Month */ rtcout_locked(RTC_DAY, ct.day);
writertc(RTC_YEAR, ct.year & 0xff); /* Write back Year */ rtcout_locked(RTC_MONTH, ct.mon);
rtcout_locked(RTC_YEAR, ct.year & 0xff);
#ifdef USE_RTC_CENTURY #ifdef USE_RTC_CENTURY
writertc(RTC_CENTURY, ct.year >> 8); /* ... and Century */ rtcout_locked(RTC_CENTURY, ct.year >> 8);
#endif #endif
/* Re-enable RTC updates and interrupts. */ /* Re-enable RTC updates and interrupts. */
writertc(RTC_STATUSB, rtc_statusb); rtcout_locked(RTC_STATUSB, rtc_statusb);
rtcin(RTC_INTR); rtcin_locked(RTC_INTR);
RTC_UNLOCK;
mtx_unlock(&atrtc_time_lock); mtx_unlock(&atrtc_time_lock);
} }
@ -358,15 +375,17 @@ atrtc_gettime(device_t dev, struct timespec *ts)
while (rtcin(RTC_STATUSA) & RTCSA_TUP) while (rtcin(RTC_STATUSA) & RTCSA_TUP)
continue; continue;
critical_enter(); critical_enter();
ct.sec = rtcin(RTC_SEC); RTC_LOCK;
ct.min = rtcin(RTC_MIN); ct.sec = rtcin_locked(RTC_SEC);
ct.hour = rtcin(RTC_HRS); ct.min = rtcin_locked(RTC_MIN);
ct.day = rtcin(RTC_DAY); ct.hour = rtcin_locked(RTC_HRS);
ct.mon = rtcin(RTC_MONTH); ct.day = rtcin_locked(RTC_DAY);
ct.year = rtcin(RTC_YEAR); ct.mon = rtcin_locked(RTC_MONTH);
ct.year = rtcin_locked(RTC_YEAR);
#ifdef USE_RTC_CENTURY #ifdef USE_RTC_CENTURY
ct.year |= rtcin(RTC_CENTURY) << 8; ct.year |= rtcin_locked(RTC_CENTURY) << 8;
#endif #endif
RTC_UNLOCK;
critical_exit(); critical_exit();
mtx_unlock(&atrtc_time_lock); mtx_unlock(&atrtc_time_lock);
/* dow is unused in timespec conversion and we have no nsec info. */ /* dow is unused in timespec conversion and we have no nsec info. */