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

Reply via email to