Module Name:    src
Committed By:   isaki
Date:           Sun Nov 27 09:00:33 UTC 2011

Modified Files:
        src/distrib/sets/lists/man: mi
        src/share/man/man4/man4.x68k: Makefile
        src/sys/arch/x68k/conf: GENERIC files.x68k
Added Files:
        src/share/man/man4/man4.x68k: powsw.4
        src/sys/arch/x68k/dev: powsw.c

Log Message:
Add powsw(4) for x68k power switch.  It substitutes for a part about
power switch handler of pow(4) deleted before.
Benefits than pow(4):
- separate a front switch (= powsw0) and an EXPWON line (= powsw1)
  completely. Only powsw0 is enabled in GENERIC by default.
- prevent chattering in some hardware individuals.
  thank you for a report and a test: Yasushi Oshima and Y.Sugahara.


To generate a diff of this commit:
cvs rdiff -u -r1.1358 -r1.1359 src/distrib/sets/lists/man/mi
cvs rdiff -u -r1.8 -r1.9 src/share/man/man4/man4.x68k/Makefile
cvs rdiff -u -r0 -r1.1 src/share/man/man4/man4.x68k/powsw.4
cvs rdiff -u -r1.157 -r1.158 src/sys/arch/x68k/conf/GENERIC
cvs rdiff -u -r1.76 -r1.77 src/sys/arch/x68k/conf/files.x68k
cvs rdiff -u -r0 -r1.1 src/sys/arch/x68k/dev/powsw.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/distrib/sets/lists/man/mi
diff -u src/distrib/sets/lists/man/mi:1.1358 src/distrib/sets/lists/man/mi:1.1359
--- src/distrib/sets/lists/man/mi:1.1358	Sat Nov 26 15:39:49 2011
+++ src/distrib/sets/lists/man/mi	Sun Nov 27 09:00:32 2011
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.1358 2011/11/26 15:39:49 tsutsui Exp $
+# $NetBSD: mi,v 1.1359 2011/11/27 09:00:32 isaki Exp $
 #
 # Note: don't delete entries from here - mark them as "obsolete" instead.
 #
@@ -1826,6 +1826,7 @@
 ./usr/share/man/cat4/x68k/mfp.0			man-sys-catman		.cat
 ./usr/share/man/cat4/x68k/neptune.0		man-sys-catman		.cat
 ./usr/share/man/cat4/x68k/pow.0			man-obsolete		obsolete
+./usr/share/man/cat4/x68k/powsw.0		man-sys-catman		.cat
 ./usr/share/man/cat4/x68k/vs.0			man-sys-catman		.cat
 ./usr/share/man/cat4/x86/amdpcib.0		man-sys-catman		.cat
 ./usr/share/man/cat4/x86/apic.0			man-sys-catman		.cat
@@ -4592,6 +4593,7 @@
 ./usr/share/man/html4/x68k/mfp.html		man-sys-htmlman		html
 ./usr/share/man/html4/x68k/neptune.html		man-sys-htmlman		html
 ./usr/share/man/html4/x68k/pow.html		man-obsolete		obsolete
+./usr/share/man/html4/x68k/powsw.html		man-sys-htmlman		html
 ./usr/share/man/html4/x68k/vs.html		man-sys-htmlman		html
 ./usr/share/man/html4/x86/amdpcib.html		man-sys-htmlman		html
 ./usr/share/man/html4/x86/apic.html		man-sys-htmlman		html
@@ -7293,6 +7295,7 @@
 ./usr/share/man/man4/x68k/mfp.4			man-sys-man		.man
 ./usr/share/man/man4/x68k/neptune.4		man-sys-man		.man
 ./usr/share/man/man4/x68k/pow.4			man-obsolete		obsolete
+./usr/share/man/man4/x68k/powsw.4		man-sys-man		.man
 ./usr/share/man/man4/x68k/vs.4			man-sys-man		.man
 ./usr/share/man/man4/x86/amdpcib.4		man-sys-man		.man
 ./usr/share/man/man4/x86/apic.4			man-sys-man		.man

Index: src/share/man/man4/man4.x68k/Makefile
diff -u src/share/man/man4/man4.x68k/Makefile:1.8 src/share/man/man4/man4.x68k/Makefile:1.9
--- src/share/man/man4/man4.x68k/Makefile:1.8	Sat Nov 19 12:27:43 2011
+++ src/share/man/man4/man4.x68k/Makefile	Sun Nov 27 09:00:33 2011
@@ -1,6 +1,6 @@
-#	$NetBSD: Makefile,v 1.8 2011/11/19 12:27:43 isaki Exp $
+#	$NetBSD: Makefile,v 1.9 2011/11/27 09:00:33 isaki Exp $
 
