add a driver for the Indy's front panel buttons.
- power button presses are reported to sysmon - volume control buttons are reported to PMF TODO: add better key repeat code. The hardware keeps firing interrupts at us whenever a button is down and not on - say - status change. If we don't clear the interrupt we'll be fired on until someone clears it. We should probably disable the entire interrupt and occasionally poll for button release.
This commit is contained in:
parent
9fc471919e
commit
251df1a41e
@ -1,4 +1,4 @@
|
||||
# $NetBSD: files.hpc,v 1.13 2009/02/12 06:33:57 rumble Exp $
|
||||
# $NetBSD: files.hpc,v 1.14 2009/05/14 01:10:19 macallan Exp $
|
||||
|
||||
device sq: arp, ether, ifnet
|
||||
attach sq at hpc
|
||||
@ -25,3 +25,6 @@ device pi1ppc: parport
|
||||
attach pi1ppc at hpc
|
||||
file arch/sgimips/hpc/pi1ppc.c pi1ppc
|
||||
|
||||
device panel : sysmon_power, sysmon_taskq
|
||||
attach panel at hpc
|
||||
file arch/sgimips/hpc/panel.c panel
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: hpc.c,v 1.61 2009/02/12 06:33:57 rumble Exp $ */
|
||||
/* $NetBSD: hpc.c,v 1.62 2009/05/14 01:10:19 macallan Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000 Soren S. Jorvang
|
||||
@ -35,7 +35,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: hpc.c,v 1.61 2009/02/12 06:33:57 rumble Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: hpc.c,v 1.62 2009/05/14 01:10:19 macallan Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -202,6 +202,12 @@ static const struct hpc_device hpc3_devices[] = {
|
||||
-1,
|
||||
HPCDEV_IP22 | HPCDEV_IP24 },
|
||||
|
||||
{ "panel", /* Indy front panel */
|
||||
HPC_BASE_ADDRESS_0,
|
||||
HPC3_PBUS_CH6_DEVREGS + IOC_PANEL, 0,
|
||||
9,
|
||||
HPCDEV_IP24 },
|
||||
|
||||
{ NULL,
|
||||
0,
|
||||
0, 0,
|
||||
|
149
sys/arch/sgimips/hpc/panel.c
Normal file
149
sys/arch/sgimips/hpc/panel.c
Normal file
@ -0,0 +1,149 @@
|
||||
/* $NetBSD: panel.c,v 1.1 2009/05/14 01:10:19 macallan Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2009 Michael Lorenz
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: panel.c,v 1.1 2009/05/14 01:10:19 macallan Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/kthread.h>
|
||||
|
||||
#include <sys/bus.h>
|
||||
|
||||
#include <dev/sysmon/sysmonvar.h>
|
||||
#include <dev/sysmon/sysmon_taskq.h>
|
||||
|
||||
#include <machine/autoconf.h>
|
||||
#include <machine/machtype.h>
|
||||
|
||||
#include <sgimips/ioc/iocreg.h>
|
||||
#include <sgimips/hpc/hpcvar.h>
|
||||
#include <sgimips/hpc/hpcreg.h>
|
||||
|
||||
struct panel_softc {
|
||||
device_t sc_dev;
|
||||
struct sysmon_pswitch sc_pbutton;
|
||||
bus_space_tag_t sc_tag;
|
||||
bus_space_handle_t sc_hreg;
|
||||
int sc_last, sc_fired;
|
||||
};
|
||||
|
||||
static int panel_match(device_t, cfdata_t, void *);
|
||||
static void panel_attach(device_t, device_t, void *);
|
||||
|
||||
static int panel_intr(void *);
|
||||
static void panel_powerbutton(void *);
|
||||
|
||||
CFATTACH_DECL_NEW(panel, sizeof(struct panel_softc),
|
||||
panel_match,
|
||||
panel_attach,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
static int
|
||||
panel_match(device_t parent, cfdata_t match, void *aux)
|
||||
{
|
||||
if (mach_type == MACH_SGI_IP22)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
panel_attach(device_t parent, device_t self, void *aux)
|
||||
{
|
||||
struct panel_softc *sc;
|
||||
struct hpc_attach_args *haa;
|
||||
|
||||
sc = device_private(self);
|
||||
sc->sc_dev = self;
|
||||
haa = aux;
|
||||
sc->sc_tag = haa->ha_st;
|
||||
sc->sc_fired = 0;
|
||||
|
||||
aprint_normal("\n");
|
||||
if (bus_space_subregion(haa->ha_st, haa->ha_sh, haa->ha_devoff,
|
||||
0x1, /* just a single register */
|
||||
&sc->sc_hreg)) {
|
||||
aprint_error(": unable to map panel register\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((cpu_intr_establish(haa->ha_irq, IPL_BIO,
|
||||
panel_intr, sc)) == NULL) {
|
||||
printf(": unable to establish interrupt!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
sc->sc_last = 0;
|
||||
|
||||
sysmon_task_queue_init();
|
||||
memset(&sc->sc_pbutton, 0, sizeof(struct sysmon_pswitch));
|
||||
sc->sc_pbutton.smpsw_name = device_xname(sc->sc_dev);
|
||||
sc->sc_pbutton.smpsw_type = PSWITCH_TYPE_POWER;
|
||||
if (sysmon_pswitch_register(&sc->sc_pbutton) != 0)
|
||||
aprint_error_dev(sc->sc_dev,
|
||||
"unable to register power button with sysmon\n");
|
||||
pmf_device_register(self, NULL, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
panel_intr(void *cookie)
|
||||
{
|
||||
struct panel_softc *sc = cookie;
|
||||
uint8_t reg;
|
||||
|
||||
reg = bus_space_read_1(sc->sc_tag, sc->sc_hreg, 0);
|
||||
bus_space_write_1(sc->sc_tag, sc->sc_hreg, 0,
|
||||
IOC_PANEL_VDOWN_IRQ | IOC_PANEL_VUP_IRQ | IOC_PANEL_POWER_IRQ);
|
||||
if ((reg & IOC_PANEL_POWER_IRQ) == 0) {
|
||||
if (!sc->sc_fired)
|
||||
sysmon_task_queue_sched(0, panel_powerbutton, sc);
|
||||
sc->sc_fired = 1;
|
||||
}
|
||||
if (time_second == sc->sc_last)
|
||||
return 1;
|
||||
sc->sc_last = time_second;
|
||||
if ((reg & IOC_PANEL_VDOWN_HOLD) == 0)
|
||||
pmf_event_inject(NULL, PMFE_AUDIO_VOLUME_DOWN);
|
||||
if ((reg & IOC_PANEL_VUP_HOLD) == 0)
|
||||
pmf_event_inject(NULL, PMFE_AUDIO_VOLUME_UP);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
panel_powerbutton(void *cookie)
|
||||
{
|
||||
struct panel_softc *sc = cookie;
|
||||
|
||||
sysmon_pswitch_event(&sc->sc_pbutton, PSWITCH_EVENT_PRESSED);
|
||||
}
|
Loading…
Reference in New Issue
Block a user