> Date: Sun, 16 Oct 2022 11:48:56 -0400
> From: George Koehler <[email protected]>
>
> 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)) {
>
>