Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 24 Jun 2002 14:59:21 +0200
From:      Willem van Engen <wvengen@stack.nl>
To:        freebsd-hackers@freebsd.org
Subject:   smbalert# hook for smbus childs
Message-ID:  <20020624145921.463108fc.wvengen@stack.nl>

next in thread | raw e-mail | index | archive | help

[-- Attachment #1 --]
Hello,

there already is some code for smbalert# handling on intpm
(ENABLE_ALART), but there is no support for handling it in a driver. O2
AudioDJ (OZ162) chips use this signal to indicate that a button was
pressed. So I need a way for a driver to be notified when smbalert#
occurs.

Of course I thought immediately about bus_(setup|teardown)_intr. I wrote
something like that for smbus: bus_(setup|teardown)_alart (see patch),
that works now. But is this The Right Way to do it? I do have some
thoughts on it, but maybe someone more knowledgeable than me could comment
on it.
It might be better to use bus_*_intr instead of bus_*_alart, but one
would need to bus_alloc_resource a slave address and pass that to
bus_setup_intr. But then it makes sense to use those slave address
resources to send smbus commands, right? But how would that fit into the
bus_space_* functions?

- Willem
p.s. I hope I'm clear, english isn't my native language.
[-- Attachment #2 --]
--- sys/dev/smbus/smbconf.c.orig	Mon Jun 24 02:36:25 2002
+++ sys/dev/smbus/smbconf.c	Mon Jun 24 11:00:11 2002
@@ -28,6 +28,9 @@
  */
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/kthread.h>
 #include <sys/module.h>
 #include <sys/bus.h>
 
@@ -35,6 +38,12 @@
 #include <dev/smbus/smbus.h>
 #include "smbus_if.h"
 
+#ifdef ENABLE_ALART
+/* List for alart hooks per slave */
+extern SLIST_HEAD(alarthook_head, alarthook_entry) alarthooks;
+#endif
+
+
 /*
  * smbus_intr()
  */
@@ -174,3 +183,70 @@
 
 	return (0);
 }
+
+#ifdef ENABLE_ALART
+
+MALLOC_DEFINE(M_SMBUS_ALART, "smbusalart", "SMBus alart hook list");
+
+/*
+ * smbus_setup_alart()
+ */
+int
+smbus_setup_alart(device_t dev, u_char slave, int flags,
+			driver_intr_t *handler, void *arg)
+{
+	struct alarthook_entry *entry;
+
+	/* Check if same hook already exists */
+	SLIST_FOREACH(entry, &alarthooks, entries)
+		if (entry->dev == dev && entry->slave == slave)
+			return (EADDRINUSE);
+
+	/* Add this one to the list */
+	MALLOC(entry, struct alarthook_entry*,
+		sizeof(struct alarthook_entry), M_SMBUS_ALART, M_WAITOK);
+	entry->dev=dev;
+	entry->slave=slave;
+	entry->handler=handler;
+	entry->arg=arg;
+	SLIST_INSERT_HEAD(&alarthooks, entry, entries);
+	
+	return (0);
+}
+
+/*
+ * smbus_teardown_alart()
+ */
+int
+smbus_teardown_alart(device_t dev, u_char slave) {
+	struct alarthook_entry *curentry, *foundentry=NULL;
+
+	SLIST_FOREACH(curentry, &alarthooks, entries)
+		if (curentry->dev == dev && curentry->slave == slave)
+			foundentry=curentry;
+
+	if (!foundentry)
+		return (ENXIO);
+
+	SLIST_REMOVE(&alarthooks, foundentry, alarthook_entry, entries);
+	FREE(foundentry,M_SMBUS_ALART);
+
+	return (0);
+}
+
+/*
+ * smbus_alart_intr()
+ */
+void
+smbus_alart_intr(device_t dev, u_char devaddr)
+{
+	struct alarthook_entry *entry;
+
+	/* Call each childfunction with matching slave address */
+	SLIST_FOREACH(entry, &alarthooks, entries)
+		if (entry->slave==devaddr && entry->handler)
+			entry->handler(entry->arg);
+
+	return;
+}
+#endif /* ENABLE_ALART */
--- sys/dev/smbus/smbconf.h.orig	Mon Jun 24 02:37:32 2002
+++ sys/dev/smbus/smbconf.h	Mon Jun 24 03:43:58 2002
@@ -80,6 +80,12 @@
 
 extern u_char smbus_get_addr(device_t);
 
+#ifdef ENABLE_ALART
+extern int smbus_setup_alart(device_t, u_char, int, driver_intr_t*, void*);
+extern int smbus_teardown_alart(device_t, u_char);
+extern void smbus_alart_intr(device_t, u_char);
+#endif
+
 #define smbus_quick(bus,slave,how) \
 	(SMBUS_QUICK(device_get_parent(bus), slave, how))
 #define smbus_sendb(bus,slave,byte) \
--- sys/dev/smbus/smbus.c.orig	Mon Jun 24 02:17:55 2002
+++ sys/dev/smbus/smbus.c	Mon Jun 24 13:13:33 2002
@@ -31,6 +31,7 @@
 #include <sys/kernel.h>
 #include <sys/module.h>
 #include <sys/bus.h> 
+#include <sys/malloc.h>
 
 #include <dev/smbus/smbconf.h>
 #include <dev/smbus/smbus.h>
@@ -48,13 +49,14 @@
  */
 static int smbus_probe(device_t);
 static int smbus_attach(device_t);
+static int smbus_detach(device_t);
 static int smbus_add_child(device_t dev, int order, const char *name, int unit);
 
 static device_method_t smbus_methods[] = {
         /* device interface */
         DEVMETHOD(device_probe,         smbus_probe),
         DEVMETHOD(device_attach,        smbus_attach),
-        DEVMETHOD(device_detach,        bus_generic_detach),
+        DEVMETHOD(device_detach,        smbus_detach),
 
         /* bus interface */
         DEVMETHOD(bus_add_child,	smbus_add_child),
@@ -69,6 +71,12 @@
         sizeof(struct smbus_softc),
 };
 
+#ifdef ENABLE_ALART
+/* List for alart hooks per slave */
+SLIST_HEAD(alarthook_head, alarthook_entry) alarthooks =
+	SLIST_HEAD_INITIALIZER(alarthooks);
+#endif
+
 /*
  * At 'probe' time, we add all the devices which we know about to the
  * bus.  The generic attach routine will probe and attach them if they
@@ -87,8 +95,30 @@
 {
 	device_add_child(dev, NULL, -1);
 	bus_generic_attach(dev);
+
+#ifdef ENABLE_ALART
+	/* Init list for alart hooks */
+	SLIST_INIT(&alarthooks);
+#endif
          
         return (0);
+}
+
+static int
+smbus_detach(device_t dev)
+{
+#ifdef ENABLE_ALART
+	struct alarthook_entry *entry;
+
+	/* Remove alart hook list */
+	while (!SLIST_EMPTY(&alarthooks)) {
+		entry = SLIST_FIRST(&alarthooks);
+		SLIST_REMOVE_HEAD(&alarthooks, entries);
+		FREE(entry, M_SMBUS_ALART);
+	}
+#endif
+
+	return bus_generic_detach(dev);
 }
 
 static int
