--- src/sys/kern/kern_todr.c.dist 2026-01-23 16:30:48.189998898 +0100 +++ src/sys/kern/kern_todr.c 2026-06-01 16:49:35.249972477 +0200 @@ -78,6 +78,7 @@ #include #include #include +#include #include #include #include @@ -86,11 +87,17 @@ #include /* hmm.. this should probably move to sys */ +struct todr_list { + todr_chip_handle_t todr_handle; + struct todr_list *todr_next; +}; + static int todr_gettime(todr_chip_handle_t, struct timeval *); static int todr_settime(todr_chip_handle_t, struct timeval *); static kmutex_t todr_mutex; -static todr_chip_handle_t todr_handle; +static struct todr_list todr_head = + { .todr_handle = NULL, .todr_next = NULL }; static bool todr_initialized; /* The minimum reasonable RTC date before preposterousness */ @@ -179,6 +186,7 @@ void todr_attach(todr_chip_handle_t todr) { + struct todr_list *todr_newp, *todr_iterp; /* * todr_init() is called very early in main(), but this is @@ -191,14 +199,24 @@ return; } - todr_lock(); - if (todr_handle) { + /* Initial entry is static, others allocated. */ + if (todr_head.todr_handle == NULL) { + todr_lock(); + todr_head.todr_handle = todr; todr_unlock(); - printf("todr_attach: TOD already configured\n"); - return; + } else { + todr_newp = kmem_alloc(sizeof(struct todr_list), + KM_SLEEP); + todr_newp->todr_next = NULL; + todr_lock(); + todr_newp->todr_handle = todr; + todr_iterp = &todr_head; + while (todr_iterp->todr_next != NULL) + todr_iterp = todr_iterp->todr_next; + todr_iterp->todr_next = todr_newp; + todr_unlock(); + printf("%s: secondary clock\n", device_xname(todr->todr_dev)); } - todr_handle = todr; - todr_unlock(); } static bool timeset = false; @@ -217,7 +235,10 @@ bool goodtime = false; bool badrtc = false; struct timespec ts; - struct timeval tv; + struct timeval tv, tv2; + struct todr_list *todr_iterp; + device_t t_dev; + time_t deltat; KASSERT(todr_lock_owned()); @@ -246,22 +267,23 @@ /* * Some ports need to be supplied base in order to fabricate a time_t. */ - if (todr_handle) - todr_handle->todr_base_time = base; + if (todr_head.todr_handle != NULL) + todr_head.todr_handle->todr_base_time = base; memset(&tv, 0, sizeof(tv)); - if ((todr_handle == NULL) || - (todr_gettime(todr_handle, &tv) != 0) || + /* Note, that we use the first RTC for system time. */ + if ((todr_head.todr_handle == NULL) || + (todr_gettime(todr_head.todr_handle, &tv) != 0) || (tv.tv_sec < (PREPOSTEROUS_YEARS * SECS_PER_COMMON_YEAR))) { - if (todr_handle != NULL) + if (todr_head.todr_handle != NULL) printf("WARNING: preposterous TOD clock time\n"); else printf("WARNING: no TOD clock present\n"); badrtc = true; } else { - time_t deltat = tv.tv_sec - base; + deltat = tv.tv_sec - base; if (deltat < 0) deltat = -deltat; @@ -301,6 +323,29 @@ tv.tv_usec = 0; } + /* Check other clocks, if any, against our time */ + todr_iterp = &todr_head; + while ((todr_iterp = todr_iterp->todr_next) != NULL) { + if ((todr_iterp->todr_handle == NULL) || + (todr_gettime(todr_iterp->todr_handle, &tv2) != 0)) + continue; + t_dev = todr_iterp->todr_handle->todr_dev; + if (tv2.tv_sec < (PREPOSTEROUS_YEARS * SECS_PER_COMMON_YEAR)) { + printf("WARNING: preposterous %s clock time\n", + device_xname(t_dev)); + deltat = 0; + } else { + deltat = tv.tv_sec - tv2.tv_sec; + rnd_add_data(NULL, &tv, sizeof(tv), 0); + } + if (deltat < -10) + printf("WARNING: %s clock lost %" PRId64 " seconds\n", + device_xname(t_dev), deltat); + if (deltat > 10) + printf("WARNING: %s clock gained %" PRId64 " seconds\n", + device_xname(t_dev), deltat); + } + timeset = true; ts.tv_sec = tv.tv_sec; @@ -315,13 +360,14 @@ /* * todr_save_systime: - * Save the current system time back to the TOD clock. + * Save the current system time back to the TOD clock(s). * Must be called with the TODR lock held. */ void todr_save_systime(void) { struct timeval tv; + struct todr_list *todr_iterp; KASSERT(todr_lock_owned()); @@ -338,9 +384,14 @@ if (tv.tv_sec == 0) return; - if (todr_handle) - if (todr_settime(todr_handle, &tv) != 0) - printf("Cannot set TOD clock time\n"); + todr_iterp = &todr_head; + do { + if ((todr_iterp->todr_handle != NULL) && + (todr_settime(todr_iterp->todr_handle, &tv) != 0)) + printf("Cannot set %s TOD clock time\n", + device_xname(todr_iterp->todr_handle->todr_dev)); + todr_iterp = todr_iterp->todr_next; + } while (todr_iterp != NULL); } /* --- src/sys/arch/sparc64/conf/GENERIC.dist 2026-06-04 15:59:46.000000000 +0200 +++ src/sys/arch/sparc64/conf/GENERIC 2026-06-04 16:01:00.229974214 +0200 @@ -840,6 +840,7 @@ seeprom* at iic? addr? # i2c-at24c64 fru's pcagpio* at iic? addr? # V210/V240 GPIO's pcf8574io* at iic? addr? # E250 GPIO's +dsrtc* at iic? addr? # RSC clock found on V210/V240 ### Other pseudo-devices --- src/sys/dev/pci/radeonfb.c.dist 2026-05-26 15:53:49.079974471 +0200 +++ src/sys/dev/pci/radeonfb.c 2026-05-26 15:52:52.889974505 +0200 @@ -463,6 +463,7 @@ pcireg_t screg; int i, j, fg, bg, ul, flags; uint32_t v; + char memstr[16] = ""; sc->sc_dev = dev; sc->sc_id = pa->pa_id; @@ -654,8 +655,10 @@ radeonfb_set_fbloc(sc); /* 64 MB should be enough -- more just wastes map entries */ - if (sc->sc_memsz > (64 << 20)) + if (sc->sc_memsz > (64 << 20)) { + snprintf(memstr, 16, " %d MB,", (int)sc->sc_memsz >> 20); sc->sc_memsz = (64 << 20); + } for (i = 0; radeonfb_limits[i].size; i++) { if (sc->sc_memsz >= radeonfb_limits[i].size) { @@ -806,8 +809,8 @@ goto error; } - aprint_normal("%s: %d MB aperture at 0x%08x, " - "%d KB registers at 0x%08x\n", XNAME(sc), + aprint_normal("%s:%s %d MB aperture at 0x%08x, " + "%d KB registers at 0x%08x\n", XNAME(sc), memstr, (int)sc->sc_memsz >> 20, (unsigned)sc->sc_memaddr, (int)sc->sc_regsz >> 10, (unsigned)sc->sc_regaddr);