-MAN=	bmd.4 intio.4 intro.4 mfp.4 neptune.4 vs.4
+MAN=	bmd.4 intio.4 intro.4 mfp.4 neptune.4 powsw.4 vs.4
 MANSUBDIR=/x68k
 
 .include <bsd.man.mk>

Index: src/sys/arch/x68k/conf/GENERIC
diff -u src/sys/arch/x68k/conf/GENERIC:1.157 src/sys/arch/x68k/conf/GENERIC:1.158
--- src/sys/arch/x68k/conf/GENERIC:1.157	Tue Nov 22 21:25:41 2011
+++ src/sys/arch/x68k/conf/GENERIC	Sun Nov 27 09:00:32 2011
@@ -1,4 +1,4 @@
-# $NetBSD: GENERIC,v 1.157 2011/11/22 21:25:41 tls Exp $
+# $NetBSD: GENERIC,v 1.158 2011/11/27 09:00:32 isaki Exp $
 #
 # GENERIC machine description file
 # 
@@ -22,7 +22,7 @@ include 	"arch/x68k/conf/std.x68k"
 
 options 	INCLUDE_CONFIG_FILE	# embed config file in kernel binary
 
-#ident 		"GENERIC-$Revision: 1.157 $"
+#ident 		"GENERIC-$Revision: 1.158 $"
 
 maxusers	8
 
@@ -288,6 +288,9 @@ par0	at intio0 addr 0xe8c000 	# Builtin 
 sram0	at intio0 addr 0xed0000		# battery-backuped static RAM
 pseudo-device	bell			# OPM bell
 
+powsw0	at mfp0				# Front switch
+#powsw1	at mfp0				# External power switch
+
 xcom0	at mainbus0			# NS16550 fast serial
 xcom1	at mainbus0
 

Index: src/sys/arch/x68k/conf/files.x68k
diff -u src/sys/arch/x68k/conf/files.x68k:1.76 src/sys/arch/x68k/conf/files.x68k:1.77
--- src/sys/arch/x68k/conf/files.x68k:1.76	Sat Nov 19 12:27:43 2011
+++ src/sys/arch/x68k/conf/files.x68k	Sun Nov 27 09:00:32 2011
@@ -1,4 +1,4 @@
-#	$NetBSD: files.x68k,v 1.76 2011/11/19 12:27:43 isaki Exp $
+#	$NetBSD: files.x68k,v 1.77 2011/11/27 09:00:32 isaki Exp $
 #
 # new style config file for x68k architecture
 #
@@ -96,6 +96,10 @@ device kbd: event
 attach	kbd at mfp
 file	arch/x68k/dev/kbd.c		kbd needs-flag
 
+device powsw: sysmon_power, sysmon_taskq
+attach	powsw at mfp
+file	arch/x68k/dev/powsw.c		powsw
+
 device rtc
 attach	rtc at intio
 file	arch/x68k/dev/rtclock.c		rtc

Added files:

Index: src/share/man/man4/man4.x68k/powsw.4
diff -u /dev/null src/share/man/man4/man4.x68k/powsw.4:1.1
--- /dev/null	Sun Nov 27 09:00:33 2011
+++ src/share/man/man4/man4.x68k/powsw.4	Sun Nov 27 09:00:33 2011
@@ -0,0 +1,55 @@
+.\" $NetBSD: powsw.4,v 1.1 2011/11/27 09:00:33 isaki Exp $
+.\"
+.\" Copyright (c) 2011 Tetsuya Isaki. 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 AUTHOR ``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 AUTHOR 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.
+.\"
+.Dd November 27, 2011
+.Dt POWSW 4 x68k
+.Os
+.Sh NAME
+.Nm powsw
+.Nd x68k power switch handler
+.Sh SYNOPSIS
+.Cd powsw0 at mfp0
+.Cd powsw1 at mfp0
+.Sh DESCRIPTION
+The
+.Nm
+driver monitors x68k's power switch,
+and is made as interface to
+.Xr sysmon_pswitch 9 .
+.Pp
+.Nm powsw0
+monitors a front switch.
+.Nm powsw1
+monitors an external power switch (EXPWON signal in I/O slot).
+.Sh SEE ALSO
+.Xr powerd 8
+.Sh HISTORY
+.Nm
+appeared in
+.Nx 6.0 .
+.Sh BUGS
+I have no idea for
+.Nm powsw2
+(rtc alarm).