--- sys/dev/smbus/smbus.h.orig	Mon Jun 24 02:17:32 2002
+++ sys/dev/smbus/smbus.h	Mon Jun 24 10:44:52 2002
@@ -38,4 +38,16 @@
 
 extern void smbus_generic_intr(device_t dev, u_char devaddr, char low, char high);
 
+#ifdef ENABLE_ALART
+struct alarthook_entry {
+	device_t dev;
+	u_char slave;
+	driver_intr_t *handler;
+	void *arg;
+	SLIST_ENTRY(alarthook_entry) entries;
+};
+
+MALLOC_DECLARE(M_SMBUS_ALART);
+#endif /* ENABLE_ALART */
+
 #endif
--- sys/pci/intpm.c.orig	Sat Jun 22 16:04:16 2002
+++ sys/pci/intpm.c	Mon Jun 24 02:46:19 2002
@@ -297,10 +297,15 @@
 			u_int8_t addr;
 			addr=bus_space_read_1(sc->st,sc->sh,
 					      PIIX4_SMBHSTDAT0);
+#ifdef ENABLE_ALART_VERBOSE
 			printf("ALART_RESPONSE: 0x%x\n", addr);
+#endif
+			smbus_alart_intr(dev, addr);
 		}
 	}else{
+#ifdef ENABLE_ALART_VERBOSE
 	        printf("ERROR\n");
+#endif
 	}
 
 	/*Re-enable INTR from ALART*/

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20020624145921.463108fc.wvengen>