i have an m4000 that would come up saying that it was 2023, which is hard for ntpd to deal with. the rtc in these machines is based on a value the firmware manages, but we never tell the firmware what we think the time is.
this diff moves all the opl firwmare handling into the prtc driver, and adds the todr_settime side of things so the time is kept across reboots. there's a bunch of dicking around with %sys_tick we could do, but i can't see what the advantage would be. ok? Index: dev/prtc.c =================================================================== RCS file: /cvs/src/sys/arch/sparc64/dev/prtc.c,v retrieving revision 1.3 diff -u -p -r1.3 prtc.c --- dev/prtc.c 10 May 2014 12:36:22 -0000 1.3 +++ dev/prtc.c 27 Aug 2018 07:26:44 -0000 @@ -49,6 +49,9 @@ struct cfdriver prtc_cd = { int prtc_gettime(todr_chip_handle_t, struct timeval *); int prtc_settime(todr_chip_handle_t, struct timeval *); +int prtc_opl_gettime(todr_chip_handle_t, struct timeval *); +int prtc_opl_settime(todr_chip_handle_t, struct timeval *); + int prtc_match(struct device *parent, void *match, void *aux) { @@ -64,6 +67,14 @@ void prtc_attach(struct device *parent, struct device *self, void *aux) { todr_chip_handle_t handle; + char buf[32]; + int opl; + + opl = OF_getprop(findroot(), "name", buf, sizeof(buf)) > 0 && + strcmp(buf, "SUNW,SPARC-Enterprise") == 0; + + if (opl) + printf(": OPL"); printf("\n"); @@ -72,26 +83,25 @@ prtc_attach(struct device *parent, struc panic("couldn't allocate todr_handle"); handle->cookie = self; - handle->todr_gettime = prtc_gettime; - handle->todr_settime = prtc_settime; + if (opl) { + handle->todr_gettime = prtc_opl_gettime; + handle->todr_settime = prtc_opl_settime; + } else { + handle->todr_gettime = prtc_gettime; + handle->todr_settime = prtc_settime; + } handle->bus_cookie = NULL; handle->todr_setwen = NULL; + todr_handle = handle; } int prtc_gettime(todr_chip_handle_t handle, struct timeval *tv) { - u_int32_t tod = 0; char buf[32]; - - if (OF_getprop(findroot(), "name", buf, sizeof(buf)) > 0 && - strcmp(buf, "SUNW,SPARC-Enterprise") == 0) { - tv->tv_sec = prom_opl_get_tod(); - tv->tv_usec = 0; - return (0); - } + u_int32_t tod = 0; snprintf(buf, sizeof(buf), "h# %08lx unix-gettod", (long)&tod); OF_interpret(buf, 0); @@ -105,4 +115,56 @@ int prtc_settime(todr_chip_handle_t handle, struct timeval *tv) { return (0); -} +} + +int +prtc_opl_gettime(todr_chip_handle_t handle, struct timeval *tv) +{ + struct { + cell_t name; + cell_t nargs; + cell_t nrets; + cell_t stick; + cell_t time; + } args = { + .name = ADR2CELL("FJSV,get-tod"), + .nargs = 0, + .nrets = 2, + }; + + if (openfirmware(&args) == -1) + return (-1); + + tv->tv_sec = args.time; + tv->tv_usec = 0; + + return (0); +} + +int +prtc_opl_settime(todr_chip_handle_t handle, struct timeval *tv) +{ + struct timeval otv; + struct { + cell_t name; + cell_t nargs; + cell_t nrets; + cell_t diff; + } args = { + .name = ADR2CELL("FJSV,set-domain-time"), + .nargs = 1, + .nrets = 0, + }; + + if (prtc_opl_gettime(handle, &otv) == -1) + return (-1); + + args.diff = tv->tv_sec - otv.tv_sec; + if (args.diff == 0) + return (-1); + + if (openfirmware(&args) == -1) + return (-1); + + return (0); +} Index: sparc64/ofw_machdep.c =================================================================== RCS file: /cvs/src/sys/arch/sparc64/sparc64/ofw_machdep.c,v retrieving revision 1.33 diff -u -p -r1.33 ofw_machdep.c --- sparc64/ofw_machdep.c 7 Mar 2016 13:21:51 -0000 1.33 +++ sparc64/ofw_machdep.c 27 Aug 2018 07:26:44 -0000 @@ -748,27 +748,6 @@ prom_serengeti_set_console_input(const c return (const char *)args.old; } -time_t -prom_opl_get_tod(void) -{ - static struct { - cell_t name; - cell_t nargs; - cell_t nreturns; - cell_t stick; - cell_t time; - } args; - - args.name = ADR2CELL("FJSV,get-tod"); - args.nargs = 0; - args.nreturns = 2; - - if (openfirmware(&args) == -1) - return (time_t)-1; - - return (time_t)args.time; -} - uint64_t prom_set_sun4v_api_version(uint64_t api_group, uint64_t major, uint64_t minor, uint64_t *supported_minor)