Connect the front panel power button on psycho based machines to sysmon's

/dev/power.

XXX - due to the way interrupt handling is structured we have no easy
way to defer clearing the button interrupt until the sysmon callback
has  happened and the event is dispatched. We clear it imediately on
return from the interrupt handler. This means we get an interrupt storm
until the button is released, and then start to handle it.
This needs to be fixed! (But with the default application for the power
button does not make a user visible difference.)
This commit is contained in:
martin 2003-04-21 12:14:19 +00:00
parent 0b8f02edad
commit d65cbab3ff
3 changed files with 56 additions and 7 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: files.sparc64,v 1.75 2003/03/22 06:39:43 nakayama Exp $
# $NetBSD: files.sparc64,v 1.76 2003/04/21 12:14:19 martin Exp $
# @(#)files.sparc64 8.1 (Berkeley) 7/19/93
# sparc64-specific configuration info
@ -41,7 +41,7 @@ include "dev/sbus/files.sbus"
attach sbus at mainbus
file arch/sparc64/dev/sbus.c sbus
device psycho: pcibus
device psycho: pcibus, sysmon_power, sysmon_taskq
attach psycho at mainbus
include "dev/pci/files.pci"
file arch/sparc64/dev/psycho.c psycho

View File

@ -1,4 +1,4 @@
/* $NetBSD: psycho.c,v 1.59 2003/04/01 16:34:58 thorpej Exp $ */
/* $NetBSD: psycho.c,v 1.60 2003/04/21 12:14:20 martin Exp $ */
/*
* Copyright (c) 2001, 2002 Eduardo E. Horvath
@ -64,6 +64,7 @@ int psycho_debug = 0x0;
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <dev/sysmon/sysmon_taskq.h>
#include <sparc64/dev/iommureg.h>
#include <sparc64/dev/iommuvar.h>
@ -125,6 +126,10 @@ void psycho_dmamem_unmap __P((bus_dma_tag_t, caddr_t, size_t));
/* base pci_chipset */
extern struct sparc_pci_chipset _sparc_pci_chipset;
/* power button handlers */
static void psycho_register_power_button(struct psycho_softc *sc);
static void psycho_power_button_pressed(void *arg);
/*
* autoconfiguration
*/
@ -461,6 +466,7 @@ found:
psycho_set_intr(sc, 15, psycho_powerfail,
&sc->sc_regs->power_int_map,
&sc->sc_regs->power_clr_int);
psycho_register_power_button(sc);
psycho_set_intr(sc, 1, psycho_wakeup,
&sc->sc_regs->pwrmgt_int_map,
&sc->sc_regs->pwrmgt_clr_int);
@ -621,6 +627,38 @@ psycho_set_intr(sc, ipl, handler, mapper, clearer)
*(ih->ih_map) |= INTMAP_V;
}
/*
* power button handlers
*/
static void
psycho_register_power_button(struct psycho_softc *sc)
{
sysmon_task_queue_init();
sc->sc_powerpressed = 0;
sc->sc_smcontext = malloc(sizeof(struct sysmon_pswitch), M_DEVBUF, 0);
if (!sc->sc_smcontext) {
printf("%s: could not allocate power button context\n",
sc->sc_dev.dv_xname);
return;
}
memset(sc->sc_smcontext, 0, sizeof(struct sysmon_pswitch));
sc->sc_smcontext->smpsw_name = sc->sc_dev.dv_xname;
sc->sc_smcontext->smpsw_type = PSWITCH_TYPE_POWER;
if (sysmon_pswitch_register(sc->sc_smcontext) != 0)
printf("%s: unable to register power button with sysmon\n",
sc->sc_dev.dv_xname);
}
static void
psycho_power_button_pressed(void *arg)
{
struct psycho_softc *sc = arg;
sysmon_pswitch_event(sc->sc_smcontext, PSWITCH_EVENT_PRESSED);
sc->sc_powerpressed = 0;
}
/*
* PCI bus support
*/
@ -841,18 +879,24 @@ psycho_bus_b(arg)
(long long)regs->psy_pcictl[0].pci_afsr);
return (1);
}
static int
psycho_powerfail(arg)
void *arg;
{
struct psycho_softc *sc = (struct psycho_softc *)arg;
/*
* We lost power. Try to shut down NOW.
* We lost power. Queue a callback with thread context to
* handle all the real work.
*/
printf("Power Failure Detected: Shutting down NOW.\n");
cpu_reboot(RB_POWERDOWN|RB_HALT, NULL);
if (sc->sc_powerpressed == 0 && sc->sc_smcontext != NULL) {
sc->sc_powerpressed = 1;
sysmon_task_queue_sched(0, psycho_power_button_pressed, sc);
}
return (1);
}
static
int psycho_wakeup(arg)
void *arg;

View File

@ -1,4 +1,4 @@
/* $NetBSD: psychovar.h,v 1.9 2003/03/22 06:33:10 nakayama Exp $ */
/* $NetBSD: psychovar.h,v 1.10 2003/04/21 12:14:20 martin Exp $ */
/*
* Copyright (c) 1999, 2000 Matthew R. Green
@ -31,6 +31,8 @@
#ifndef _SPARC64_DEV_PSYCHOVAR_H_
#define _SPARC64_DEV_PSYCHOVAR_H_
#include <dev/sysmon/sysmonvar.h>
/* per real PCI bus info */
struct psycho_softc;
@ -121,6 +123,9 @@ struct psycho_softc {
#define PSYCHO_MODE_PSYCHO 2 /* i'm a psycho (w*nker) */
struct iommu_state *sc_is;
struct sysmon_pswitch *sc_smcontext; /* power switch definition */
int sc_powerpressed;/* already signaled */
};
/* get a PCI offset address from bus_space_handle_t */