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 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)) {