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