Index: src/sys/arch/x68k/dev/powsw.c
diff -u /dev/null src/sys/arch/x68k/dev/powsw.c:1.1
--- /dev/null	Sun Nov 27 09:00:33 2011
+++ src/sys/arch/x68k/dev/powsw.c	Sun Nov 27 09:00:32 2011
@@ -0,0 +1,290 @@
+/*	$NetBSD: powsw.c,v 1.1 2011/11/27 09:00:32 isaki Exp $	*/
+
+/*
+ * Copyright (c) 2011 Tetsuya Isaki. 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 AUTHOR ``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 AUTHOR 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.
+ */
+
+/*
+ * Power switch monitor
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: powsw.c,v 1.1 2011/11/27 09:00:32 isaki Exp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/device.h>
+#include <sys/intr.h>
+#include <sys/callout.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+
+#include <arch/x68k/dev/intiovar.h>
+#include <arch/x68k/dev/mfp.h>
+
+#include <dev/sysmon/sysmonvar.h>
+#include <dev/sysmon/sysmon_taskq.h>
+
+extern int power_switch_is_off;		/* XXX should be in .h */
+
+//#define POWSW_DEBUG
+
+#if defined(POWSW_DEBUG)
+#define DPRINTF(fmt...)	printf(fmt)
+#define DEBUG_LOG_ADD(c)	sc->sc_log[sc->sc_loglen++] = (c)
+#define DEBUG_LOG_PRINT()	do {	\
+	sc->sc_log[sc->sc_loglen] = '\0';	\
+	printf("%s", sc->sc_log);	\
+} while (0)
+#else
+#define DPRINTF(fmt...)
+#define DEBUG_LOG_ADD(c)
+#define DEBUG_LOG_PRINT()
+#endif
+
+/* mask */
+#define POWSW_ALARM		(0x01)
+#define POWSW_EXTERNAL	(0x02)
+#define POWSW_FRONT		(0x04)
+
+/* parameter */
+#define POWSW_MAX_TICK	(30)
+#define POWSW_THRESHOLD	(10)
+
+struct powsw_softc {
+	device_t sc_dev;
+	struct sysmon_pswitch sc_smpsw;
+	callout_t sc_callout;
+	int sc_mask;
+	int sc_prev;
+	int sc_last_sw;
+	int sc_tick;
+	int sc_count;
+#if defined(POWSW_DEBUG)
+	char sc_log[100];
+	int sc_loglen;
+#endif
+};
+
+extern struct cfdriver powsw_cd;
+
+static int  powsw_match(device_t, cfdata_t, void *);
+static void powsw_attach(device_t, device_t, void *);
+static int  powsw_intr(void *);
+static void powsw_softintr(void *);
+static void powsw_pswitch_event(void *);
+static void powsw_shutdown_check(void *);
+static void powsw_reset_counter(struct powsw_softc *);
+static void powsw_set_aer(struct powsw_softc *, int);
+
+CFATTACH_DECL_NEW(powsw, sizeof(struct powsw_softc),
+    powsw_match, powsw_attach, NULL, NULL);
+
+
+typedef const struct {
+	int vector;			/* interrupt vector */
+	int mask;			/* mask bit for MFP GPIP */
+	const char *name;
+} powsw_desc_t;
+
+static powsw_desc_t powsw_desc[2] = {
+	{ 66, POWSW_FRONT,		"Front Switch", },
+	{ 65, POWSW_EXTERNAL,	"External Power Switch", },
+	/* XXX I'm not sure about alarm bit */
+};
+
+
+static int
+powsw_match(device_t parent, cfdata_t cf, void *aux)
+{
+	return 1;
+}
+
+static void
+powsw_attach(device_t parent, device_t self, void *aux)
+{
+	struct powsw_softc *sc = device_private(self);
+	powsw_desc_t *desc;
+	const char *xname;
+	int unit;
+	int sw;
+
+	unit = device_unit(self);
+	xname = device_xname(self);
+	desc = &powsw_desc[unit];
+
+	memset(sc, 0, sizeof(*sc));
+	sc->sc_dev = self;
+	sc->sc_mask = desc->mask;
+	sc->sc_prev = -1;
+	powsw_reset_counter(sc);
+
+	sysmon_task_queue_init();
+	sc->sc_smpsw.smpsw_name = xname;
+	sc->sc_smpsw.smpsw_type = PSWITCH_TYPE_POWER;
+	if (sysmon_pswitch_register(&sc->sc_smpsw) != 0)
+		panic("can't register with sysmon");
+
+	callout_init(&sc->sc_callout, 0);
+	callout_setfunc(&sc->sc_callout, powsw_softintr, sc);
+
+	if (shutdownhook_establish(powsw_shutdown_check, sc) == NULL)
+		panic("%s: can't establish shutdown hook", xname);
+
+	if (intio_intr_establish(desc->vector, xname, powsw_intr, sc) < 0)
+		panic("%s: can't establish interrupt", xname);
+
+	/* Set AER and enable interrupt */
+	sw = (mfp_get_gpip() & sc->sc_mask);
+	powsw_set_aer(sc, sw ? 0 : 1);
+	mfp_bit_set_ierb(sc->sc_mask);
+
+	aprint_normal(": %s\n", desc->name);
+}
+
+static int
+powsw_intr(void *arg)
+{
+	struct powsw_softc *sc = arg;
+
+	if (sc->sc_tick == 0) {
+		mfp_bit_clear_ierb(sc->sc_mask);
+		sc->sc_tick++;
+		DEBUG_LOG_ADD('i');
+		/*
+		 * The button state seems unstable for few ticks,
+		 * so wait a bit to settle.
+		 */
+		callout_schedule(&sc->sc_callout, 1);
+	} else {
+		DEBUG_LOG_ADD('x');
+	}
+	return 0;
+}
+
+void
+powsw_softintr(void *arg)
+{
+	struct powsw_softc *sc = arg;
+	int sw;
+	int s;
+
+	s = spl6();
+
+	if (sc->sc_tick++ >= POWSW_MAX_TICK) {
+		/* tick is over, broken switch? */
+		printf("%s: unstable power switch?, ignored\n",
+		    device_xname(sc->sc_dev));
+		powsw_reset_counter(sc);
+
+		mfp_bit_set_ierb(sc->sc_mask);
+		splx(s);
+		return;
+	}
+
+	sw = (mfp_get_gpip() & sc->sc_mask) ? 1 : 0;
+	DEBUG_LOG_ADD('0' + sw);
+
+	if (sw == sc->sc_last_sw) {
+		sc->sc_count++;
+	} else {
+		sc->sc_last_sw = sw;
+		sc->sc_count = 1;
+	}
+
+	if (sc->sc_count < POWSW_THRESHOLD) {
+		callout_schedule(&sc->sc_callout, 1);
+	} else {
+		/* switch seems stable */
+		DEBUG_LOG_PRINT();
+
+		if (sc->sc_last_sw == sc->sc_prev) {
+			/* switch state is not changed, it was a noise */
+			DPRINTF(" ignore(sw=%d,prev=%d)\n", sc->sc_last_sw, sc->sc_prev);
+		} else {
+			/* switch state has been changed */
+			sc->sc_prev = sc->sc_last_sw;
+			powsw_set_aer(sc, 1 - sc->sc_prev);
+			sysmon_task_queue_sched(0, powsw_pswitch_event, sc);
+		}
+		powsw_reset_counter(sc);
+		mfp_bit_set_ierb(sc->sc_mask);	// enable interrupt
+	}
+
+	splx(s);
+}
+
+static void
+powsw_pswitch_event(void *arg)
+{
+	struct powsw_softc *sc = arg;
+	int poweroff;
+
+	poweroff = sc->sc_prev;
+
+	DPRINTF(" %s is %s\n", device_xname(sc->sc_dev),
+	    poweroff ? "off(PRESS)" : "on(RELEASE)");
+
+	sysmon_pswitch_event(&sc->sc_smpsw,
+		poweroff ? PSWITCH_EVENT_PRESSED : PSWITCH_EVENT_RELEASED);
+}
+
+static void
+powsw_shutdown_check(void *arg)
+{
+	struct powsw_softc *sc = arg;
+	int poweroff;
+
+	poweroff = sc->sc_prev;
+	if (poweroff)
+		power_switch_is_off = 1;
+	DPRINTF("powsw_shutdown_check %s = %d\n",
+		device_xname(sc->sc_dev), power_switch_is_off);
+}
+
+static void
+powsw_reset_counter(struct powsw_softc *sc)
+{
+	sc->sc_last_sw = -1;
+	sc->sc_tick = 0;
+	sc->sc_count = 0;
+#if defined(POWSW_DEBUG)
+	sc->sc_loglen = 0;
+#endif
+}
+
+static void
+powsw_set_aer(struct powsw_softc *sc, int aer)
+{
+	KASSERT(aer == 0 || aer == 1);
+
+	if (aer == 0) {
+		mfp_bit_clear_aer(sc->sc_mask);
+	} else {
+		mfp_bit_set_aer(sc->sc_mask);
+	}
+	DPRINTF(" SetAER=%d", aer);
+}

Reply via email to