--- a/sys/bus/iicbus/iicbus.c 2026-06-29 12:51:18.000000000 +0000 +++ b/sys/bus/iicbus/iicbus.c 2026-10-07 15:58:54.263534670 +0000 @@ -55,6 +55,8 @@ static int iicbus_attach(device_t); static int iicbus_detach(device_t); static int iicbus_add_child(device_t dev, int order, const char *name, int unit); +static int iicbus_read_ivar(device_t, device_t, int, uintptr_t *); +static int iicbus_write_ivar(device_t, device_t, int, uintptr_t); static device_method_t iicbus_methods[] = { /* device interface */ @@ -66,6 +68,8 @@ DEVMETHOD(bus_add_child, iicbus_add_child), DEVMETHOD(bus_driver_added, bus_generic_driver_added), DEVMETHOD(bus_print_child, bus_generic_print_child), + DEVMETHOD(bus_read_ivar, iicbus_read_ivar), + DEVMETHOD(bus_write_ivar, iicbus_write_ivar), DEVMETHOD(iicbus_transfer, iicbus_transfer_gen), @@ -191,5 +195,43 @@ return (IIC_ENOTSUPP); } +/* + * ivar accessors. Children of iicbus are created with plain + * device_add_child() (no ivars are ever allocated: iicbus_attach() + * and iicbus_add_child()), while the generated accessor + * iicbus_get_addr() (__BUS_ACCESSOR, sys/sys/bus.h) discards our + * error return -- so a failed lookup must still write a sane value + * instead of leaving the caller's uninitialized stack in place + * (consumed by iic_probe(), sys/bus/iicbus/iic.c:115). + */ +static int +iicbus_read_ivar(device_t dev, device_t child, int index, uintptr_t *result) +{ + struct iicbus_ivar *ivar = IICBUS_IVAR(child); + + switch (index) { + case IICBUS_IVAR_ADDR: + *result = (ivar != NULL) ? ivar->addr : 0; + return (0); + default: + return (ENOENT); + } +} + +static int +iicbus_write_ivar(device_t dev, device_t child, int index, uintptr_t value) +{ + struct iicbus_ivar *ivar = IICBUS_IVAR(child); + + switch (index) { + case IICBUS_IVAR_ADDR: + if (ivar != NULL) + ivar->addr = (uint32_t)value; + return (0); + default: + return (ENOENT); + } +} + DRIVER_MODULE(iicbus, iicbb, iicbus_driver, iicbus_devclass, NULL, NULL); MODULE_VERSION(iicbus, IICBUS_MODVER);