On Sun, 16 Oct 2022 18:05:28 +0200
Mark Kettenis <mark.kette...@xs4all.nl> wrote:

> The consensus is that calling prsignal() from interrupt context isn't
> safe.  See dev/fdt/dapmic.c for a way to avoid that.

I put prsignal() in interrupt context after "grep -R 'prsignal.*USR2'"
found other files that might do the same,

arch/arm64/dev/aplsmc.c
  aplmbox_intr -> sc_rx_callback = rtkit_rx_callback -> rtkit_poll
  -> callback = aplsmc_callback -> aplsmc_handle_notification
  -> prsignal
arch/sparc64/dev/power.c    power_intr -> prsignal
arch/sparc64/dev/rtc.c      rtc_intr -> prsignal
arch/sparc64/dev/sbus.c     sbus_overtemp -> prsignal
dev/pv/pvbus.c
  virtio_pci_config_intr -> sc_config_change = vmmci_config_change
  -> pvbus_shutdown -> prsignal

I have edited adb.c in this diff to act like dapmic.c and use
task_add(9) to call prsignal() from process context.  (This diff
still has the #if 0 in pm_env_intr; I will delete it.)

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       20 Oct 2022 18:29:42 -0000
@@ -89,6 +89,7 @@
 #include <sys/fcntl.h>
 #include <sys/proc.h>
 #include <sys/signalvar.h>
+#include <sys/task.h>
 #include <sys/timeout.h>
 #include <sys/systm.h>
 
@@ -242,6 +243,11 @@ int        adb_intr(void *arg);
 void   adb_cuda_autopoll(void);
 void   adb_cuda_fileserver_mode(void);
 
+#ifndef SMALL_KERNEL
+void   adb_shutdown(void *);
+struct task adb_shutdown_task = TASK_INITIALIZER(adb_shutdown, NULL);
+#endif
+
 #ifdef ADB_DEBUG
 /*
  * print_single
@@ -831,6 +837,49 @@ adb_soft_intr(void)
        }
 }
 
+#ifndef SMALL_KERNEL
+void
+adb_shutdown(void *arg)
+{
+       extern int allowpowerdown;
+
+       if (allowpowerdown == 1) {
+               allowpowerdown = 0;
+               prsignal(initprocess, SIGUSR2);
+       }
+}
+#endif /* !SMALL_KERNEL */
+
+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
+       switch (pwr_action) {
+       case 1:
+               task_add(systq, &adb_shutdown_task);
+               break;
+       case 2:
+               /* Suspend. */
+               break;
+       }
+#endif
+}
+
 
 /*
  * This is my version of the ADBOp routine. It mainly just calls the
@@ -1597,6 +1646,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 20 Oct 2022 18:29:42 -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 20 Oct 2022 18:29:42 -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   20 Oct 2022 18:29:42 -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        20 Oct 2022 18:29:42 -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       20 Oct 2022 18:29:42 -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      20 Oct 2022 18:29:42 -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