From cb2cd8b2556239b462759c4c0b04aec253835bc1 Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Wed, 25 Jun 2025 20:39:28 -0400 Subject: kernel/amd64: mc1468xx: Implement date setting Implement logic to update the date returned by the MC1468XX/RTC chip. This can be used to later implement some sort of time synchronization protocol or manual setting of the date. Signed-off-by: Ian Moffett --- sys/arch/amd64/isa/mc1468.c | 67 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) (limited to 'sys') diff --git a/sys/arch/amd64/isa/mc1468.c b/sys/arch/amd64/isa/mc1468.c index 5e8b32f..bbaa3d1 100644 --- a/sys/arch/amd64/isa/mc1468.c +++ b/sys/arch/amd64/isa/mc1468.c @@ -50,6 +50,29 @@ static struct cdevsw mc1468_cdevsw; +static uint8_t +bin_dabble(uint8_t bin) +{ + uint8_t retval = 0; + uint8_t nibble; + + for (int i = 7; i >= 0; --i) { + retval <<= 1; + if (bin & (1 << i)) { + retval |= 1; + } + + for (int j = 0; j < 2; ++j) { + nibble = retval & (retval >> (4 * nibble)) & 0x0F; + if (nibble >= 5) { + retval += 0x03 << (4 * nibble); + } + } + } + + return retval; +} + /* * Read a byte from an MC1468XX register. */ @@ -60,6 +83,16 @@ mc1468_read(uint8_t reg) return inb(MC1468_DATA); } +/* + * Write a byte to the MC1468XX register. + */ +static void +mc1468_write(uint8_t reg, uint8_t val) +{ + outb(MC1468_REGSEL, reg); + outb(MC1468_DATA, val); +} + /* * Returns true if the MC1468XX is updating * its time registers. @@ -134,6 +167,23 @@ __mc1468_get_time(struct date *dp) dp->hour = mc1468_read(0x04); } +/* + * Write a new time/date to the chip. + */ +static void +mc1468_set_date(const struct date *dp) +{ + while (mc1468_updating()) { + md_pause(); + } + + mc1468_write(0x08, bin_dabble(dp->month)); + mc1468_write(0x07, bin_dabble(dp->day)); + mc1468_write(0x04, bin_dabble(dp->hour)); + mc1468_write(0x02, bin_dabble(dp->min)); + mc1468_write(0x00, bin_dabble(dp->sec)); +} + static int mc1468_get_date(struct date *dp) { @@ -194,6 +244,21 @@ mc1468_dev_read(dev_t dev, struct sio_txn *sio, int flags) return sio->len; } +static int +mc1468_dev_write(dev_t dev, struct sio_txn *sio, int flags) +{ + struct date d; + size_t len = sizeof(d); + + if (sio->len > len) { + sio->len = len; + } + + memcpy(&d, sio->buf, sio->len); + mc1468_set_date(&d); + return sio->len; +} + static int mc1468_init(void) { @@ -210,7 +275,7 @@ mc1468_init(void) static struct cdevsw mc1468_cdevsw = { .read = mc1468_dev_read, - .write = nowrite + .write = mc1468_dev_write, }; DRIVER_EXPORT(mc1468_init); -- cgit v1.2.3