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.
--- 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*/

Reply via email to