summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorshige <shige@NetBSD.org>2005-09-04 12:20:15 +0000
committershige <shige@NetBSD.org>2005-09-04 12:20:15 +0000
commit044ec00fc2142dbb8db7c0113059864485da1178 (patch)
treedfa80bcbbb4f54c1fd15e943baedff8dfbfd3276 /sys
parent100f9bce034c71f708a5e372f0dad3f10df8be7d (diff)
Support LED-control via sysctl (on=1/off=0).
Sysctl name: hw.obsled.led{1,2,4}. Submitted by kiyohara.
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/evbppc/obs405/dev/obsled.c104
1 files changed, 95 insertions, 9 deletions
diff --git a/sys/arch/evbppc/obs405/dev/obsled.c b/sys/arch/evbppc/obs405/dev/obsled.c
index 519560690c1..e91db58ab6a 100644
--- a/sys/arch/evbppc/obs405/dev/obsled.c
+++ b/sys/arch/evbppc/obs405/dev/obsled.c
@@ -1,4 +1,4 @@
-/* $NetBSD: obsled.c,v 1.2 2005/03/18 14:12:34 shige Exp $ */
+/* $NetBSD: obsled.c,v 1.3 2005/09/04 12:20:15 shige Exp $ */
/*
* Copyright (c) 2004 Shigeyuki Fukushima.
@@ -31,11 +31,12 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: obsled.c,v 1.2 2005/03/18 14:12:34 shige Exp $");
+__KERNEL_RCSID(0, "$NetBSD: obsled.c,v 1.3 2005/09/04 12:20:15 shige Exp $");
#include <sys/param.h>
#include <sys/device.h>
#include <sys/queue.h>
+#include <sys/sysctl.h>
#include <sys/systm.h>
#include <machine/obs266.h>
@@ -46,10 +47,14 @@ struct obsled_softc {
struct device sc_dev;
gpio_tag_t sc_tag;
int sc_addr;
+ int sc_led_state; /* LED status (ON=1/OFF=0) */
+ int sc_led_state_mib;
};
static void obsled_attach(struct device *, struct device *, void *);
static int obsled_match(struct device *, struct cfdata *, void *);
+static int obsled_sysctl_verify(SYSCTLFN_PROTO);
+static void obsled_set_state(struct obsled_softc *);
CFATTACH_DECL(obsled, sizeof(struct obsled_softc),
obsled_match, obsled_attach, NULL, NULL);
@@ -75,15 +80,53 @@ obsled_attach(struct device *parent, struct device *self, void *aux)
{
struct obsled_softc *sc = (struct obsled_softc *)self;
struct gpio_attach_args *ga = aux;
- int led = (1 << sc->sc_dev.dv_unit);
+ struct sysctlnode *node;
+ int err, node_mib;
+ char led_name[5];
+ /* int led = (1 << sc->sc_dev.dv_unit); */
- aprint_naive(": OpenBlockS LED%d\n", led);
- aprint_normal(": OpenBlockS LED%d\n", led);
+ snprintf(led_name, sizeof(led_name),
+ "led%d", (1 << sc->sc_dev.dv_unit) & 0x7);
+ aprint_naive(": OpenBlockS %s\n", led_name);
+ aprint_normal(": OpenBlockS %s\n", led_name);
sc->sc_tag = ga->ga_tag;
sc->sc_addr = ga->ga_addr;
+ sc->sc_led_state = 0;
obs266_led_set(OBS266_LED_OFF);
+
+ /* add sysctl interface */
+ err = sysctl_createv(NULL, 0,
+ NULL, NULL,
+ 0, CTLTYPE_NODE,
+ "hw",
+ NULL,
+ NULL, 0, NULL, 0,
+ CTL_HW, CTL_EOL);
+ if (err != 0)
+ return;
+ err = sysctl_createv(NULL, 0,
+ NULL, (const struct sysctlnode **)&node,
+ 0, CTLTYPE_NODE,
+ "obsled",
+ NULL,
+ NULL, 0, NULL, 0,
+ CTL_HW, CTL_CREATE, CTL_EOL);
+ if (err != 0)
+ return;
+ node_mib = node->sysctl_num;
+ err = sysctl_createv(NULL, 0,
+ NULL, (const struct sysctlnode **)&node,
+ CTLFLAG_READWRITE, CTLTYPE_INT,
+ led_name,
+ SYSCTL_DESCR("OpenBlockS LED state (0=off, 1=on)"),
+ obsled_sysctl_verify, 0, sc, 0,
+ CTL_HW, node_mib, CTL_CREATE, CTL_EOL);
+ if (err != 0)
+ return;
+
+ sc->sc_led_state_mib = node->sysctl_num;
#if 0
{
gpio_tag_t tag = sc->sc_tag;
@@ -92,20 +135,63 @@ obsled_attach(struct device *parent, struct device *self, void *aux)
#endif
}
+static int
+obsled_sysctl_verify(SYSCTLFN_ARGS)
+{
+ struct obsled_softc *sc = rnode->sysctl_data;
+ struct sysctlnode node;
+ int err, state;
+
+ node = *rnode;
+ state = sc->sc_led_state;
+ node.sysctl_data = &state;
+
+ err = sysctl_lookup(SYSCTLFN_CALL(&node));
+ if (err != 0 || newp == NULL)
+ return err;
+
+ if (node.sysctl_num == sc->sc_led_state_mib) {
+ if (state < 0 || state > 1)
+ return EINVAL;
+ sc->sc_led_state = state;
+ obsled_set_state(sc);
+ }
+
+ return 0;
+}
+
+static void
+obsled_set_state(struct obsled_softc *sc)
+{
+ gpio_tag_t tag = sc->sc_tag;
+
+ (*(tag)->io_or_write)((tag)->cookie,
+ sc->sc_addr,
+ (~(sc->sc_led_state) & 1));
+ /* GPIO LED input ON=0/OFF=1 */
+}
+
+/*
+ * Setting LED interface for inside kernel.
+ * Argumnt `led' is 3-bit LED state (led=0-7/ON=1/OFF=0).
+ */
void
obs266_led_set(int led)
{
struct device *dp = NULL;
struct devicelist *dlp = &alldevs;
+ /*
+ * Sarching "obsled" devices from device tree.
+ * Do you have something better idea?
+ */
for (dp = TAILQ_FIRST(dlp); dp != NULL; dp = TAILQ_NEXT(dp, dv_list)) {
if (dp->dv_cfdata != NULL
&& strcmp(dp->dv_cfdata->cf_name, "obsled") == 0) {
struct obsled_softc *sc = (struct obsled_softc *)dp;
- gpio_tag_t tag = sc->sc_tag;
- int bit = (led & (1 << dp->dv_unit)) >> dp->dv_unit;
- (*(tag)->io_or_write)((tag)->cookie,
- sc->sc_addr, (~bit & 1));
+ sc->sc_led_state =
+ (led & (1 << dp->dv_unit)) >> dp->dv_unit;
+ obsled_set_state(sc);
}
}
}