From 94b815050ee014b22fbbd1a396d8d22a76ba0958 Mon Sep 17 00:00:00 2001 From: augustss Date: Sat, 26 Jun 1999 08:25:25 +0000 Subject: [PATCH] Add powerhooks, i.e., the ability to register a function that will be called when the machine does a suspend or resume. XXX Will go away when Jason's kevents come to life. --- sys/arch/i386/i386/apm.c | 28 +++++++++++------ sys/kern/kern_subr.c | 68 +++++++++++++++++++++++++++++++++++++++- sys/sys/systm.h | 12 ++++++- 3 files changed, 97 insertions(+), 11 deletions(-) diff --git a/sys/arch/i386/i386/apm.c b/sys/arch/i386/i386/apm.c index f9b9e0b57094..715ea22faa85 100644 --- a/sys/arch/i386/i386/apm.c +++ b/sys/arch/i386/i386/apm.c @@ -1,4 +1,4 @@ -/* $NetBSD: apm.c,v 1.38 1999/03/19 04:58:46 cgd Exp $ */ +/* $NetBSD: apm.c,v 1.39 1999/06/26 08:25:25 augustss Exp $ */ /*- * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc. @@ -142,6 +142,7 @@ static void apm_set_ver __P((struct apm_softc *)); static void apm_standby __P((void)); static const char *apm_strerror __P((int)); static void apm_suspend __P((void)); +static void apm_resume __P((struct apm_softc *, struct bioscallregs *)); cdev_decl(apm); @@ -348,6 +349,7 @@ apm_get_powstate(dev) static void apm_suspend() { + dopowerhooks(PWR_SUSPEND); /* XXX cgd */ (void)apm_set_powstate(APM_DEV_ALLDEVS, APM_SYS_SUSPEND); @@ -356,11 +358,22 @@ apm_suspend() static void apm_standby() { + dopowerhooks(PWR_STANDBY); /* XXX cgd */ (void)apm_set_powstate(APM_DEV_ALLDEVS, APM_SYS_STANDBY); } +static void +apm_resume(sc, regs) + struct apm_softc *sc; + struct bioscallregs *regs; +{ + inittodr(time.tv_sec); + dopowerhooks(PWR_RESUME); + apm_record_event(sc, regs->BX); +} + /* * return 0 if the user will notice and handle the event, * return 1 if the kernel driver should do so. @@ -467,26 +480,22 @@ apm_event_handle(sc, regs) case APM_NORMAL_RESUME: DPRINTF(APMDEBUG_EVENTS, ("apmev: resume system\n")); - inittodr(time.tv_sec); - apm_record_event(sc, regs->BX); + apm_resume(sc, regs); break; case APM_CRIT_RESUME: DPRINTF(APMDEBUG_EVENTS, ("apmev: critical resume system")); - inittodr(time.tv_sec); - apm_record_event(sc, regs->BX); + apm_resume(sc, regs); break; case APM_SYS_STANDBY_RESUME: DPRINTF(APMDEBUG_EVENTS, ("apmev: system standby resume\n")); - inittodr(time.tv_sec); - apm_record_event(sc, regs->BX); + apm_resume(sc, regs); break; case APM_UPDATE_TIME: DPRINTF(APMDEBUG_EVENTS, ("apmev: update time\n")); - inittodr(time.tv_sec); - apm_record_event(sc, regs->BX); + apm_resume(sc, regs); break; case APM_CRIT_SUSPEND_REQ: @@ -604,6 +613,7 @@ apm_set_powstate(dev, state) struct bioscallregs regs; if (!apm_inited || (apm_minver == 0 && state > APM_SYS_OFF)) return EINVAL; + regs.BX = dev; regs.CX = state; if (apmcall(APM_SET_PWR_STATE, ®s) != 0) { diff --git a/sys/kern/kern_subr.c b/sys/kern/kern_subr.c index 27720327ccaf..b1ac43f5f5a2 100644 --- a/sys/kern/kern_subr.c +++ b/sys/kern/kern_subr.c @@ -1,4 +1,4 @@ -/* $NetBSD: kern_subr.c,v 1.51 1999/06/07 20:16:09 thorpej Exp $ */ +/* $NetBSD: kern_subr.c,v 1.52 1999/06/26 08:25:25 augustss Exp $ */ /*- * Copyright (c) 1997, 1998, 1999 The NetBSD Foundation, Inc. @@ -314,6 +314,72 @@ doshutdownhooks() } } +/* + * "Power hook" types, functions, and variables. + */ + +struct powerhook_desc { + LIST_ENTRY(powerhook_desc) sfd_list; + void (*sfd_fn) __P((int, void *)); + void *sfd_arg; +}; + +LIST_HEAD(, powerhook_desc) powerhook_list; + +void * +powerhook_establish(fn, arg) + void (*fn) __P((int, void *)); + void *arg; +{ + struct powerhook_desc *ndp; + + ndp = (struct powerhook_desc *) + malloc(sizeof(*ndp), M_DEVBUF, M_NOWAIT); + if (ndp == NULL) + return NULL; + + ndp->sfd_fn = fn; + ndp->sfd_arg = arg; + LIST_INSERT_HEAD(&powerhook_list, ndp, sfd_list); + + return (ndp); +} + +void +powerhook_disestablish(vhook) + void *vhook; +{ +#ifdef DIAGNOSTIC + struct powerhook_desc *dp; + + for (dp = powerhook_list.lh_first; dp != NULL; + dp = dp->sfd_list.le_next) + if (dp == vhook) + break; + if (dp == NULL) + panic("powerhook_disestablish: hook not established"); +#endif + + LIST_REMOVE((struct powerhook_desc *)vhook, sfd_list); + free(vhook, M_DEVBUF); +} + +/* + * Run power hooks. + */ +void +dopowerhooks(why) + int why; +{ + struct powerhook_desc *dp; + + for (dp = LIST_FIRST(&powerhook_list); + dp != NULL; + dp = LIST_NEXT(dp, sfd_list)) { + (*dp->sfd_fn)(why, dp->sfd_arg); + } +} + /* * "Mountroot hook" types, functions, and variables. */ diff --git a/sys/sys/systm.h b/sys/sys/systm.h index e36fad209858..a2881b7fc9e2 100644 --- a/sys/sys/systm.h +++ b/sys/sys/systm.h @@ -1,4 +1,4 @@ -/* $NetBSD: systm.h,v 1.91 1999/05/20 05:53:34 lukem Exp $ */ +/* $NetBSD: systm.h,v 1.92 1999/06/26 08:25:26 augustss Exp $ */ /*- * Copyright (c) 1982, 1988, 1991, 1993 @@ -266,6 +266,16 @@ void *shutdownhook_establish __P((void (*)(void *), void *)); void shutdownhook_disestablish __P((void *)); void doshutdownhooks __P((void)); +/* + * Power managment hooks. + */ +void *powerhook_establish __P((void (*)(int, void *), void *)); +void powerhook_disestablish __P((void *)); +void dopowerhooks __P((int)); +#define PWR_RESUME 0 +#define PWR_SUSPEND 1 +#define PWR_STANDBY 2 + /* * Mountroot hooks. Device drivers establish these to be executed * just before (*mountroot)() if the passed device is selected