> Date: Sun, 16 Oct 2022 11:48:56 -0400 > From: George Koehler <kern...@gmail.com> > > This diff will add a few features to the macppc kernel: > > - sysctl hw.power will be set to 0 or 1 when I unplug or plug in > my PowerBook's AC adapter. > - sysctl machdep.lidaction and machdep.pwraction will exist. > - The default machdep.pwraction=1 will power off my macppc when I > push the power button. > - The default machdep.lidaction=1 should suspend, but will do > nothing, because suspend is not yet implemented. > - PowerBooks and iBooks will have a lid sensor, which looks like > > $ sysctl hw.sensors > hw.sensors.adb0.indicator0=On (lid open) > > machdep.{lid,pwr}action are documented in acpi(4), but macppcs > don't have acpi. This diff doesn't change any manuals. To access > the new sysctls, I needed to build a kernel, install the kernel's > includes, and build sysctl(8). machdep.pwraction=0 will disable the > power button, which I might do on my Cube G4, where I sometimes touch > the power button by accident. Small kernels (bsd.rd) will ignore the > power button. Some other models of macppcs might have power buttons > or lids that don't work with this diff. > > Most of these features use adb(4)'s environment interrupt, which > this diff renames from PMU_INT_WAKEUP to PMU_INT_ENVIRONMENT to > match Linux, FreeBSD, NetBSD. I will commit this diff in a few > days, unless it breaks my build. A 2nd commit will connect the > power button and lid interrupts to the incomplete suspend code. > > --George
The consensus is that calling prsignal() from interrupt context isn't safe. See dev/fdt/dapmic.c for a way to avoid that. You probably want to remove the #ifdef 0 code before committing this. > > Index: arch/macppc/dev/adb.c > =================================================================== > RCS file: /cvs/src/sys/arch/macppc/dev/adb.c,v > retrieving revision 1.46 > diff -u -p -r1.46 adb.c > --- arch/macppc/dev/adb.c 2 Jul 2022 08:50:41 -0000 1.46 > +++ arch/macppc/dev/adb.c 8 Oct 2022 03:52:17 -0000 > @@ -831,6 +831,41 @@ adb_soft_intr(void) > } > } > > +void > +adb_lid_closed_intr(void) > +{ > +#ifndef SMALL_KERNEL > + switch (lid_action) { > + case 1: > + /* Suspend. */ > + break; > + case 2: > + /* Hibernate. */ > + break; > + } > +#endif > +} > + > +void > +adb_power_button_intr(void) > +{ > +#ifndef SMALL_KERNEL > + extern int allowpowerdown; > + > + switch (pwr_action) { > + case 1: > + if (allowpowerdown == 1) { > + allowpowerdown = 0; > + prsignal(initprocess, SIGUSR2); > + } > + break; > + case 2: > + /* Suspend. */ > + break; > + } > +#endif > +} > + > > /* > * This is my version of the ADBOp routine. It mainly just calls the > @@ -1597,6 +1632,7 @@ adbattach(struct device *parent, struct > adbHardware = ADB_HW_CUDA; > else if (strcmp(ca->ca_name, "via-pmu") == 0) { > adbHardware = ADB_HW_PMU; > + pm_in_adbattach(sc->sc_dev.dv_xname); > > /* > * Bus reset can take a long time if no adb devices are > Index: arch/macppc/dev/pm_direct.c > =================================================================== > RCS file: /cvs/src/sys/arch/macppc/dev/pm_direct.c,v > retrieving revision 1.31 > diff -u -p -r1.31 pm_direct.c > --- arch/macppc/dev/pm_direct.c 18 Sep 2022 21:36:41 -0000 1.31 > +++ arch/macppc/dev/pm_direct.c 8 Oct 2022 03:52:17 -0000 > @@ -42,6 +42,7 @@ > #include <sys/param.h> > #include <sys/device.h> > #include <sys/systm.h> > +#include <sys/sensors.h> > > #include <machine/cpu.h> > > @@ -142,6 +143,9 @@ signed char pm_receive_cmd_type[] = { > -1, -1, -1, -1, -1, -1, -1, -1, > }; > > +int pm_old_env; > +struct ksensor pm_lid_sens; > +struct ksensordev pm_sensdev; > > /* > * Define the private functions > @@ -161,6 +165,10 @@ int pm_send(u_char); > void pm_adb_get_TALK_result(PMData *); > void pm_adb_get_ADB_data(PMData *); > > +void pm_env_intr(PMData *); > + > + > +extern int hw_power; > > /* > * These variables are in adb_direct.c. > @@ -413,6 +421,21 @@ pmgrop(PMData *pmdata) > return rval; > } > > +void > +pm_in_adbattach(const char *devname) > +{ > + /* A PowerBook (including iBook) has a lid. */ > + if (strncmp(hw_prod, "PowerBook", 9) == 0) { > + strlcpy(pm_sensdev.xname, devname, > + sizeof(pm_sensdev.xname)); > + strlcpy(pm_lid_sens.desc, "lid open", > + sizeof(pm_lid_sens.desc)); > + pm_lid_sens.type = SENSOR_INDICATOR; > + sensor_attach(&pm_sensdev, &pm_lid_sens); > + sensordev_install(&pm_sensdev); > + pm_lid_sens.value = 1; /* This is a guess. */ > + } > +} > > /* > * My PM interrupt routine for the PB Duo series and the PB 5XX series > @@ -456,9 +479,11 @@ pm_intr(void) > case 0x16: /* ADB device event */ > case 0x18: > case 0x1e: > - case PMU_INT_WAKEUP: > pm_adb_get_ADB_data(&pmdata); > break; > + case PMU_INT_ENVIRONMENT: > + pm_env_intr(&pmdata); > + break; > default: > #ifdef ADB_DEBUG > if (adb_debug) > @@ -664,6 +689,41 @@ pm_adb_get_ADB_data(PMData *pmdata) > } > > void > +pm_env_intr(PMData *pmdata) > +{ > + int env, old; > +#if 0 > + int i; > + > + printf("pm_env_intr:"); > + for (i = 3; i < pmdata->num_data; i++) > + printf(" %02x", pmdata->data[i]); > + printf("\n"); > +#endif > + > + /* We might have 3 bytes data[3..5], but use only data[3]. */ > + if (pmdata->num_data < 3) > + return; > + env = pmdata->data[3]; > + old = pm_old_env; > + > + pm_lid_sens.value = !(env & PMU_ENV_LID_CLOSED); > + if (!(old & PMU_ENV_LID_CLOSED) && (env & PMU_ENV_LID_CLOSED)) > + adb_lid_closed_intr(); > + > + hw_power = !!(env & PMU_ENV_AC_POWER); > + > + /* > + * Act if one presses and releases the power button on a Mac > + * with no ADB keyboard. > + */ > + if ((old & PMU_ENV_POWER_BUTTON) && !(env & PMU_ENV_POWER_BUTTON)) > + adb_power_button_intr(); > + > + pm_old_env = env; > +} > + > +void > pm_adb_restart(void) > { > PMData p; > @@ -753,6 +813,7 @@ pm_battery_info(int battery, struct pmu_ > pmgrop(&p); > > info->flags = p.data[1]; > + hw_power = !!(info->flags & PMU_PWR_AC_PRESENT); > > switch (p.data[0]) { > case 3: > Index: arch/macppc/dev/pm_direct.h > =================================================================== > RCS file: /cvs/src/sys/arch/macppc/dev/pm_direct.h,v > retrieving revision 1.14 > diff -u -p -r1.14 pm_direct.h > --- arch/macppc/dev/pm_direct.h 18 Sep 2022 21:36:41 -0000 1.14 > +++ arch/macppc/dev/pm_direct.h 8 Oct 2022 03:52:17 -0000 > @@ -49,6 +49,7 @@ typedef struct { > } PMData; > > int pmgrop(PMData *); > +void pm_in_adbattach(const char *); > int pm_adb_op(u_char *, void *, void *, int); > void pm_adb_restart(void); > void pm_adb_poweroff(void); > @@ -104,7 +105,7 @@ void pmu_fileserver_mode(int); > #define PMU_INT_SNDBRT 0x08 /* sound/brightness up/down > buttons */ > #define PMU_INT_ADB 0x10 /* ADB autopoll or reply data */ > #define PMU_INT_BATTERY 0x20 > -#define PMU_INT_WAKEUP 0x40 > +#define PMU_INT_ENVIRONMENT 0x40 > #define PMU_INT_TICK 0x80 /* 1-second tick interrupt */ > #define PMU_INT_ALL 0xff /* Mask of all interrupts */ > > @@ -119,6 +120,13 @@ void pmu_fileserver_mode(int); > #define PMU_POW_CHARGER 0x02 /* battery charger power */ > #define PMU_POW_IRLED 0x04 /* IR led power (on wallstreet) > */ > #define PMU_POW_MEDIABAY 0x08 /* media bay power (wallstreet/lombard > ?) */ > + > +/* Bits from PMU_INT_ENVIRONMENT */ > +#define PMU_ENV_LID_CLOSED 0x01 /* The lid is closed */ > +#define PMU_ENV_AC_POWER 0x04 /* AC is plugged in */ > +#define PMU_ENV_POWER_BUTTON 0x08 /* power button on ADB-less Macs */ > +#define PMU_ENV_BATTERY 0x10 > +#define PMU_ENV_OVER_TEMP 0x20 > > /* PMU PMU_POWER_EVENTS commands */ > enum { > Index: arch/macppc/include/cpu.h > =================================================================== > RCS file: /cvs/src/sys/arch/macppc/include/cpu.h,v > retrieving revision 1.14 > diff -u -p -r1.14 cpu.h > --- arch/macppc/include/cpu.h 9 Oct 2013 17:43:50 -0000 1.14 > +++ arch/macppc/include/cpu.h 8 Oct 2022 03:52:17 -0000 > @@ -39,12 +39,16 @@ > */ > #define CPU_ALLOWAPERTURE 1 /* allow mmap of /dev/xf86 */ > #define CPU_ALTIVEC 2 /* altivec is present */ > -#define CPU_MAXID 3 /* number of valid machdep ids */ > +#define CPU_LIDACTION 3 /* action caused by lid close */ > +#define CPU_PWRACTION 4 /* action caused by power > button */ > +#define CPU_MAXID 5 /* number of valid machdep ids */ > > #define CTL_MACHDEP_NAMES { \ > { 0, 0 }, \ > { "allowaperture", CTLTYPE_INT }, \ > { "altivec", CTLTYPE_INT }, \ > + { "lidaction", CTLTYPE_INT }, \ > + { "pwraction", CTLTYPE_INT }, \ > } > > #ifdef _KERNEL > @@ -64,6 +68,9 @@ extern void (*ppc64_slew_voltage)(u_int) > > extern u_int32_t ticks_per_sec; > extern u_int32_t ns_per_tick; > + > +extern int lid_action; > +extern int pwr_action; > > #endif /* _KERNEL */ > #endif /* _MACHINE_CPU_H_ */ > Index: arch/macppc/macppc/machdep.c > =================================================================== > RCS file: /cvs/src/sys/arch/macppc/macppc/machdep.c,v > retrieving revision 1.196 > diff -u -p -r1.196 machdep.c > --- arch/macppc/macppc/machdep.c 19 May 2022 05:43:48 -0000 1.196 > +++ arch/macppc/macppc/machdep.c 8 Oct 2022 03:52:17 -0000 > @@ -117,6 +117,8 @@ void * startsym, *endsym; > #ifdef APERTURE > int allowaperture = 0; > #endif > +int lid_action = 1; > +int pwr_action = 1; > > void dumpsys(void); > int lcsplx(int ipl); /* called from LCore */ > @@ -346,7 +348,7 @@ install_extint(void (*handler)(void)) > extint_call = (extint_call & 0xfc000003) | offset; > bcopy(&extint, (void *)EXC_EXI, (size_t)&extsize); > syncicache((void *)&extint_call, sizeof extint_call); > - syncicache((void *)EXC_EXI, (int)&extsize); > + syncicache((void *)EXC_EXI, (size_t)&extsize); > ppc_mtmsr(omsr); > } > > @@ -533,9 +535,14 @@ sys_sigreturn(struct proc *p, void *v, r > return EJUSTRETURN; > } > > +const struct sysctl_bounded_args cpuctl_vars[] = { > + { CPU_ALTIVEC, &ppc_altivec, SYSCTL_INT_READONLY }, > + { CPU_LIDACTION, &lid_action, 0, 2 }, > + { CPU_PWRACTION, &pwr_action, 0, 2 }, > +}; > + > /* > * Machine dependent system variables. > - * None for now. > */ > int > cpu_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, > @@ -556,10 +563,9 @@ cpu_sysctl(int *name, u_int namelen, voi > #else > return (sysctl_rdint(oldp, oldlenp, newp, 0)); > #endif > - case CPU_ALTIVEC: > - return (sysctl_rdint(oldp, oldlenp, newp, ppc_altivec)); > default: > - return EOPNOTSUPP; > + return (sysctl_bounded_arr(cpuctl_vars, nitems(cpuctl_vars), > + name, namelen, oldp, oldlenp, newp, newlen)); > } > } > > Index: dev/adb/adb.h > =================================================================== > RCS file: /cvs/src/sys/dev/adb/adb.h,v > retrieving revision 1.5 > diff -u -p -r1.5 adb.h > --- dev/adb/adb.h 16 Jun 2011 10:44:33 -0000 1.5 > +++ dev/adb/adb.h 8 Oct 2022 03:52:18 -0000 > @@ -139,6 +139,8 @@ typedef struct { > } ADBDataBlock; > > int adbprint(void *, const char *); > +void adb_lid_closed_intr(void); > +void adb_power_button_intr(void); > int adb_op_sync(Ptr, short); > int set_adb_info(ADBSetInfoBlock *, int); > > Index: dev/adb/akbd.c > =================================================================== > RCS file: /cvs/src/sys/dev/adb/akbd.c,v > retrieving revision 1.15 > diff -u -p -r1.15 akbd.c > --- dev/adb/akbd.c 6 Apr 2022 18:59:27 -0000 1.15 > +++ dev/adb/akbd.c 8 Oct 2022 03:52:18 -0000 > @@ -467,13 +467,14 @@ akbd_processevent(struct akbd_softc *sc, > case 2: > /* > * The reset (or power) key sends 0x7f7f on press and > - * 0xffff on release, and we ignore it. > + * 0xffff on release. > */ > if (event->bytes[0] == event->bytes[1] && > ADBK_KEYVAL(event->bytes[0]) == ADBK_RESET) { > - if (event->bytes[0] == ADBK_KEYDOWN(ADBK_RESET)) > + if (event->bytes[0] == ADBK_KEYDOWN(ADBK_RESET)) { > SET(sc->sc_caps, CL_DOWN_RESET); > - else { > + adb_power_button_intr(); > + } else { > if (ISSET(sc->sc_caps, CL_DOWN_RESET)) > CLR(sc->sc_caps, CL_DOWN_RESET); > else if (ISSET(sc->sc_caps, CL_DOWN_ADB)) { > >