diff options
-rw-r--r-- | sys/dev/ichsmb/ichsmb.c | 50 | ||||
-rw-r--r-- | sys/dev/ichsmb/ichsmb_pci.c | 30 | ||||
-rw-r--r-- | sys/pci/alpm.c | 114 | ||||
-rw-r--r-- | sys/pci/amdpm.c | 84 | ||||
-rw-r--r-- | sys/pci/amdsmb.c | 47 | ||||
-rw-r--r-- | sys/pci/intpm.c | 848 | ||||
-rw-r--r-- | sys/pci/intpmreg.h | 2 | ||||
-rw-r--r-- | sys/pci/nfsmb.c | 57 | ||||
-rw-r--r-- | sys/pci/viapm.c | 111 |
9 files changed, 765 insertions, 578 deletions
diff --git a/sys/dev/ichsmb/ichsmb.c b/sys/dev/ichsmb/ichsmb.c index 18aa32b..a12f287 100644 --- a/sys/dev/ichsmb/ichsmb.c +++ b/sys/dev/ichsmb/ichsmb.c @@ -71,7 +71,7 @@ __FBSDID("$FreeBSD$"); #define ICHSMB_DEBUG 0 #if ICHSMB_DEBUG != 0 && defined(__CC_SUPPORTS___FUNC__) #define DBG(fmt, args...) \ - do { log(LOG_DEBUG, "%s: " fmt, __func__ , ## args); } while (0) + do { printf("%s: " fmt, __func__ , ## args); } while (0) #else #define DBG(fmt, args...) do { } while (0) #endif @@ -110,26 +110,38 @@ ichsmb_attach(device_t dev) const sc_p sc = device_get_softc(dev); int error; + /* Create mutex */ + mtx_init(&sc->mutex, device_get_nameunit(dev), "ichsmb", MTX_DEF); + /* Add child: an instance of the "smbus" device */ if ((sc->smb = device_add_child(dev, DRIVER_SMBUS, -1)) == NULL) { - log(LOG_ERR, "%s: no \"%s\" child found\n", - device_get_nameunit(dev), DRIVER_SMBUS); - return (ENXIO); + device_printf(dev, "no \"%s\" child found\n", DRIVER_SMBUS); + error = ENXIO; + goto fail; } /* Clear interrupt conditions */ bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_STA, 0xff); - /* Add "smbus" child */ + /* Set up interrupt handler */ + error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC, + ichsmb_device_intr, sc, &sc->irq_handle); + if (error != 0) { + device_printf(dev, "can't setup irq\n"); + goto fail; + } + + /* Attach "smbus" child */ if ((error = bus_generic_attach(dev)) != 0) { - log(LOG_ERR, "%s: failed to attach child: %d\n", - device_get_nameunit(dev), error); - return (ENXIO); + device_printf(dev, "failed to attach child: %d\n", error); + goto fail; } - /* Create mutex */ - mtx_init(&sc->mutex, device_get_nameunit(dev), "ichsmb", MTX_DEF); return (0); + +fail: + mtx_destroy(&sc->mutex); + return (error); } /******************************************************************** @@ -518,8 +530,8 @@ ichsmb_device_intr(void *cookie) ok_bits |= ichsmb_state_irqs[cmd_index]; } if ((status & ~ok_bits) != 0) { - log(LOG_ERR, "%s: irq 0x%02x during %d\n", - device_get_nameunit(dev), status, cmd_index); + device_printf(dev, "irq 0x%02x during %d\n", status, + cmd_index); bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_STA, (status & ~ok_bits)); continue; @@ -529,12 +541,10 @@ ichsmb_device_intr(void *cookie) if (status & ICH_HST_STA_SMBALERT_STS) { static int smbalert_count = 16; if (smbalert_count > 0) { - log(LOG_WARNING, "%s: SMBALERT# rec'd\n", - device_get_nameunit(dev)); + device_printf(dev, "SMBALERT# rec'd\n"); if (--smbalert_count == 0) { - log(LOG_WARNING, - "%s: not logging anymore\n", - device_get_nameunit(dev)); + device_printf(dev, + "not logging anymore\n"); } } } @@ -609,8 +619,7 @@ finished: /* Too many loops? */ if (count == maxloops) { - log(LOG_ERR, "%s: interrupt loop, status=0x%02x\n", - device_get_nameunit(dev), + device_printf(dev, "interrupt loop, status=0x%02x\n", bus_space_read_1(sc->io_bst, sc->io_bsh, ICH_HST_STA)); } } @@ -635,8 +644,7 @@ ichsmb_wait(sc_p sc) smb_error = sc->smb_error; break; case EWOULDBLOCK: - log(LOG_ERR, "%s: device timeout, status=0x%02x\n", - device_get_nameunit(dev), + device_printf(dev, "device timeout, status=0x%02x\n", bus_space_read_1(sc->io_bst, sc->io_bsh, ICH_HST_STA)); sc->ich_cmd = -1; smb_error = SMB_ETIMEOUT; diff --git a/sys/dev/ichsmb/ichsmb_pci.c b/sys/dev/ichsmb/ichsmb_pci.c index 54c3b97..336c01c 100644 --- a/sys/dev/ichsmb/ichsmb_pci.c +++ b/sys/dev/ichsmb/ichsmb_pci.c @@ -164,7 +164,6 @@ static int ichsmb_pci_attach(device_t dev) { const sc_p sc = device_get_softc(dev); - u_int32_t cmd; int error; /* Initialize private state */ @@ -180,7 +179,7 @@ ichsmb_pci_attach(device_t dev) sc->io_res = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->io_rid, 0, ~0, 32, RF_ACTIVE); if (sc->io_res == NULL) { - log(LOG_ERR, "%s: can't map I/O\n", device_get_nameunit(dev)); + device_printf(dev, "can't map I/O\n"); error = ENXIO; goto fail; } @@ -192,27 +191,7 @@ ichsmb_pci_attach(device_t dev) sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irq_rid, RF_ACTIVE | RF_SHAREABLE); if (sc->irq_res == NULL) { - log(LOG_ERR, "%s: can't get IRQ\n", device_get_nameunit(dev)); - error = ENXIO; - goto fail; - } - - /* Set up interrupt handler */ - error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC, - ichsmb_device_intr, sc, &sc->irq_handle); - if (error != 0) { - log(LOG_ERR, "%s: can't setup irq\n", device_get_nameunit(dev)); - goto fail; - } - - /* Enable I/O mapping */ - cmd = pci_read_config(dev, PCIR_COMMAND, 4); - cmd |= PCIM_CMD_PORTEN; - pci_write_config(dev, PCIR_COMMAND, cmd, 4); - cmd = pci_read_config(dev, PCIR_COMMAND, 4); - if ((cmd & PCIM_CMD_PORTEN) == 0) { - log(LOG_ERR, "%s: can't enable memory map\n", - device_get_nameunit(dev)); + device_printf(dev, "can't get IRQ\n"); error = ENXIO; goto fail; } @@ -221,7 +200,10 @@ ichsmb_pci_attach(device_t dev) pci_write_config(dev, ICH_HOSTC, ICH_HOSTC_HST_EN, 1); /* Done */ - return (ichsmb_attach(dev)); + error = ichsmb_attach(dev); + if (error) + goto fail; + return (0); fail: /* Attach failed, release resources */ diff --git a/sys/pci/alpm.c b/sys/pci/alpm.c index d90d919..53b2f9d 100644 --- a/sys/pci/alpm.c +++ b/sys/pci/alpm.c @@ -32,11 +32,12 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> +#include <sys/bus.h> #include <sys/kernel.h> -#include <sys/systm.h> +#include <sys/lock.h> #include <sys/module.h> -#include <sys/bus.h> -#include <sys/uio.h> +#include <sys/mutex.h> +#include <sys/systm.h> #include <machine/bus.h> #include <machine/resource.h> @@ -45,7 +46,6 @@ __FBSDID("$FreeBSD$"); #include <dev/pci/pcivar.h> #include <dev/pci/pcireg.h> -#include <dev/iicbus/iiconf.h> #include <dev/smbus/smbconf.h> #include "smbus_if.h" @@ -59,10 +59,8 @@ static int alpm_debug = 0; #define ACER_M1543_PMU_ID 0x710110b9 -/* Uncomment this line to force another I/O base address for SMB */ -/* #define ALPM_SMBIO_BASE_ADDR 0x3a80 */ - -/* I/O registers offsets - the base address is programmed via the +/* + * I/O registers offsets - the base address is programmed via the * SMBBA PCI configuration register */ #define SMBSTS 0x0 /* SMBus host/slave status register */ @@ -74,6 +72,9 @@ static int alpm_debug = 0; #define SMBHBLOCK 0x6 /* block register for host controller */ #define SMBHCMD 0x7 /* command register for host controller */ +/* SMBHADDR mask. */ +#define LSB 0x1 /* XXX: Better name: Read/Write? */ + /* SMBSTS masks */ #define TERMINATE 0x80 #define BUS_COLLI 0x40 @@ -101,7 +102,7 @@ static int alpm_debug = 0; #define COM 0x4 #define COM_ENABLE_IO 0x1 -#define SMBBA 0x14 +#define SMBBA PCIR_BAR(1) #define ATPC 0x5b #define ATPC_SMBCTRL 0x04 /* XX linux has this as 0x6 */ @@ -126,44 +127,27 @@ struct alpm_softc { bus_space_tag_t smbst; bus_space_handle_t smbsh; device_t smbus; + struct mtx lock; }; +#define ALPM_LOCK(alpm) mtx_lock(&(alpm)->lock) +#define ALPM_UNLOCK(alpm) mtx_unlock(&(alpm)->lock) +#define ALPM_LOCK_ASSERT(alpm) mtx_assert(&(alpm)->lock, MA_OWNED) + #define ALPM_SMBINB(alpm,register) \ (bus_space_read_1(alpm->smbst, alpm->smbsh, register)) #define ALPM_SMBOUTB(alpm,register,value) \ (bus_space_write_1(alpm->smbst, alpm->smbsh, register, value)) +static int alpm_detach(device_t dev); + static int alpm_probe(device_t dev) { -#ifdef ALPM_SMBIO_BASE_ADDR - u_int32_t l; -#endif if (pci_get_devid(dev) == ACER_M1543_PMU_ID) { device_set_desc(dev, "AcerLabs M15x3 Power Management Unit"); -#ifdef ALPM_SMBIO_BASE_ADDR - if (bootverbose || alpm_debug) - device_printf(dev, "forcing base I/O at 0x%x\n", - ALPM_SMBIO_BASE_ADDR); - - /* disable I/O */ - l = pci_read_config(dev, COM, 2); - pci_write_config(dev, COM, l & ~COM_ENABLE_IO, 2); - - /* set the I/O base address */ - pci_write_config(dev, SMBBA, ALPM_SMBIO_BASE_ADDR | 0x1, 4); - - /* enable I/O */ - pci_write_config(dev, COM, l | COM_ENABLE_IO, 2); - - if (bus_set_resource(dev, SYS_RES_IOPORT, SMBBA, - ALPM_SMBIO_BASE_ADDR, 256)) { - device_printf(dev, "could not set bus resource\n"); - return (ENXIO); - } -#endif return (BUS_PROBE_DEFAULT); } @@ -234,9 +218,14 @@ alpm_attach(device_t dev) } alpm->smbst = rman_get_bustag(alpm->res); alpm->smbsh = rman_get_bushandle(alpm->res); + mtx_init(&alpm->lock, device_get_nameunit(dev), "alpm", MTX_DEF); /* attach the smbus */ alpm->smbus = device_add_child(dev, "smbus", -1); + if (alpm->smbus == NULL) { + alpm_detach(dev); + return (EINVAL); + } bus_generic_attach(dev); return (0); @@ -251,6 +240,7 @@ alpm_detach(device_t dev) device_delete_child(dev, alpm->smbus); alpm->smbus = NULL; } + mtx_destroy(&alpm->lock); if (alpm->res) bus_release_resource(dev, SYS_RES_IOPORT, SMBBA, alpm->res); @@ -317,7 +307,7 @@ alpm_wait(struct alpm_softc *sc) int error; /* wait for command to complete and SMBus controller is idle */ - while(count--) { + while (count--) { DELAY(10); sts = ALPM_SMBINB(sc, SMBSTS); if (sts & SMI_I_STS) @@ -352,9 +342,12 @@ alpm_quick(device_t dev, u_char slave, int how) struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev); int error; + ALPM_LOCK(sc); alpm_clear(sc); - if (!alpm_idle(sc)) + if (!alpm_idle(sc)) { + ALPM_UNLOCK(sc); return (EBUSY); + } switch (how) { case SMB_QWRITE: @@ -375,6 +368,7 @@ alpm_quick(device_t dev, u_char slave, int how) error = alpm_wait(sc); ALPM_DEBUG(printf(", error=0x%x\n", error)); + ALPM_UNLOCK(sc); return (error); } @@ -385,9 +379,12 @@ alpm_sendb(device_t dev, u_char slave, char byte) struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev); int error; + ALPM_LOCK(sc); alpm_clear(sc); - if (!alpm_idle(sc)) + if (!alpm_idle(sc)) { + ALPM_UNLOCK(sc); return (SMB_EBUSY); + } ALPM_SMBOUTB(sc, SMBHADDR, slave & ~LSB); ALPM_SMBOUTB(sc, SMBCMD, SMBSRBYTE); @@ -397,6 +394,7 @@ alpm_sendb(device_t dev, u_char slave, char byte) error = alpm_wait(sc); ALPM_DEBUG(printf("alpm: SENDB to 0x%x, byte=0x%x, error=0x%x\n", slave, byte, error)); + ALPM_UNLOCK(sc); return (error); } @@ -407,9 +405,12 @@ alpm_recvb(device_t dev, u_char slave, char *byte) struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev); int error; + ALPM_LOCK(sc); alpm_clear(sc); - if (!alpm_idle(sc)) + if (!alpm_idle(sc)) { + ALPM_UNLOCK(sc); return (SMB_EBUSY); + } ALPM_SMBOUTB(sc, SMBHADDR, slave | LSB); ALPM_SMBOUTB(sc, SMBCMD, SMBSRBYTE); @@ -419,6 +420,7 @@ alpm_recvb(device_t dev, u_char slave, char *byte) *byte = ALPM_SMBINB(sc, SMBHDATA); ALPM_DEBUG(printf("alpm: RECVB from 0x%x, byte=0x%x, error=0x%x\n", slave, *byte, error)); + ALPM_UNLOCK(sc); return (error); } @@ -429,9 +431,12 @@ alpm_writeb(device_t dev, u_char slave, char cmd, char byte) struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev); int error; + ALPM_LOCK(sc); alpm_clear(sc); - if (!alpm_idle(sc)) + if (!alpm_idle(sc)) { + ALPM_UNLOCK(sc); return (SMB_EBUSY); + } ALPM_SMBOUTB(sc, SMBHADDR, slave & ~LSB); ALPM_SMBOUTB(sc, SMBCMD, SMBWRBYTE); @@ -442,6 +447,7 @@ alpm_writeb(device_t dev, u_char slave, char cmd, char byte) error = alpm_wait(sc); ALPM_DEBUG(printf("alpm: WRITEB to 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, byte, error)); + ALPM_UNLOCK(sc); return (error); } @@ -452,9 +458,12 @@ alpm_readb(device_t dev, u_char slave, char cmd, char *byte) struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev); int error; + ALPM_LOCK(sc); alpm_clear(sc); - if (!alpm_idle(sc)) + if (!alpm_idle(sc)) { + ALPM_UNLOCK(sc); return (SMB_EBUSY); + } ALPM_SMBOUTB(sc, SMBHADDR, slave | LSB); ALPM_SMBOUTB(sc, SMBCMD, SMBWRBYTE); @@ -465,6 +474,7 @@ alpm_readb(device_t dev, u_char slave, char cmd, char *byte) *byte = ALPM_SMBINB(sc, SMBHDATA); ALPM_DEBUG(printf("alpm: READB from 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, *byte, error)); + ALPM_UNLOCK(sc); return (error); } @@ -475,9 +485,12 @@ alpm_writew(device_t dev, u_char slave, char cmd, short word) struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev); int error; + ALPM_LOCK(sc); alpm_clear(sc); - if (!alpm_idle(sc)) + if (!alpm_idle(sc)) { + ALPM_UNLOCK(sc); return (SMB_EBUSY); + } ALPM_SMBOUTB(sc, SMBHADDR, slave & ~LSB); ALPM_SMBOUTB(sc, SMBCMD, SMBWRWORD); @@ -489,6 +502,7 @@ alpm_writew(device_t dev, u_char slave, char cmd, short word) error = alpm_wait(sc); ALPM_DEBUG(printf("alpm: WRITEW to 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, word, error)); + ALPM_UNLOCK(sc); return (error); } @@ -500,9 +514,12 @@ alpm_readw(device_t dev, u_char slave, char cmd, short *word) int error; u_char high, low; + ALPM_LOCK(sc); alpm_clear(sc); - if (!alpm_idle(sc)) + if (!alpm_idle(sc)) { + ALPM_UNLOCK(sc); return (SMB_EBUSY); + } ALPM_SMBOUTB(sc, SMBHADDR, slave | LSB); ALPM_SMBOUTB(sc, SMBCMD, SMBWRWORD); @@ -517,6 +534,7 @@ alpm_readw(device_t dev, u_char slave, char cmd, short *word) } ALPM_DEBUG(printf("alpm: READW from 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, *word, error)); + ALPM_UNLOCK(sc); return (error); } @@ -530,9 +548,13 @@ alpm_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf) if (count < 1 || count > 32) return (SMB_EINVAL); + + ALPM_LOCK(sc); alpm_clear(sc); - if(!alpm_idle(sc)) + if(!alpm_idle(sc)) { + ALPM_UNLOCK(sc); return (SMB_EBUSY); + } ALPM_SMBOUTB(sc, SMBHADDR, slave & ~LSB); @@ -553,6 +575,7 @@ alpm_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf) error = alpm_wait(sc); ALPM_DEBUG(printf("alpm: WRITEBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error)); + ALPM_UNLOCK(sc); return (error); } @@ -566,9 +589,13 @@ alpm_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf) if (*count < 1 || *count > 32) return (SMB_EINVAL); + + ALPM_LOCK(sc); alpm_clear(sc); - if (!alpm_idle(sc)) + if (!alpm_idle(sc)) { + ALPM_UNLOCK(sc); return (SMB_EBUSY); + } ALPM_SMBOUTB(sc, SMBHADDR, slave | LSB); @@ -595,6 +622,7 @@ alpm_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf) error: ALPM_DEBUG(printf("alpm: READBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, *count, cmd, error)); + ALPM_UNLOCK(sc); return (error); } diff --git a/sys/pci/amdpm.c b/sys/pci/amdpm.c index fb34642..f8ec9c5 100644 --- a/sys/pci/amdpm.c +++ b/sys/pci/amdpm.c @@ -36,11 +36,12 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> +#include <sys/bus.h> #include <sys/kernel.h> -#include <sys/systm.h> +#include <sys/lock.h> #include <sys/module.h> -#include <sys/bus.h> -#include <sys/uio.h> +#include <sys/mutex.h> +#include <sys/systm.h> #include <machine/bus.h> #include <machine/resource.h> @@ -49,7 +50,6 @@ __FBSDID("$FreeBSD$"); #include <dev/pci/pcivar.h> #include <dev/pci/pcireg.h> -#include <dev/iicbus/iiconf.h> #include <dev/smbus/smbconf.h> #include "smbus_if.h" @@ -108,6 +108,8 @@ static int amdpm_debug = 0; #define AMDSMB_GE_CYC_PROCCALL 4 #define AMDSMB_GE_CYC_BLOCK 5 +#define LSB 0x1 /* XXX: Better name: Read/Write? */ + #define AMDSMB_HSTADDR (0x04) #define AMDSMB_HSTDATA (0x06) #define AMDSMB_HSTCMD (0x08) @@ -123,10 +125,14 @@ struct amdpm_softc { struct resource *res; bus_space_tag_t smbst; bus_space_handle_t smbsh; - device_t smbus; + struct mtx lock; }; +#define AMDPM_LOCK(amdpm) mtx_lock(&(amdpm)->lock) +#define AMDPM_UNLOCK(amdpm) mtx_unlock(&(amdpm)->lock) +#define AMDPM_LOCK_ASSERT(amdpm) mtx_assert(&(amdpm)->lock, MA_OWNED) + #define AMDPM_SMBINB(amdpm,register) \ (bus_space_read_1(amdpm->smbst, amdpm->smbsh, register)) #define AMDPM_SMBOUTB(amdpm,register,value) \ @@ -136,6 +142,8 @@ struct amdpm_softc { #define AMDPM_SMBOUTW(amdpm,register,value) \ (bus_space_write_2(amdpm->smbst, amdpm->smbsh, register, value)) +static int amdpm_detach(device_t dev); + static int amdpm_probe(device_t dev) { @@ -207,11 +215,14 @@ amdpm_attach(device_t dev) amdpm_sc->smbst = rman_get_bustag(amdpm_sc->res); amdpm_sc->smbsh = rman_get_bushandle(amdpm_sc->res); + mtx_init(&amdpm_sc->lock, device_get_nameunit(dev), "amdpm", MTX_DEF); /* Allocate a new smbus device */ amdpm_sc->smbus = device_add_child(dev, "smbus", -1); - if (!amdpm_sc->smbus) + if (!amdpm_sc->smbus) { + amdpm_detach(dev); return (EINVAL); + } bus_generic_attach(dev); @@ -228,6 +239,7 @@ amdpm_detach(device_t dev) amdpm_sc->smbus = NULL; } + mtx_destroy(&amdpm_sc->lock); if (amdpm_sc->res) bus_release_resource(dev, SYS_RES_IOPORT, amdpm_sc->rid, amdpm_sc->res); @@ -254,6 +266,8 @@ amdpm_callback(device_t dev, int index, void *data) static int amdpm_clear(struct amdpm_softc *sc) { + + AMDPM_LOCK_ASSERT(sc); AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_STATUS, AMDSMB_GS_CLEAR_STS); DELAY(10); @@ -278,6 +292,7 @@ amdpm_idle(struct amdpm_softc *sc) { u_short sts; + AMDPM_LOCK_ASSERT(sc); sts = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_STATUS); AMDPM_DEBUG(printf("amdpm: busy? STS=0x%x\n", sts)); @@ -295,6 +310,7 @@ amdpm_wait(struct amdpm_softc *sc) u_short sts = 0; int error; + AMDPM_LOCK_ASSERT(sc); /* Wait for command to complete (SMBus controller is idle) */ while(count--) { DELAY(10); @@ -332,9 +348,12 @@ amdpm_quick(device_t dev, u_char slave, int how) int error; u_short l; + AMDPM_LOCK(sc); amdpm_clear(sc); - if (!amdpm_idle(sc)) + if (!amdpm_idle(sc)) { + AMDPM_UNLOCK(sc); return (EBUSY); + } switch (how) { case SMB_QWRITE: @@ -354,6 +373,7 @@ amdpm_quick(device_t dev, u_char slave, int how) error = amdpm_wait(sc); AMDPM_DEBUG(printf(", error=0x%x\n", error)); + AMDPM_UNLOCK(sc); return (error); } @@ -365,9 +385,12 @@ amdpm_sendb(device_t dev, u_char slave, char byte) int error; u_short l; + AMDPM_LOCK(sc); amdpm_clear(sc); - if (!amdpm_idle(sc)) + if (!amdpm_idle(sc)) { + AMDPM_UNLOCK(sc); return (SMB_EBUSY); + } AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB); AMDPM_SMBOUTW(sc, AMDSMB_HSTDATA, byte); @@ -377,6 +400,7 @@ amdpm_sendb(device_t dev, u_char slave, char byte) error = amdpm_wait(sc); AMDPM_DEBUG(printf("amdpm: SENDB to 0x%x, byte=0x%x, error=0x%x\n", slave, byte, error)); + AMDPM_UNLOCK(sc); return (error); } @@ -388,9 +412,12 @@ amdpm_recvb(device_t dev, u_char slave, char *byte) int error; u_short l; + AMDPM_LOCK(sc); amdpm_clear(sc); - if (!amdpm_idle(sc)) + if (!amdpm_idle(sc)) { + AMDPM_UNLOCK(sc); return (SMB_EBUSY); + } AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB); l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); @@ -400,6 +427,7 @@ amdpm_recvb(device_t dev, u_char slave, char *byte) *byte = AMDPM_SMBINW(sc, AMDSMB_HSTDATA); AMDPM_DEBUG(printf("amdpm: RECVB from 0x%x, byte=0x%x, error=0x%x\n", slave, *byte, error)); + AMDPM_UNLOCK(sc); return (error); } @@ -411,9 +439,12 @@ amdpm_writeb(device_t dev, u_char slave, char cmd, char byte) int error; u_short l; + AMDPM_LOCK(sc); amdpm_clear(sc); - if (!amdpm_idle(sc)) + if (!amdpm_idle(sc)) { + AMDPM_UNLOCK(sc); return (SMB_EBUSY); + } AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB); AMDPM_SMBOUTW(sc, AMDSMB_HSTDATA, byte); @@ -424,6 +455,7 @@ amdpm_writeb(device_t dev, u_char slave, char cmd, char byte) error = amdpm_wait(sc); AMDPM_DEBUG(printf("amdpm: WRITEB to 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, byte, error)); + AMDPM_UNLOCK(sc); return (error); } @@ -435,9 +467,12 @@ amdpm_readb(device_t dev, u_char slave, char cmd, char *byte) int error; u_short l; + AMDPM_LOCK(sc); amdpm_clear(sc); - if (!amdpm_idle(sc)) + if (!amdpm_idle(sc)) { + AMDPM_UNLOCK(sc); return (SMB_EBUSY); + } AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB); AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd); @@ -448,6 +483,7 @@ amdpm_readb(device_t dev, u_char slave, char cmd, char *byte) *byte = AMDPM_SMBINW(sc, AMDSMB_HSTDATA); AMDPM_DEBUG(printf("amdpm: READB from 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, *byte, error)); + AMDPM_UNLOCK(sc); return (error); } @@ -459,9 +495,12 @@ amdpm_writew(device_t dev, u_char slave, char cmd, short word) int error; u_short l; + AMDPM_LOCK(sc); amdpm_clear(sc); - if (!amdpm_idle(sc)) + if (!amdpm_idle(sc)) { + AMDPM_UNLOCK(sc); return (SMB_EBUSY); + } AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB); AMDPM_SMBOUTW(sc, AMDSMB_HSTDATA, word); @@ -472,6 +511,7 @@ amdpm_writew(device_t dev, u_char slave, char cmd, short word) error = amdpm_wait(sc); AMDPM_DEBUG(printf("amdpm: WRITEW to 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, word, error)); + AMDPM_UNLOCK(sc); return (error); } @@ -483,9 +523,12 @@ amdpm_readw(device_t dev, u_char slave, char cmd, short *word) int error; u_short l; + AMDPM_LOCK(sc); amdpm_clear(sc); - if (!amdpm_idle(sc)) + if (!amdpm_idle(sc)) { + AMDPM_UNLOCK(sc); return (SMB_EBUSY); + } AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB); AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd); @@ -496,6 +539,7 @@ amdpm_readw(device_t dev, u_char slave, char cmd, short *word) *word = AMDPM_SMBINW(sc, AMDSMB_HSTDATA); AMDPM_DEBUG(printf("amdpm: READW from 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, *word, error)); + AMDPM_UNLOCK(sc); return (error); } @@ -510,9 +554,13 @@ amdpm_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf) if (count < 1 || count > 32) return (SMB_EINVAL); + + AMDPM_LOCK(sc); amdpm_clear(sc); - if(!amdpm_idle(sc)) + if (!amdpm_idle(sc)) { + AMDPM_UNLOCK(sc); return (SMB_EBUSY); + } AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB); @@ -535,6 +583,7 @@ amdpm_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf) error = amdpm_wait(sc); AMDPM_DEBUG(printf("amdpm: WRITEBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error)); + AMDPM_UNLOCK(sc); return (error); } @@ -549,9 +598,13 @@ amdpm_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf) if (*count < 1 || *count > 32) return (SMB_EINVAL); + + AMDPM_LOCK(sc); amdpm_clear(sc); - if (!amdpm_idle(sc)) + if (!amdpm_idle(sc)) { + AMDPM_UNLOCK(sc); return (SMB_EBUSY); + } AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB); @@ -577,6 +630,7 @@ amdpm_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf) error: AMDPM_DEBUG(printf("amdpm: READBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, *count, cmd, error)); + AMDPM_UNLOCK(sc); return (error); } diff --git a/sys/pci/amdsmb.c b/sys/pci/amdsmb.c index dde1f12..1b59a5a 100644 --- a/sys/pci/amdsmb.c +++ b/sys/pci/amdsmb.c @@ -2,11 +2,12 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> +#include <sys/bus.h> #include <sys/kernel.h> -#include <sys/systm.h> +#include <sys/lock.h> #include <sys/module.h> -#include <sys/bus.h> -#include <sys/uio.h> +#include <sys/mutex.h> +#include <sys/systm.h> #include <machine/bus.h> #include <machine/resource.h> @@ -15,7 +16,6 @@ __FBSDID("$FreeBSD$"); #include <dev/pci/pcivar.h> #include <dev/pci/pcireg.h> -#include <dev/iicbus/iiconf.h> #include <dev/smbus/smbconf.h> #include "smbus_if.h" @@ -86,15 +86,21 @@ struct amdsmb_softc { struct resource *res; bus_space_tag_t smbst; bus_space_handle_t smbsh; - device_t smbus; + struct mtx lock; }; -#define AMDSMB_ECINB(amdsmb, register) \ +#define AMDSMB_LOCK(amdsmb) mtx_lock(&(amdsmb)->lock) +#define AMDSMB_UNLOCK(amdsmb) mtx_unlock(&(amdsmb)->lock) +#define AMDSMB_LOCK_ASSERT(amdsmb) mtx_assert(&(amdsmb)->lock, MA_OWNED) + +#define AMDSMB_ECINB(amdsmb, register) \ (bus_space_read_1(amdsmb->smbst, amdsmb->smbsh, register)) #define AMDSMB_ECOUTB(amdsmb, register, value) \ (bus_space_write_1(amdsmb->smbst, amdsmb->smbsh, register, value)) +static int amdsmb_detach(device_t dev); + static int amdsmb_probe(device_t dev) { @@ -133,11 +139,14 @@ amdsmb_attach(device_t dev) amdsmb_sc->smbst = rman_get_bustag(amdsmb_sc->res); amdsmb_sc->smbsh = rman_get_bushandle(amdsmb_sc->res); + mtx_init(&amdsmb_sc->lock, device_get_nameunit(dev), "amdsmb", MTX_DEF); /* Allocate a new smbus device */ amdsmb_sc->smbus = device_add_child(dev, "smbus", -1); - if (!amdsmb_sc->smbus) + if (!amdsmb_sc->smbus) { + amdsmb_detach(dev); return (EINVAL); + } bus_generic_attach(dev); @@ -154,6 +163,7 @@ amdsmb_detach(device_t dev) amdsmb_sc->smbus = NULL; } + mtx_destroy(&amdsmb_sc->lock); if (amdsmb_sc->res) bus_release_resource(dev, SYS_RES_IOPORT, amdsmb_sc->rid, amdsmb_sc->res); @@ -209,6 +219,7 @@ static int amdsmb_ec_read(struct amdsmb_softc *sc, u_char addr, u_char *data) { + AMDSMB_LOCK_ASSERT(sc); if (amdsmb_ec_wait_write(sc)) return (1); AMDSMB_ECOUTB(sc, EC_CMD, EC_CMD_RD); @@ -228,6 +239,7 @@ static int amdsmb_ec_write(struct amdsmb_softc *sc, u_char addr, u_char data) { + AMDSMB_LOCK_ASSERT(sc); if (amdsmb_ec_wait_write(sc)) return (1); AMDSMB_ECOUTB(sc, EC_CMD, EC_CMD_WR); @@ -249,6 +261,7 @@ amdsmb_wait(struct amdsmb_softc *sc) u_char sts, temp; int error, count; + AMDSMB_LOCK_ASSERT(sc); amdsmb_ec_read(sc, SMB_PRTCL, &temp); if (temp != 0) { @@ -313,12 +326,14 @@ amdsmb_quick(device_t dev, u_char slave, int how) panic("%s: unknown QUICK command (%x)!", __func__, how); } + AMDSMB_LOCK(sc); amdsmb_ec_write(sc, SMB_ADDR, slave); amdsmb_ec_write(sc, SMB_PRTCL, protocol); error = amdsmb_wait(sc); AMDSMB_DEBUG(printf(", error=0x%x\n", error)); + AMDSMB_UNLOCK(sc); return (error); } @@ -329,6 +344,7 @@ amdsmb_sendb(device_t dev, u_char slave, char byte) struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev); int error; + AMDSMB_LOCK(sc); amdsmb_ec_write(sc, SMB_CMD, byte); amdsmb_ec_write(sc, SMB_ADDR, slave); amdsmb_ec_write(sc, SMB_PRTCL, SMB_PRTCL_WRITE | SMB_PRTCL_BYTE); @@ -337,6 +353,7 @@ amdsmb_sendb(device_t dev, u_char slave, char byte) AMDSMB_DEBUG(printf("amdsmb: SENDB to 0x%x, byte=0x%x, error=0x%x\n", slave, byte, error)); + AMDSMB_UNLOCK(sc); return (error); } @@ -347,6 +364,7 @@ amdsmb_recvb(device_t dev, u_char slave, char *byte) struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev); int error; + AMDSMB_LOCK(sc); amdsmb_ec_write(sc, SMB_ADDR, slave); amdsmb_ec_write(sc, SMB_PRTCL, SMB_PRTCL_READ | SMB_PRTCL_BYTE); @@ -355,6 +373,7 @@ amdsmb_recvb(device_t dev, u_char slave, char *byte) AMDSMB_DEBUG(printf("amdsmb: RECVB from 0x%x, byte=0x%x, error=0x%x\n", slave, *byte, error)); + AMDSMB_UNLOCK(sc); return (error); } @@ -365,6 +384,7 @@ amdsmb_writeb(device_t dev, u_char slave, char cmd, char byte) struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev); int error; + AMDSMB_LOCK(sc); amdsmb_ec_write(sc, SMB_CMD, cmd); amdsmb_ec_write(sc, SMB_DATA, byte); amdsmb_ec_write(sc, SMB_ADDR, slave); @@ -374,6 +394,7 @@ amdsmb_writeb(device_t dev, u_char slave, char cmd, char byte) AMDSMB_DEBUG(printf("amdsmb: WRITEB to 0x%x, cmd=0x%x, byte=0x%x, " "error=0x%x\n", slave, cmd, byte, error)); + AMDSMB_UNLOCK(sc); return (error); } @@ -384,6 +405,7 @@ amdsmb_readb(device_t dev, u_char slave, char cmd, char *byte) struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev); int error; + AMDSMB_LOCK(sc); amdsmb_ec_write(sc, SMB_CMD, cmd); amdsmb_ec_write(sc, SMB_ADDR, slave); amdsmb_ec_write(sc, SMB_PRTCL, SMB_PRTCL_READ | SMB_PRTCL_BYTE_DATA); @@ -393,6 +415,7 @@ amdsmb_readb(device_t dev, u_char slave, char cmd, char *byte) AMDSMB_DEBUG(printf("amdsmb: READB from 0x%x, cmd=0x%x, byte=0x%x, " "error=0x%x\n", slave, cmd, (unsigned char)*byte, error)); + AMDSMB_UNLOCK(sc); return (error); } @@ -403,6 +426,7 @@ amdsmb_writew(device_t dev, u_char slave, char cmd, short word) struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev); int error; + AMDSMB_LOCK(sc); amdsmb_ec_write(sc, SMB_CMD, cmd); amdsmb_ec_write(sc, SMB_DATA, word); amdsmb_ec_write(sc, SMB_DATA + 1, word >> 8); @@ -413,6 +437,7 @@ amdsmb_writew(device_t dev, u_char slave, char cmd, short word) AMDSMB_DEBUG(printf("amdsmb: WRITEW to 0x%x, cmd=0x%x, word=0x%x, " "error=0x%x\n", slave, cmd, word, error)); + AMDSMB_UNLOCK(sc); return (error); } @@ -424,6 +449,7 @@ amdsmb_readw(device_t dev, u_char slave, char cmd, short *word) u_char temp[2]; int error; + AMDSMB_LOCK(sc); amdsmb_ec_write(sc, SMB_CMD, cmd); amdsmb_ec_write(sc, SMB_ADDR, slave); amdsmb_ec_write(sc, SMB_PRTCL, SMB_PRTCL_READ | SMB_PRTCL_WORD_DATA); @@ -436,6 +462,7 @@ amdsmb_readw(device_t dev, u_char slave, char cmd, short *word) AMDSMB_DEBUG(printf("amdsmb: READW from 0x%x, cmd=0x%x, word=0x%x, " "error=0x%x\n", slave, cmd, (unsigned short)*word, error)); + AMDSMB_UNLOCK(sc); return (error); } @@ -449,6 +476,8 @@ amdsmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf) if (count < 1 || count > 32) return (SMB_EINVAL); + + AMDSMB_LOCK(sc); amdsmb_ec_write(sc, SMB_CMD, cmd); amdsmb_ec_write(sc, SMB_BCNT, count); for (i = 0; i < count; i++) @@ -460,6 +489,7 @@ amdsmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf) AMDSMB_DEBUG(printf("amdsmb: WRITEBLK to 0x%x, count=0x%x, cmd=0x%x, " "error=0x%x", slave, count, cmd, error)); + AMDSMB_UNLOCK(sc); return (error); } @@ -473,6 +503,8 @@ amdsmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf) if (*count < 1 || *count > 32) return (SMB_EINVAL); + + AMDSMB_LOCK(sc); amdsmb_ec_write(sc, SMB_CMD, cmd); amdsmb_ec_write(sc, SMB_ADDR, slave); amdsmb_ec_write(sc, SMB_PRTCL, SMB_PRTCL_READ | SMB_PRTCL_BLOCK_DATA); @@ -489,6 +521,7 @@ amdsmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf) AMDSMB_DEBUG(printf("amdsmb: READBLK to 0x%x, count=0x%x, cmd=0x%x, " "error=0x%x", slave, *count, cmd, error)); + AMDSMB_UNLOCK(sc); return (error); } diff --git a/sys/pci/intpm.c b/sys/pci/intpm.c index 75a1b2b..d13ef07 100644 --- a/sys/pci/intpm.c +++ b/sys/pci/intpm.c @@ -29,47 +29,43 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/systm.h> +#include <sys/bus.h> #include <sys/kernel.h> -#include <machine/bus.h> - -#include <sys/uio.h> +#include <sys/lock.h> #include <sys/module.h> -#include <sys/bus.h> +#include <sys/mutex.h> #include <sys/rman.h> -#include <machine/resource.h> +#include <machine/bus.h> #include <dev/smbus/smbconf.h> #include "smbus_if.h" -/*This should be removed if force_pci_map_int supported*/ -#include <sys/interrupt.h> - #include <dev/pci/pcireg.h> #include <dev/pci/pcivar.h> #include <pci/intpmreg.h> #include "opt_intpm.h" -static struct _pcsid -{ - u_int32_t type; - char *desc; -} pci_ids[] = { - { 0x71138086, "Intel 82371AB Power management controller" }, - { 0x719b8086, "Intel 82443MX Power management controller" }, -#if 0 - /* Not a good idea yet, this stops isab0 functioning */ - { 0x02001166, "ServerWorks OSB4 PCI to ISA Bridge" }, -#endif - - { 0x00000000, NULL } +struct intsmb_softc { + device_t dev; + struct resource *io_res; + struct resource *irq_res; + void *irq_hand; + device_t smbus; + int isbusy; + struct mtx lock; }; +#define INTSMB_LOCK(sc) mtx_lock(&(sc)->lock) +#define INTSMB_UNLOCK(sc) mtx_unlock(&(sc)->lock) +#define INTSMB_LOCK_ASSERT(sc) mtx_assert(&(sc)->lock, MA_OWNED) + static int intsmb_probe(device_t); static int intsmb_attach(device_t); -static int intsmb_intr(device_t dev); -static int intsmb_slvintr(device_t dev); -static void intsmb_alrintr(device_t dev); +static int intsmb_detach(device_t); +static int intsmb_intr(struct intsmb_softc *sc); +static int intsmb_slvintr(struct intsmb_softc *sc); +static void intsmb_alrintr(struct intsmb_softc *sc); static int intsmb_callback(device_t dev, int index, void *data); static int intsmb_quick(device_t dev, u_char slave, int how); static int intsmb_sendb(device_t dev, u_char slave, char byte); @@ -81,116 +77,160 @@ static int intsmb_readw(device_t dev, u_char slave, char cmd, short *word); static int intsmb_pcall(device_t dev, u_char slave, char cmd, short sdata, short *rdata); static int intsmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf); static int intsmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf); -static void intsmb_start(device_t dev, u_char cmd, int nointr); -static int intsmb_stop(device_t dev); -static int intsmb_stop_poll(device_t dev); -static int intsmb_free(device_t dev); -static int intpm_probe (device_t dev); -static int intpm_attach (device_t dev); -static void intpm_intr(void *arg); +static void intsmb_start(struct intsmb_softc *sc, u_char cmd, int nointr); +static int intsmb_stop(struct intsmb_softc *sc); +static int intsmb_stop_poll(struct intsmb_softc *sc); +static int intsmb_free(struct intsmb_softc *sc); +static void intsmb_rawintr(void *arg); -static devclass_t intsmb_devclass; +static int +intsmb_probe(device_t dev) +{ -static device_method_t intpm_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, intsmb_probe), - DEVMETHOD(device_attach, intsmb_attach), + switch (pci_get_devid(dev)) { + case 0x71138086: /* Intel 82371AB */ + case 0x719b8086: /* Intel 82443MX */ +#if 0 + /* Not a good idea yet, this stops isab0 functioning */ + case 0x02001166: /* ServerWorks OSB4 */ +#endif + device_set_desc(dev, "Intel PIIX4 SMBUS Interface"); + break; + default: + return (ENXIO); + } - /* Bus interface */ - DEVMETHOD(bus_print_child, bus_generic_print_child), + return (BUS_PROBE_DEFAULT); +} - /* SMBus interface */ - DEVMETHOD(smbus_callback, intsmb_callback), - DEVMETHOD(smbus_quick, intsmb_quick), - DEVMETHOD(smbus_sendb, intsmb_sendb), - DEVMETHOD(smbus_recvb, intsmb_recvb), - DEVMETHOD(smbus_writeb, intsmb_writeb), - DEVMETHOD(smbus_writew, intsmb_writew), - DEVMETHOD(smbus_readb, intsmb_readb), - DEVMETHOD(smbus_readw, intsmb_readw), - DEVMETHOD(smbus_pcall, intsmb_pcall), - DEVMETHOD(smbus_bwrite, intsmb_bwrite), - DEVMETHOD(smbus_bread, intsmb_bread), +static int +intsmb_attach(device_t dev) +{ + struct intsmb_softc *sc = device_get_softc(dev); + int error, rid, value; + char *str; - { 0, 0 } -}; + sc = device_get_softc(dev); + mtx_init(&sc->lock, device_get_nameunit(dev), "intsmb", MTX_DEF); -struct intpm_pci_softc { - bus_space_tag_t smbst; - bus_space_handle_t smbsh; - bus_space_tag_t pmst; - bus_space_handle_t pmsh; - device_t smbus; -}; + rid = PCI_BASE_ADDR_SMB; + sc->io_res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, + RF_ACTIVE); + if (sc->io_res == NULL) { + device_printf(dev, "Could not allocate I/O space\n"); + error = ENXIO; + goto fail; + } + +#ifndef NO_CHANGE_PCICONF + pci_write_config(dev, PCIR_INTLINE, 0x9, 1); + pci_write_config(dev, PCI_HST_CFG_SMB, + PCI_INTR_SMB_IRQ9 | PCI_INTR_SMB_ENABLE, 1); +#endif + value = pci_read_config(dev, PCI_HST_CFG_SMB, 1); + switch (value & 0xe) { + case PCI_INTR_SMB_SMI: + str = "SMI"; + break; + case PCI_INTR_SMB_IRQ9: + str = "IRQ 9"; + break; + default: + str = "BOGUS"; + } + device_printf(dev, "intr %s %s ", str, + (value & 1) ? "enabled" : "disabled"); + value = pci_read_config(dev, PCI_REVID_SMB, 1); + printf("revision %d\n", value); + if ((value & 0xe) != PCI_INTR_SMB_IRQ9) { + device_printf(dev, "Unsupported interrupt mode\n"); + error = ENXIO; + goto fail; + } -struct intsmb_softc { - struct intpm_pci_softc *pci_sc; - bus_space_tag_t st; - bus_space_handle_t sh; - device_t smbus; - int isbusy; -}; + /* Force IRQ 9. */ + rid = 0; + bus_set_resource(dev, SYS_RES_IRQ, rid, 9, 1); + sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, + RF_SHAREABLE | RF_ACTIVE); + if (sc->irq_res == NULL) { + device_printf(dev, "Could not allocate irq\n"); + error = ENXIO; + goto fail; + } -static driver_t intpm_driver = { - "intsmb", - intpm_methods, - sizeof(struct intsmb_softc), -}; + error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC, intsmb_rawintr, + sc, &sc->irq_hand); + if (error) { + device_printf(dev, "Failed to map intr\n"); + goto fail; + } -static devclass_t intpm_devclass; + value = pci_read_config(dev, PCI_BASE_ADDR_PM, 4); + device_printf(dev, "PM %s %x\n", (value & 1) ? "I/O mapped" : "Memory", + value & 0xfffe); -static device_method_t intpm_pci_methods[] = { - DEVMETHOD(device_probe, intpm_probe), - DEVMETHOD(device_attach, intpm_attach), + sc->isbusy = 0; + sc->smbus = device_add_child(dev, "smbus", -1); + if (sc->smbus == NULL) { + error = ENXIO; + goto fail; + } + error = device_probe_and_attach(sc->smbus); + if (error) + goto fail; - { 0, 0 } -}; +#ifdef ENABLE_ALART + /* Enable Arart */ + bus_write_1(sc->io_res, PIIX4_SMBSLVCNT, PIIX4_SMBSLVCNT_ALTEN); +#endif + return (0); -static driver_t intpm_pci_driver = { - "intpm", - intpm_pci_methods, - sizeof(struct intpm_pci_softc) -}; +fail: + intsmb_detach(dev); + return (error); +} static int -intsmb_probe(device_t dev) +intsmb_detach(device_t dev) { struct intsmb_softc *sc = device_get_softc(dev); + int error; - sc->smbus = device_add_child(dev, "smbus", -1); - if (!sc->smbus) - return (EINVAL); /* XXX don't know what to return else */ - device_set_desc(dev, "Intel PIIX4 SMBUS Interface"); + error = bus_generic_detach(dev); + if (error) + return (error); - return (BUS_PROBE_DEFAULT); /* XXX don't know what to return else */ + if (sc->smbus) + device_delete_child(dev, sc->smbus); + if (sc->irq_hand) + bus_teardown_intr(dev, sc->irq_res, sc->irq_hand); + if (sc->irq_res) + bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res); + if (sc->io_res) + bus_release_resource(dev, SYS_RES_IOPORT, PCI_BASE_ADDR_SMB, + sc->io_res); + mtx_destroy(&sc->lock); + return (0); } -static int -intsmb_attach(device_t dev) + +static void +intsmb_rawintr(void *arg) { - struct intsmb_softc *sc = device_get_softc(dev); + struct intsmb_softc *sc = arg; - sc->pci_sc = device_get_softc(device_get_parent(dev)); - sc->isbusy = 0; - sc->sh = sc->pci_sc->smbsh; - sc->st = sc->pci_sc->smbst; - sc->pci_sc->smbus = dev; - device_probe_and_attach(sc->smbus); -#ifdef ENABLE_ALART - /*Enable Arart*/ - bus_space_write_1(sc->st, sc->sh, PIIX4_SMBSLVCNT, - PIIX4_SMBSLVCNT_ALTEN); -#endif - return (0); + INTSMB_LOCK(sc); + intsmb_intr(sc); + intsmb_slvintr(sc); + INTSMB_UNLOCK(sc); } static int intsmb_callback(device_t dev, int index, void *data) { int error = 0; - intrmask_t s; - s = splnet(); switch (index) { case SMB_REQUEST_BUS: break; @@ -199,56 +239,49 @@ intsmb_callback(device_t dev, int index, void *data) default: error = EINVAL; } - splx(s); return (error); } /* Counterpart of smbtx_smb_free(). */ static int -intsmb_free(device_t dev) +intsmb_free(struct intsmb_softc *sc) { - struct intsmb_softc *sc = device_get_softc(dev); - intrmask_t s; - if ((bus_space_read_1(sc->st, sc->sh, PIIX4_SMBHSTSTS) & - PIIX4_SMBHSTSTAT_BUSY) || + INTSMB_LOCK_ASSERT(sc); + if ((bus_read_1(sc->io_res, PIIX4_SMBHSTSTS) & PIIX4_SMBHSTSTAT_BUSY) || #ifdef ENABLE_ALART - (bus_space_read_1(sc->st, sc->sh, PIIX4_SMBSLVSTS) & - PIIX4_SMBSLVSTS_BUSY) || + (bus_read_1(sc->io_res, PIIX4_SMBSLVSTS) & PIIX4_SMBSLVSTS_BUSY) || #endif sc->isbusy) - return (EBUSY); - s = splhigh(); + return (SMB_EBUSY); + sc->isbusy = 1; /* Disable Interrupt in slave part. */ #ifndef ENABLE_ALART - bus_space_write_1(sc->st, sc->sh, PIIX4_SMBSLVCNT, 0); + bus_write_1(sc->io_res, PIIX4_SMBSLVCNT, 0); #endif /* Reset INTR Flag to prepare INTR. */ - bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTSTS, - (PIIX4_SMBHSTSTAT_INTR | PIIX4_SMBHSTSTAT_ERR | - PIIX4_SMBHSTSTAT_BUSC | PIIX4_SMBHSTSTAT_FAIL)); - splx(s); + bus_write_1(sc->io_res, PIIX4_SMBHSTSTS, + PIIX4_SMBHSTSTAT_INTR | PIIX4_SMBHSTSTAT_ERR | + PIIX4_SMBHSTSTAT_BUSC | PIIX4_SMBHSTSTAT_FAIL); return (0); } static int -intsmb_intr(device_t dev) +intsmb_intr(struct intsmb_softc *sc) { - struct intsmb_softc *sc = device_get_softc(dev); - int status; + int status, tmp; - status = bus_space_read_1(sc->st, sc->sh, PIIX4_SMBHSTSTS); + status = bus_read_1(sc->io_res, PIIX4_SMBHSTSTS); if (status & PIIX4_SMBHSTSTAT_BUSY) return (1); if (status & (PIIX4_SMBHSTSTAT_INTR | PIIX4_SMBHSTSTAT_ERR | PIIX4_SMBHSTSTAT_BUSC | PIIX4_SMBHSTSTAT_FAIL)) { - int tmp; - tmp = bus_space_read_1(sc->st, sc->sh, PIIX4_SMBHSTCNT); - bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTCNT, + tmp = bus_read_1(sc->io_res, PIIX4_SMBHSTCNT); + bus_write_1(sc->io_res, PIIX4_SMBHSTCNT, tmp & ~PIIX4_SMBHSTCNT_INTREN); if (sc->isbusy) { sc->isbusy = 0; @@ -260,78 +293,73 @@ intsmb_intr(device_t dev) } static int -intsmb_slvintr(device_t dev) +intsmb_slvintr(struct intsmb_softc *sc) { - struct intsmb_softc *sc = device_get_softc(dev); - int status, retval; + int status; - retval = 1; - status = bus_space_read_1(sc->st, sc->sh, PIIX4_SMBSLVSTS); + status = bus_read_1(sc->io_res, PIIX4_SMBSLVSTS); if (status & PIIX4_SMBSLVSTS_BUSY) - return (retval); - if (status & PIIX4_SMBSLVSTS_ALART) { - intsmb_alrintr(dev); - retval = 0; - } else if (status & ~(PIIX4_SMBSLVSTS_ALART | PIIX4_SMBSLVSTS_SDW2 + return (1); + if (status & PIIX4_SMBSLVSTS_ALART) + intsmb_alrintr(sc); + else if (status & ~(PIIX4_SMBSLVSTS_ALART | PIIX4_SMBSLVSTS_SDW2 | PIIX4_SMBSLVSTS_SDW1)) { - retval = 0; } /* Reset Status Register */ - bus_space_write_1(sc->st, sc->sh, PIIX4_SMBSLVSTS, + bus_write_1(sc->io_res, PIIX4_SMBSLVSTS, PIIX4_SMBSLVSTS_ALART | PIIX4_SMBSLVSTS_SDW2 | PIIX4_SMBSLVSTS_SDW1 | PIIX4_SMBSLVSTS_SLV); - return (retval); + return (0); } static void -intsmb_alrintr(device_t dev) +intsmb_alrintr(struct intsmb_softc *sc) { - struct intsmb_softc *sc = device_get_softc(dev); int slvcnt; #ifdef ENABLE_ALART int error; + uint8_t addr; #endif /* Stop generating INTR from ALART. */ - slvcnt = bus_space_read_1(sc->st, sc->sh, PIIX4_SMBSLVCNT); + slvcnt = bus_read_1(sc->io_res, PIIX4_SMBSLVCNT); #ifdef ENABLE_ALART - bus_space_write_1(sc->st, sc->sh, PIIX4_SMBSLVCNT, + bus_write_1(sc->io_res, PIIX4_SMBSLVCNT, slvcnt & ~PIIX4_SMBSLVCNT_ALTEN); #endif DELAY(5); /* Ask bus who asserted it and then ask it what's the matter. */ #ifdef ENABLE_ALART - error = intsmb_free(dev); - if (!error) { - bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTADD, - SMBALTRESP | LSB); - intsmb_start(dev, PIIX4_SMBHSTCNT_PROT_BYTE, 1); - if (!(error = intsmb_stop_poll(dev))) { - u_int8_t addr; - - addr = bus_space_read_1(sc->st, sc->sh, - PIIX4_SMBHSTDAT0); - printf("ALART_RESPONSE: 0x%x\n", addr); - } - } else - printf("ERROR\n"); + error = intsmb_free(sc); + if (error) + return; + + bus_write_1(sc->io_res, PIIX4_SMBHSTADD, SMBALTRESP | LSB); + intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_BYTE, 1); + error = intsmb_stop_poll(sc); + if (error) + device_printf(sc->dev, "ALART: ERROR\n"); + else { + addr = bus_read_1(sc->io_res, PIIX4_SMBHSTDAT0); + device_printf(sc->dev, "ALART_RESPONSE: 0x%x\n", addr); + } /* Re-enable INTR from ALART. */ - bus_space_write_1(sc->st, sc->sh, PIIX4_SMBSLVCNT, + bus_write_1(sc->io_res, PIIX4_SMBSLVCNT, slvcnt | PIIX4_SMBSLVCNT_ALTEN); DELAY(5); #endif } static void -intsmb_start(device_t dev, unsigned char cmd, int nointr) +intsmb_start(struct intsmb_softc *sc, unsigned char cmd, int nointr) { - struct intsmb_softc *sc = device_get_softc(dev); unsigned char tmp; - tmp = bus_space_read_1(sc->st, sc->sh, PIIX4_SMBHSTCNT); + INTSMB_LOCK_ASSERT(sc); + tmp = bus_read_1(sc->io_res, PIIX4_SMBHSTCNT); tmp &= 0xe0; tmp |= cmd; tmp |= PIIX4_SMBHSTCNT_START; @@ -339,7 +367,21 @@ intsmb_start(device_t dev, unsigned char cmd, int nointr) /* While not in autoconfiguration enable interrupts. */ if (!cold || !nointr) tmp |= PIIX4_SMBHSTCNT_INTREN; - bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTCNT, tmp); + bus_write_1(sc->io_res, PIIX4_SMBHSTCNT, tmp); +} + +static int +intsmb_error(int status) +{ + int error = 0; + + if (status & PIIX4_SMBHSTSTAT_ERR) + error |= SMB_EBUSERR; + if (status & PIIX4_SMBHSTSTAT_BUSC) + error |= SMB_ECOLLI; + if (status & PIIX4_SMBHSTSTAT_FAIL) + error |= SMB_ENOACK; + return (error); } /* @@ -351,72 +393,60 @@ intsmb_start(device_t dev, unsigned char cmd, int nointr) * polling code then. */ static int -intsmb_stop_poll(device_t dev) +intsmb_stop_poll(struct intsmb_softc *sc) { - struct intsmb_softc *sc = device_get_softc(dev); - int error, i; - int tmp; + int error, i, status, tmp; - /* - * In smbtx driver, Simply waiting. - * This loops 100-200 times. - */ + INTSMB_LOCK_ASSERT(sc); + + /* First, wait for busy to be set. */ for (i = 0; i < 0x7fff; i++) - if (bus_space_read_1(sc->st, sc->sh, PIIX4_SMBHSTSTS) & + if (bus_read_1(sc->io_res, PIIX4_SMBHSTSTS) & PIIX4_SMBHSTSTAT_BUSY) break; + /* Wait for busy to clear. */ for (i = 0; i < 0x7fff; i++) { - int status; - - status = bus_space_read_1(sc->st, sc->sh, PIIX4_SMBHSTSTS); + status = bus_read_1(sc->io_res, PIIX4_SMBHSTSTS); if (!(status & PIIX4_SMBHSTSTAT_BUSY)) { sc->isbusy = 0; - error = (status & PIIX4_SMBHSTSTAT_ERR) ? EIO : - (status & PIIX4_SMBHSTSTAT_BUSC) ? EBUSY : - (status & PIIX4_SMBHSTSTAT_FAIL) ? EIO : 0; + error = intsmb_error(status); if (error == 0 && !(status & PIIX4_SMBHSTSTAT_INTR)) - printf("unknown cause why?"); + device_printf(sc->dev, "unknown cause why?"); return (error); } } + /* Timed out waiting for busy to clear. */ sc->isbusy = 0; - tmp = bus_space_read_1(sc->st, sc->sh, PIIX4_SMBHSTCNT); - bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTCNT, - tmp & ~PIIX4_SMBHSTCNT_INTREN); - return (EIO); + tmp = bus_read_1(sc->io_res, PIIX4_SMBHSTCNT); + bus_write_1(sc->io_res, PIIX4_SMBHSTCNT, tmp & ~PIIX4_SMBHSTCNT_INTREN); + return (SMB_ETIMEOUT); } /* * Wait for completion and return result. */ static int -intsmb_stop(device_t dev) +intsmb_stop(struct intsmb_softc *sc) { - struct intsmb_softc *sc = device_get_softc(dev); - int error; - intrmask_t s; + int error, status; - if (cold) { - /* So that it can use device during device probe on SMBus. */ - error = intsmb_stop_poll(dev); - return (error); - } + INTSMB_LOCK_ASSERT(sc); - if (!tsleep(sc, (PWAIT) | PCATCH, "SMBWAI", hz/8)) { - int status; + if (cold) + /* So that it can use device during device probe on SMBus. */ + return (intsmb_stop_poll(sc)); - status = bus_space_read_1(sc->st, sc->sh, PIIX4_SMBHSTSTS); + error = tsleep(sc, PWAIT | PCATCH, "SMBWAI", hz / 8); + if (error == 0) { + status = bus_read_1(sc->io_res, PIIX4_SMBHSTSTS); if (!(status & PIIX4_SMBHSTSTAT_BUSY)) { - error = (status & PIIX4_SMBHSTSTAT_ERR) ? EIO : - (status & PIIX4_SMBHSTSTAT_BUSC) ? EBUSY : - (status & PIIX4_SMBHSTSTAT_FAIL) ? EIO : 0; + error = intsmb_error(status); if (error == 0 && !(status & PIIX4_SMBHSTSTAT_INTR)) - printf("intsmb%d: unknown cause why?\n", - device_get_unit(dev)); + device_printf(sc->dev, "unknown cause why?\n"); #ifdef ENABLE_ALART - bus_space_write_1(sc->st, sc->sh, PIIX4_SMBSLVCNT, + bus_write_1(sc->io_res, PIIX4_SMBSLVCNT, PIIX4_SMBSLVCNT_ALTEN); #endif return (error); @@ -424,21 +454,21 @@ intsmb_stop(device_t dev) } /* Timeout Procedure. */ - s = splhigh(); sc->isbusy = 0; /* Re-enable supressed interrupt from slave part. */ - bus_space_write_1(sc->st, sc->sh, PIIX4_SMBSLVCNT, - PIIX4_SMBSLVCNT_ALTEN); - splx(s); - return (EIO); + bus_write_1(sc->io_res, PIIX4_SMBSLVCNT, PIIX4_SMBSLVCNT_ALTEN); + if (error == EWOULDBLOCK) + return (SMB_ETIMEOUT); + else + return (SMB_EABORT); } static int intsmb_quick(device_t dev, u_char slave, int how) { struct intsmb_softc *sc = device_get_softc(dev); - int error = 0; + int error; u_char data; data = slave; @@ -452,18 +482,19 @@ intsmb_quick(device_t dev, u_char slave, int how) data |= LSB; break; default: - error = EINVAL; - } - if (!error) { - error = intsmb_free(dev); - if (!error) { - bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTADD, - data); - intsmb_start(dev, PIIX4_SMBHSTCNT_PROT_QUICK, 0); - error = intsmb_stop(dev); - } + return (EINVAL); } + INTSMB_LOCK(sc); + error = intsmb_free(sc); + if (error) { + INTSMB_UNLOCK(sc); + return (error); + } + bus_write_1(sc->io_res, PIIX4_SMBHSTADD, data); + intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_QUICK, 0); + error = intsmb_stop(sc); + INTSMB_UNLOCK(sc); return (error); } @@ -473,14 +504,17 @@ intsmb_sendb(device_t dev, u_char slave, char byte) struct intsmb_softc *sc = device_get_softc(dev); int error; - error = intsmb_free(dev); - if (!error) { - bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTADD, - slave & ~LSB); - bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTCMD, byte); - intsmb_start(dev, PIIX4_SMBHSTCNT_PROT_BYTE, 0); - error = intsmb_stop(dev); + INTSMB_LOCK(sc); + error = intsmb_free(sc); + if (error) { + INTSMB_UNLOCK(sc); + return (error); } + bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave & ~LSB); + bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, byte); + intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_BYTE, 0); + error = intsmb_stop(sc); + INTSMB_UNLOCK(sc); return (error); } @@ -490,24 +524,27 @@ intsmb_recvb(device_t dev, u_char slave, char *byte) struct intsmb_softc *sc = device_get_softc(dev); int error; - error = intsmb_free(dev); - if (!error) { - bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTADD, slave | LSB); - intsmb_start(dev, PIIX4_SMBHSTCNT_PROT_BYTE, 0); - if (!(error = intsmb_stop(dev))) { + INTSMB_LOCK(sc); + error = intsmb_free(sc); + if (error) { + INTSMB_UNLOCK(sc); + return (error); + } + bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave | LSB); + intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_BYTE, 0); + error = intsmb_stop(sc); + if (error == 0) { #ifdef RECV_IS_IN_CMD - /* - * Linux SMBus stuff also troubles - * Because Intel's datasheet does not make clear. - */ - *byte = bus_space_read_1(sc->st, sc->sh, - PIIX4_SMBHSTCMD); + /* + * Linux SMBus stuff also troubles + * Because Intel's datasheet does not make clear. + */ + *byte = bus_read_1(sc->io_res, PIIX4_SMBHSTCMD); #else - *byte = bus_space_read_1(sc->st, sc->sh, - PIIX4_SMBHSTDAT0); + *byte = bus_read_1(sc->io_res, PIIX4_SMBHSTDAT0); #endif - } } + INTSMB_UNLOCK(sc); return (error); } @@ -517,15 +554,18 @@ intsmb_writeb(device_t dev, u_char slave, char cmd, char byte) struct intsmb_softc *sc = device_get_softc(dev); int error; - error = intsmb_free(dev); - if (!error) { - bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTADD, - slave & ~LSB); - bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTCMD, cmd); - bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTDAT0, byte); - intsmb_start(dev, PIIX4_SMBHSTCNT_PROT_BDATA, 0); - error = intsmb_stop(dev); + INTSMB_LOCK(sc); + error = intsmb_free(sc); + if (error) { + INTSMB_UNLOCK(sc); + return (error); } + bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave & ~LSB); + bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, cmd); + bus_write_1(sc->io_res, PIIX4_SMBHSTDAT0, byte); + intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_BDATA, 0); + error = intsmb_stop(sc); + INTSMB_UNLOCK(sc); return (error); } @@ -535,18 +575,19 @@ intsmb_writew(device_t dev, u_char slave, char cmd, short word) struct intsmb_softc *sc = device_get_softc(dev); int error; - error = intsmb_free(dev); - if (!error) { - bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTADD, - slave & ~LSB); - bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTCMD, cmd); - bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTDAT0, - word & 0xff); - bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTDAT1, - (word >> 8) & 0xff); - intsmb_start(dev, PIIX4_SMBHSTCNT_PROT_WDATA, 0); - error = intsmb_stop(dev); + INTSMB_LOCK(sc); + error = intsmb_free(sc); + if (error) { + INTSMB_UNLOCK(sc); + return (error); } + bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave & ~LSB); + bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, cmd); + bus_write_1(sc->io_res, PIIX4_SMBHSTDAT0, word & 0xff); + bus_write_1(sc->io_res, PIIX4_SMBHSTDAT1, (word >> 8) & 0xff); + intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_WDATA, 0); + error = intsmb_stop(sc); + INTSMB_UNLOCK(sc); return (error); } @@ -556,35 +597,43 @@ intsmb_readb(device_t dev, u_char slave, char cmd, char *byte) struct intsmb_softc *sc = device_get_softc(dev); int error; - error = intsmb_free(dev); - if (!error) { - bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTADD, slave | LSB); - bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTCMD, cmd); - intsmb_start(dev, PIIX4_SMBHSTCNT_PROT_BDATA, 0); - if (!(error = intsmb_stop(dev))) - *byte = bus_space_read_1(sc->st, sc->sh, - PIIX4_SMBHSTDAT0); + INTSMB_LOCK(sc); + error = intsmb_free(sc); + if (error) { + INTSMB_UNLOCK(sc); + return (error); } + bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave | LSB); + bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, cmd); + intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_BDATA, 0); + error = intsmb_stop(sc); + if (error == 0) + *byte = bus_read_1(sc->io_res, PIIX4_SMBHSTDAT0); + INTSMB_UNLOCK(sc); return (error); } + static int intsmb_readw(device_t dev, u_char slave, char cmd, short *word) { struct intsmb_softc *sc = device_get_softc(dev); int error; - error = intsmb_free(dev); - if (!error) { - bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTADD, slave | LSB); - bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTCMD, cmd); - intsmb_start(dev, PIIX4_SMBHSTCNT_PROT_WDATA, 0); - if (!(error = intsmb_stop(dev))) { - *word = bus_space_read_1(sc->st, sc->sh, - PIIX4_SMBHSTDAT0); - *word |= bus_space_read_1(sc->st, sc->sh, - PIIX4_SMBHSTDAT1) << 8; - } + INTSMB_LOCK(sc); + error = intsmb_free(sc); + if (error) { + INTSMB_UNLOCK(sc); + return (error); } + bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave | LSB); + bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, cmd); + intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_WDATA, 0); + error = intsmb_stop(sc); + if (error == 0) { + *word = bus_read_1(sc->io_res, PIIX4_SMBHSTDAT0); + *word |= bus_read_1(sc->io_res, PIIX4_SMBHSTDAT1) << 8; + } + INTSMB_UNLOCK(sc); return (error); } @@ -600,25 +649,26 @@ intsmb_pcall(device_t dev, u_char slave, char cmd, short sdata, short *rdata) struct intsmb_softc *sc = device_get_softc(dev); int error; - error = intsmb_free(dev); - if (!error) { - bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTADD, - slave & ~LSB); - bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTCMD, cmd); - bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTDAT0, - sdata & 0xff); - bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTDAT1, - (sdata & 0xff) >> 8); - intsmb_start(dev, PIIX4_SMBHSTCNT_PROT_WDATA, 0); + INTSMB_LOCK(sc); + error = intsmb_free(sc); + if (error) { + INTSMB_UNLOCK(sc); + return (error); } - if (!(error = intsmb_stop(dev))) { - *rdata = bus_space_read_1(sc->st, sc->sh, PIIX4_SMBHSTDAT0); - *rdata |= bus_space_read_1(sc->st, sc->sh, PIIX4_SMBHSTDAT1) << - 8; + bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave & ~LSB); + bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, cmd); + bus_write_1(sc->io_res, PIIX4_SMBHSTDAT0, sdata & 0xff); + bus_write_1(sc->io_res, PIIX4_SMBHSTDAT1, (sdata & 0xff) >> 8); + intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_WDATA, 0); + error = intsmb_stop(sc); + if (error == 0) { + *rdata = bus_read_1(sc->io_res, PIIX4_SMBHSTDAT0); + *rdata |= bus_read_1(sc->io_res, PIIX4_SMBHSTDAT1) << 8; } + INTSMB_UNLOCK(sc); return (error); #else - return (0); + return (SMB_ENOTSUPP); #endif } @@ -628,23 +678,27 @@ intsmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf) struct intsmb_softc *sc = device_get_softc(dev); int error, i; - error = intsmb_free(dev); if (count > SMBBLOCKTRANS_MAX || count == 0) - error = SMB_EINVAL; - if (!error) { - /* Reset internal array index. */ - bus_space_read_1(sc->st, sc->sh, PIIX4_SMBHSTCNT); - - bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTADD, - slave & ~LSB); - bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTCMD, cmd); - for (i = 0; i < count; i++) - bus_space_write_1(sc->st, sc->sh, PIIX4_SMBBLKDAT, - buf[i]); - bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTDAT0, count); - intsmb_start(dev, PIIX4_SMBHSTCNT_PROT_BLOCK, 0); - error = intsmb_stop(dev); + return (SMB_EINVAL); + + INTSMB_LOCK(sc); + error = intsmb_free(sc); + if (error) { + INTSMB_UNLOCK(sc); + return (error); } + + /* Reset internal array index. */ + bus_read_1(sc->io_res, PIIX4_SMBHSTCNT); + + bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave & ~LSB); + bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, cmd); + for (i = 0; i < count; i++) + bus_write_1(sc->io_res, PIIX4_SMBBLKDAT, buf[i]); + bus_write_1(sc->io_res, PIIX4_SMBHSTDAT0, count); + intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_BLOCK, 0); + error = intsmb_stop(sc); + INTSMB_UNLOCK(sc); return (error); } @@ -655,140 +709,74 @@ intsmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf) int error, i; u_char data, nread; - error = intsmb_free(dev); if (*count > SMBBLOCKTRANS_MAX || *count == 0) - error = SMB_EINVAL; - if (!error) { - /* Reset internal array index. */ - bus_space_read_1(sc->st, sc->sh, PIIX4_SMBHSTCNT); - - bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTADD, slave | LSB); - bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTCMD, cmd); - bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTDAT0, *count); - intsmb_start(dev, PIIX4_SMBHSTCNT_PROT_BLOCK, 0); - error = intsmb_stop(dev); - if (!error) { - nread= bus_space_read_1(sc->st, sc->sh, - PIIX4_SMBHSTDAT0); - if (nread != 0 && nread <= SMBBLOCKTRANS_MAX) { - for (i = 0; i < nread; i++) { - data = bus_space_read_1(sc->st, sc->sh, - PIIX4_SMBBLKDAT); - if (i < *count) - buf[i] = data; - } - *count = nread; - } else { - error = EIO; + return (SMB_EINVAL); + + INTSMB_LOCK(sc); + error = intsmb_free(sc); + if (error) { + INTSMB_UNLOCK(sc); + return (error); + } + + /* Reset internal array index. */ + bus_read_1(sc->io_res, PIIX4_SMBHSTCNT); + + bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave | LSB); + bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, cmd); + bus_write_1(sc->io_res, PIIX4_SMBHSTDAT0, *count); + intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_BLOCK, 0); + error = intsmb_stop(sc); + if (error == 0) { + nread = bus_read_1(sc->io_res, PIIX4_SMBHSTDAT0); + if (nread != 0 && nread <= SMBBLOCKTRANS_MAX) { + for (i = 0; i < nread; i++) { + data = bus_read_1(sc->io_res, PIIX4_SMBBLKDAT); + if (i < *count) + buf[i] = data; } - } + *count = nread; + } else + error = EIO; } + INTSMB_UNLOCK(sc); return (error); } -DRIVER_MODULE(intsmb, intpm, intpm_driver, intsmb_devclass, 0, 0); - -static int -intpm_attach(device_t dev) -{ - struct intpm_pci_softc *sc; - struct resource *res; - device_t smbinterface; - void *ih; - char *str; - int error, rid, value; - int unit = device_get_unit(dev); - - sc = device_get_softc(dev); - if (sc == NULL) - return (ENOMEM); - - rid = PCI_BASE_ADDR_SMB; - res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE); - if (res == NULL) { - device_printf(dev, "Could not allocate Bus space\n"); - return (ENXIO); - } - sc->smbst = rman_get_bustag(res); - sc->smbsh = rman_get_bushandle(res); - -#ifdef __i386__ - device_printf(dev, "%s %lx\n", (sc->smbst == I386_BUS_SPACE_IO) ? - "I/O mapped" : "Memory", rman_get_start(res)); -#endif - -#ifndef NO_CHANGE_PCICONF - pci_write_config(dev, PCIR_INTLINE, 0x9, 1); - pci_write_config(dev, PCI_HST_CFG_SMB, - PCI_INTR_SMB_IRQ9 | PCI_INTR_SMB_ENABLE, 1); -#endif - value = pci_read_config(dev, PCI_HST_CFG_SMB, 1); - switch (value & 0xe) { - case PCI_INTR_SMB_SMI: - str = "SMI"; - break; - case PCI_INTR_SMB_IRQ9: - str = "IRQ 9"; - break; - default: - str = "BOGUS"; - } - device_printf(dev, "intr %s %s ", str, - (value & 1) ? "enabled" : "disabled"); - value = pci_read_config(dev, PCI_REVID_SMB, 1); - printf("revision %d\n", value); +static devclass_t intsmb_devclass; - /* Install interrupt handler. */ - rid = 0; - res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 9, 9, 1, - RF_SHAREABLE | RF_ACTIVE); - if (res == NULL) { - device_printf(dev, "could not allocate irq"); - return (ENOMEM); - } - error = bus_setup_intr(dev, res, INTR_TYPE_MISC, intpm_intr, sc, &ih); - if (error) { - device_printf(dev, "Failed to map intr\n"); - return (error); - } - smbinterface = device_add_child(dev, "intsmb", unit); - if (!smbinterface) - printf("intsmb%d: could not add SMBus device\n", unit); - device_probe_and_attach(smbinterface); +static device_method_t intsmb_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, intsmb_probe), + DEVMETHOD(device_attach, intsmb_attach), + DEVMETHOD(device_detach, intsmb_detach), - value = pci_read_config(dev, PCI_BASE_ADDR_PM, 4); - printf("intpm%d: PM %s %x \n", unit, - (value & 1) ? "I/O mapped" : "Memory", value & 0xfffe); - return (0); -} + /* Bus interface */ + DEVMETHOD(bus_print_child, bus_generic_print_child), -static int -intpm_probe(device_t dev) -{ - struct _pcsid *ep = pci_ids; - uint32_t device_id = pci_get_devid(dev); - - while (ep->type && ep->type != device_id) - ++ep; - if (ep->desc != NULL) { - device_set_desc(dev, ep->desc); - bus_set_resource(dev, SYS_RES_IRQ, 0, 9, 1); /* XXX setup intr resource */ - return (BUS_PROBE_DEFAULT); - } else { - return (ENXIO); - } -} + /* SMBus interface */ + DEVMETHOD(smbus_callback, intsmb_callback), + DEVMETHOD(smbus_quick, intsmb_quick), + DEVMETHOD(smbus_sendb, intsmb_sendb), + DEVMETHOD(smbus_recvb, intsmb_recvb), + DEVMETHOD(smbus_writeb, intsmb_writeb), + DEVMETHOD(smbus_writew, intsmb_writew), + DEVMETHOD(smbus_readb, intsmb_readb), + DEVMETHOD(smbus_readw, intsmb_readw), + DEVMETHOD(smbus_pcall, intsmb_pcall), + DEVMETHOD(smbus_bwrite, intsmb_bwrite), + DEVMETHOD(smbus_bread, intsmb_bread), -static void -intpm_intr(void *arg) -{ - struct intpm_pci_softc *sc = arg; + { 0, 0 } +}; - intsmb_intr(sc->smbus); - intsmb_slvintr(sc->smbus); -} +static driver_t intsmb_driver = { + "intsmb", + intsmb_methods, + sizeof(struct intsmb_softc), +}; -DRIVER_MODULE(intpm, pci , intpm_pci_driver, intpm_devclass, 0, 0); +DRIVER_MODULE(intsmb, pci, intsmb_driver, intsmb_devclass, 0, 0); DRIVER_MODULE(smbus, intsmb, smbus_driver, smbus_devclass, 0, 0); -MODULE_DEPEND(intpm, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER); -MODULE_VERSION(intpm, 1); +MODULE_DEPEND(intsmb, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER); +MODULE_VERSION(intsmb, 1); diff --git a/sys/pci/intpmreg.h b/sys/pci/intpmreg.h index c15fc77..236c737 100644 --- a/sys/pci/intpmreg.h +++ b/sys/pci/intpmreg.h @@ -34,7 +34,7 @@ /* PCI Config Registers. */ #define PCI_BASE_ADDR_SMB 0x90 /* IO BAR. */ #define PCI_BASE_ADDR_PM 0x40 -#define PCI_HST_CFG_SMB 0xd2 /*Host Configuration*/ +#define PCI_HST_CFG_SMB 0xd2 /* Host Configuration */ #define PCI_INTR_SMB_SMI 0 #define PCI_INTR_SMB_IRQ9 8 #define PCI_INTR_SMB_ENABLE 1 diff --git a/sys/pci/nfsmb.c b/sys/pci/nfsmb.c index b7cbca7..7eac2ec 100644 --- a/sys/pci/nfsmb.c +++ b/sys/pci/nfsmb.c @@ -2,11 +2,12 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> +#include <sys/bus.h> #include <sys/kernel.h> -#include <sys/systm.h> +#include <sys/lock.h> #include <sys/module.h> -#include <sys/bus.h> -#include <sys/uio.h> +#include <sys/mutex.h> +#include <sys/systm.h> #include <machine/bus.h> #include <machine/resource.h> @@ -15,7 +16,6 @@ __FBSDID("$FreeBSD$"); #include <dev/pci/pcivar.h> #include <dev/pci/pcireg.h> -#include <dev/iicbus/iiconf.h> #include <dev/smbus/smbconf.h> #include "smbus_if.h" @@ -86,16 +86,23 @@ struct nfsmb_softc { struct resource *res; bus_space_tag_t smbst; bus_space_handle_t smbsh; - device_t smbus; device_t subdev; + struct mtx lock; }; -#define NFSMB_SMBINB(nfsmb, register) \ +#define NFSMB_LOCK(nfsmb) mtx_lock(&(nfsmb)->lock) +#define NFSMB_UNLOCK(nfsmb) mtx_unlock(&(nfsmb)->lock) +#define NFSMB_LOCK_ASSERT(nfsmb) mtx_assert(&(nfsmb)->lock, MA_OWNED) + +#define NFSMB_SMBINB(nfsmb, register) \ (bus_space_read_1(nfsmb->smbst, nfsmb->smbsh, register)) #define NFSMB_SMBOUTB(nfsmb, register, value) \ (bus_space_write_1(nfsmb->smbst, nfsmb->smbsh, register, value)) +static int nfsmb_detach(device_t dev); +static int nfsmbsub_detach(device_t dev); + static int nfsmbsub_probe(device_t dev) { @@ -155,10 +162,14 @@ nfsmbsub_attach(device_t dev) } nfsmbsub_sc->smbst = rman_get_bustag(nfsmbsub_sc->res); nfsmbsub_sc->smbsh = rman_get_bushandle(nfsmbsub_sc->res); + mtx_init(&nfsmbsub_sc->lock, device_get_nameunit(dev), "nfsmb", + MTX_DEF); nfsmbsub_sc->smbus = device_add_child(dev, "smbus", -1); - if (nfsmbsub_sc->smbus == NULL) + if (nfsmbsub_sc->smbus == NULL) { + nfsmbsub_detach(dev); return (EINVAL); + } bus_generic_attach(dev); @@ -189,11 +200,14 @@ nfsmb_attach(device_t dev) nfsmb_sc->smbst = rman_get_bustag(nfsmb_sc->res); nfsmb_sc->smbsh = rman_get_bushandle(nfsmb_sc->res); + mtx_init(&nfsmb_sc->lock, device_get_nameunit(dev), "nfsmb", MTX_DEF); /* Allocate a new smbus device */ nfsmb_sc->smbus = device_add_child(dev, "smbus", -1); - if (!nfsmb_sc->smbus) + if (!nfsmb_sc->smbus) { + nfsmb_detach(dev); return (EINVAL); + } nfsmb_sc->subdev = NULL; switch (pci_get_device(dev)) { @@ -207,8 +221,10 @@ nfsmb_attach(device_t dev) case NFSMB_DEVICEID_NF4_55_SMB: /* Trying to add secondary device as slave */ nfsmb_sc->subdev = device_add_child(dev, "nfsmb", -1); - if (!nfsmb_sc->subdev) + if (!nfsmb_sc->subdev) { + nfsmb_detach(dev); return (EINVAL); + } break; default: break; @@ -231,6 +247,7 @@ nfsmbsub_detach(device_t dev) device_delete_child(dev, nfsmbsub_sc->smbus); nfsmbsub_sc->smbus = NULL; } + mtx_destroy(&nfsmbsub_sc->lock); if (nfsmbsub_sc->res) { bus_release_resource(parent, SYS_RES_IOPORT, nfsmbsub_sc->rid, nfsmbsub_sc->res); @@ -254,6 +271,7 @@ nfsmb_detach(device_t dev) nfsmb_sc->smbus = NULL; } + mtx_destroy(&nfsmb_sc->lock); if (nfsmb_sc->res) { bus_release_resource(dev, SYS_RES_IOPORT, nfsmb_sc->rid, nfsmb_sc->res); @@ -285,6 +303,7 @@ nfsmb_wait(struct nfsmb_softc *sc) u_char sts; int error, count; + NFSMB_LOCK_ASSERT(sc); if (NFSMB_SMBINB(sc, SMB_PRTCL) != 0) { count = 10000; @@ -346,12 +365,14 @@ nfsmb_quick(device_t dev, u_char slave, int how) panic("%s: unknown QUICK command (%x)!", __func__, how); } + NFSMB_LOCK(sc); NFSMB_SMBOUTB(sc, SMB_ADDR, slave); NFSMB_SMBOUTB(sc, SMB_PRTCL, protocol); error = nfsmb_wait(sc); NFSMB_DEBUG(printf(", error=0x%x\n", error)); + NFSMB_UNLOCK(sc); return (error); } @@ -362,6 +383,7 @@ nfsmb_sendb(device_t dev, u_char slave, char byte) struct nfsmb_softc *sc = (struct nfsmb_softc *)device_get_softc(dev); int error; + NFSMB_LOCK(sc); NFSMB_SMBOUTB(sc, SMB_CMD, byte); NFSMB_SMBOUTB(sc, SMB_ADDR, slave); NFSMB_SMBOUTB(sc, SMB_PRTCL, SMB_PRTCL_WRITE | SMB_PRTCL_BYTE); @@ -369,6 +391,7 @@ nfsmb_sendb(device_t dev, u_char slave, char byte) error = nfsmb_wait(sc); NFSMB_DEBUG(printf("nfsmb: SENDB to 0x%x, byte=0x%x, error=0x%x\n", slave, byte, error)); + NFSMB_UNLOCK(sc); return (error); } @@ -379,6 +402,7 @@ nfsmb_recvb(device_t dev, u_char slave, char *byte) struct nfsmb_softc *sc = (struct nfsmb_softc *)device_get_softc(dev); int error; + NFSMB_LOCK(sc); NFSMB_SMBOUTB(sc, SMB_ADDR, slave); NFSMB_SMBOUTB(sc, SMB_PRTCL, SMB_PRTCL_READ | SMB_PRTCL_BYTE); @@ -386,6 +410,7 @@ nfsmb_recvb(device_t dev, u_char slave, char *byte) *byte = NFSMB_SMBINB(sc, SMB_DATA); NFSMB_DEBUG(printf("nfsmb: RECVB from 0x%x, byte=0x%x, error=0x%x\n", slave, *byte, error)); + NFSMB_UNLOCK(sc); return (error); } @@ -396,6 +421,7 @@ nfsmb_writeb(device_t dev, u_char slave, char cmd, char byte) struct nfsmb_softc *sc = (struct nfsmb_softc *)device_get_softc(dev); int error; + NFSMB_LOCK(sc); NFSMB_SMBOUTB(sc, SMB_CMD, cmd); NFSMB_SMBOUTB(sc, SMB_DATA, byte); NFSMB_SMBOUTB(sc, SMB_ADDR, slave); @@ -404,6 +430,7 @@ nfsmb_writeb(device_t dev, u_char slave, char cmd, char byte) error = nfsmb_wait(sc); NFSMB_DEBUG(printf("nfsmb: WRITEB to 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, byte, error)); + NFSMB_UNLOCK(sc); return (error); } @@ -414,6 +441,7 @@ nfsmb_readb(device_t dev, u_char slave, char cmd, char *byte) struct nfsmb_softc *sc = (struct nfsmb_softc *)device_get_softc(dev); int error; + NFSMB_LOCK(sc); NFSMB_SMBOUTB(sc, SMB_CMD, cmd); NFSMB_SMBOUTB(sc, SMB_ADDR, slave); NFSMB_SMBOUTB(sc, SMB_PRTCL, SMB_PRTCL_READ | SMB_PRTCL_BYTE_DATA); @@ -422,6 +450,7 @@ nfsmb_readb(device_t dev, u_char slave, char cmd, char *byte) *byte = NFSMB_SMBINB(sc, SMB_DATA); NFSMB_DEBUG(printf("nfsmb: READB from 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, (unsigned char)*byte, error)); + NFSMB_UNLOCK(sc); return (error); } @@ -432,6 +461,7 @@ nfsmb_writew(device_t dev, u_char slave, char cmd, short word) struct nfsmb_softc *sc = (struct nfsmb_softc *)device_get_softc(dev); int error; + NFSMB_LOCK(sc); NFSMB_SMBOUTB(sc, SMB_CMD, cmd); NFSMB_SMBOUTB(sc, SMB_DATA, word); NFSMB_SMBOUTB(sc, SMB_DATA + 1, word >> 8); @@ -441,6 +471,7 @@ nfsmb_writew(device_t dev, u_char slave, char cmd, short word) error = nfsmb_wait(sc); NFSMB_DEBUG(printf("nfsmb: WRITEW to 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, word, error)); + NFSMB_UNLOCK(sc); return (error); } @@ -451,6 +482,7 @@ nfsmb_readw(device_t dev, u_char slave, char cmd, short *word) struct nfsmb_softc *sc = (struct nfsmb_softc *)device_get_softc(dev); int error; + NFSMB_LOCK(sc); NFSMB_SMBOUTB(sc, SMB_CMD, cmd); NFSMB_SMBOUTB(sc, SMB_ADDR, slave); NFSMB_SMBOUTB(sc, SMB_PRTCL, SMB_PRTCL_READ | SMB_PRTCL_WORD_DATA); @@ -460,6 +492,7 @@ nfsmb_readw(device_t dev, u_char slave, char cmd, short *word) (NFSMB_SMBINB(sc, SMB_DATA + 1) << 8); NFSMB_DEBUG(printf("nfsmb: READW from 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, (unsigned short)*word, error)); + NFSMB_UNLOCK(sc); return (error); } @@ -473,6 +506,8 @@ nfsmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf) if (count < 1 || count > 32) return (SMB_EINVAL); + + NFSMB_LOCK(sc); NFSMB_SMBOUTB(sc, SMB_CMD, cmd); NFSMB_SMBOUTB(sc, SMB_BCNT, count); for (i = 0; i < count; i++) @@ -483,6 +518,7 @@ nfsmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf) error = nfsmb_wait(sc); NFSMB_DEBUG(printf("nfsmb: WRITEBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error)); + NFSMB_UNLOCK(sc); return (error); } @@ -496,6 +532,8 @@ nfsmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf) if (*count < 1 || *count > 32) return (SMB_EINVAL); + + NFSMB_LOCK(sc); NFSMB_SMBOUTB(sc, SMB_CMD, cmd); NFSMB_SMBOUTB(sc, SMB_ADDR, slave); NFSMB_SMBOUTB(sc, SMB_PRTCL, SMB_PRTCL_READ | SMB_PRTCL_BLOCK_DATA); @@ -511,6 +549,7 @@ nfsmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf) } NFSMB_DEBUG(printf("nfsmb: READBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, *count, cmd, error)); + NFSMB_UNLOCK(sc); return (error); } diff --git a/sys/pci/viapm.c b/sys/pci/viapm.c index 4c990c2..6a7fac5 100644 --- a/sys/pci/viapm.c +++ b/sys/pci/viapm.c @@ -30,11 +30,12 @@ __FBSDID("$FreeBSD$"); #include "opt_isa.h" #include <sys/param.h> +#include <sys/bus.h> #include <sys/kernel.h> -#include <sys/systm.h> +#include <sys/lock.h> #include <sys/module.h> -#include <sys/bus.h> -#include <sys/uio.h> +#include <sys/mutex.h> +#include <sys/systm.h> #include <machine/bus.h> #include <machine/resource.h> @@ -82,6 +83,10 @@ static int viapm_debug = 0; #define VIAPM_TYP_686A 4 #define VIAPM_TYP_8233 5 +#define VIAPM_LOCK(sc) mtx_lock(&(sc)->lock) +#define VIAPM_UNLOCK(sc) mtx_unlock(&(sc)->lock) +#define VIAPM_LOCK_ASSERT(sc) mtx_assert(&(sc)->lock, MA_OWNED) + struct viapm_softc { int type; u_int32_t base; @@ -92,9 +97,9 @@ struct viapm_softc { struct resource *iores; struct resource *irqres; void *irqih; - device_t iicbb; device_t smbus; + struct mtx lock; }; static devclass_t viapm_devclass; @@ -329,6 +334,7 @@ viapm_pro_attach(device_t dev) struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev); u_int32_t l; + mtx_init(&viapm->lock, device_get_nameunit(dev), "viapm", MTX_DEF); if (!(viapm->iores = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &viapm->iorid, RF_ACTIVE))) { device_printf(dev, "could not allocate bus space\n"); @@ -394,6 +400,7 @@ error: if (viapm->irqres) bus_release_resource(dev, SYS_RES_IRQ, viapm->irqrid, viapm->irqres); #endif + mtx_destroy(&viapm->lock); return ENXIO; } @@ -402,11 +409,12 @@ static int viapm_586b_attach(device_t dev) { struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev); - + + mtx_init(&viapm->lock, device_get_nameunit(dev), "viapm", MTX_DEF); if (!(viapm->iores = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &viapm->iorid, RF_ACTIVE | RF_SHAREABLE))) { device_printf(dev, "could not allocate bus resource\n"); - return ENXIO; + goto error; } viapm->st = rman_get_bustag(viapm->iores); viapm->sh = rman_get_bushandle(viapm->iores); @@ -425,6 +433,7 @@ error: if (viapm->iores) bus_release_resource(dev, SYS_RES_IOPORT, viapm->iorid, viapm->iores); + mtx_destroy(&viapm->lock); return ENXIO; } @@ -432,16 +441,16 @@ static int viapm_586b_detach(device_t dev) { struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev); - int error; bus_generic_detach(dev); if (viapm->iicbb) { device_delete_child(dev, viapm->iicbb); } - if (viapm->iores && (error = bus_release_resource(dev, SYS_RES_IOPORT, - viapm->iorid, viapm->iores))) - return (error); + if (viapm->iores) + bus_release_resource(dev, SYS_RES_IOPORT, viapm->iorid, + viapm->iores); + mtx_destroy(&viapm->lock); return 0; } @@ -450,22 +459,18 @@ static int viapm_pro_detach(device_t dev) { struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev); - int error; bus_generic_detach(dev); if (viapm->smbus) { device_delete_child(dev, viapm->smbus); } - if ((error = bus_release_resource(dev, SYS_RES_IOPORT, - viapm->iorid, viapm->iores))) - return (error); + bus_release_resource(dev, SYS_RES_IOPORT, viapm->iorid, viapm->iores); #ifdef notyet - if ((error = bus_release_resource(dev, SYS_RES_IRQ, - viapm->irqrid, viapm->irqres)) - return (error); + bus_release_resource(dev, SYS_RES_IRQ, viapm->irqrid, viapm->irqres); #endif + mtx_destroy(&viapm->lock); return 0; } @@ -482,6 +487,7 @@ viabb_setscl(device_t dev, int ctrl) struct viapm_softc *viapm = device_get_softc(dev); u_char val; + VIAPM_LOCK(viapm); val = VIAPM_INB(GPIO_VAL); if (ctrl) @@ -490,6 +496,7 @@ viabb_setscl(device_t dev, int ctrl) val &= ~VIAPM_SCL; VIAPM_OUTB(GPIO_VAL, val); + VIAPM_UNLOCK(viapm); return; } @@ -500,6 +507,7 @@ viabb_setsda(device_t dev, int data) struct viapm_softc *viapm = device_get_softc(dev); u_char val; + VIAPM_LOCK(viapm); val = VIAPM_INB(GPIO_VAL); if (data) @@ -508,6 +516,7 @@ viabb_setsda(device_t dev, int data) val &= ~VIAPM_SDA; VIAPM_OUTB(GPIO_VAL, val); + VIAPM_UNLOCK(viapm); return; } @@ -526,16 +535,24 @@ static int viabb_getscl(device_t dev) { struct viapm_softc *viapm = device_get_softc(dev); + u_char val; - return ((VIAPM_INB(EXTSMI_VAL) & VIAPM_SCL) != 0); + VIAPM_LOCK(viapm); + val = VIAPM_INB(EXTSMI_VAL); + VIAPM_UNLOCK(viapm); + return ((val & VIAPM_SCL) != 0); } static int viabb_getsda(device_t dev) { struct viapm_softc *viapm = device_get_softc(dev); + u_char val; - return ((VIAPM_INB(EXTSMI_VAL) & VIAPM_SDA) != 0); + VIAPM_LOCK(viapm); + val = VIAPM_INB(EXTSMI_VAL); + VIAPM_UNLOCK(viapm); + return ((val & VIAPM_SDA) != 0); } static int @@ -579,6 +596,8 @@ viapm_wait(struct viapm_softc *viapm) u_char sts = 0; int error; + VIAPM_LOCK_ASSERT(viapm); + /* wait for command to complete and SMBus controller is idle */ while(count--) { DELAY(10); @@ -636,9 +655,12 @@ viasmb_quick(device_t dev, u_char slave, int how) struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev); int error; + VIAPM_LOCK(viapm); viapm_clear(viapm); - if (viapm_busy(viapm)) + if (viapm_busy(viapm)) { + VIAPM_UNLOCK(viapm); return (SMB_EBUSY); + } switch (how) { case SMB_QWRITE: @@ -656,6 +678,7 @@ viasmb_quick(device_t dev, u_char slave, int how) VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_QUICK); error = viapm_wait(viapm); + VIAPM_UNLOCK(viapm); return (error); } @@ -666,9 +689,12 @@ viasmb_sendb(device_t dev, u_char slave, char byte) struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev); int error; + VIAPM_LOCK(viapm); viapm_clear(viapm); - if (viapm_busy(viapm)) + if (viapm_busy(viapm)) { + VIAPM_UNLOCK(viapm); return (SMB_EBUSY); + } VIAPM_OUTB(SMBHADDR, slave & ~ LSB); VIAPM_OUTB(SMBHCMD, byte); @@ -678,6 +704,7 @@ viasmb_sendb(device_t dev, u_char slave, char byte) error = viapm_wait(viapm); VIAPM_DEBUG(printf("viapm: SENDB to 0x%x, byte=0x%x, error=0x%x\n", slave, byte, error)); + VIAPM_UNLOCK(viapm); return (error); } @@ -688,9 +715,12 @@ viasmb_recvb(device_t dev, u_char slave, char *byte) struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev); int error; + VIAPM_LOCK(viapm); viapm_clear(viapm); - if (viapm_busy(viapm)) + if (viapm_busy(viapm)) { + VIAPM_UNLOCK(viapm); return (SMB_EBUSY); + } VIAPM_OUTB(SMBHADDR, slave | LSB); @@ -700,6 +730,7 @@ viasmb_recvb(device_t dev, u_char slave, char *byte) *byte = VIAPM_INB(SMBHDATA0); VIAPM_DEBUG(printf("viapm: RECVB from 0x%x, byte=0x%x, error=0x%x\n", slave, *byte, error)); + VIAPM_UNLOCK(viapm); return (error); } @@ -710,9 +741,12 @@ viasmb_writeb(device_t dev, u_char slave, char cmd, char byte) struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev); int error; + VIAPM_LOCK(viapm); viapm_clear(viapm); - if (viapm_busy(viapm)) + if (viapm_busy(viapm)) { + VIAPM_UNLOCK(viapm); return (SMB_EBUSY); + } VIAPM_OUTB(SMBHADDR, slave & ~ LSB); VIAPM_OUTB(SMBHCMD, cmd); @@ -723,6 +757,7 @@ viasmb_writeb(device_t dev, u_char slave, char cmd, char byte) error = viapm_wait(viapm); VIAPM_DEBUG(printf("viapm: WRITEB to 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, byte, error)); + VIAPM_UNLOCK(viapm); return (error); } @@ -733,9 +768,12 @@ viasmb_readb(device_t dev, u_char slave, char cmd, char *byte) struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev); int error; + VIAPM_LOCK(viapm); viapm_clear(viapm); - if (viapm_busy(viapm)) + if (viapm_busy(viapm)) { + VIAPM_UNLOCK(viapm); return (SMB_EBUSY); + } VIAPM_OUTB(SMBHADDR, slave | LSB); VIAPM_OUTB(SMBHCMD, cmd); @@ -746,6 +784,7 @@ viasmb_readb(device_t dev, u_char slave, char cmd, char *byte) *byte = VIAPM_INB(SMBHDATA0); VIAPM_DEBUG(printf("viapm: READB from 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, *byte, error)); + VIAPM_UNLOCK(viapm); return (error); } @@ -756,9 +795,12 @@ viasmb_writew(device_t dev, u_char slave, char cmd, short word) struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev); int error; + VIAPM_LOCK(viapm); viapm_clear(viapm); - if (viapm_busy(viapm)) + if (viapm_busy(viapm)) { + VIAPM_UNLOCK(viapm); return (SMB_EBUSY); + } VIAPM_OUTB(SMBHADDR, slave & ~ LSB); VIAPM_OUTB(SMBHCMD, cmd); @@ -770,6 +812,7 @@ viasmb_writew(device_t dev, u_char slave, char cmd, short word) error = viapm_wait(viapm); VIAPM_DEBUG(printf("viapm: WRITEW to 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, word, error)); + VIAPM_UNLOCK(viapm); return (error); } @@ -781,9 +824,12 @@ viasmb_readw(device_t dev, u_char slave, char cmd, short *word) int error; u_char high, low; + VIAPM_LOCK(viapm); viapm_clear(viapm); - if (viapm_busy(viapm)) + if (viapm_busy(viapm)) { + VIAPM_UNLOCK(viapm); return (SMB_EBUSY); + } VIAPM_OUTB(SMBHADDR, slave | LSB); VIAPM_OUTB(SMBHCMD, cmd); @@ -798,6 +844,7 @@ viasmb_readw(device_t dev, u_char slave, char cmd, short *word) } VIAPM_DEBUG(printf("viapm: READW from 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, *word, error)); + VIAPM_UNLOCK(viapm); return (error); } @@ -812,9 +859,12 @@ viasmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf) if (count < 1 || count > 32) return (SMB_EINVAL); + VIAPM_LOCK(viapm); viapm_clear(viapm); - if (viapm_busy(viapm)) + if (viapm_busy(viapm)) { + VIAPM_UNLOCK(viapm); return (SMB_EBUSY); + } VIAPM_OUTB(SMBHADDR, slave & ~LSB); VIAPM_OUTB(SMBHCMD, cmd); @@ -832,6 +882,7 @@ viasmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf) error = viapm_wait(viapm); VIAPM_DEBUG(printf("viapm: WRITEBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error)); + VIAPM_UNLOCK(viapm); return (error); @@ -847,9 +898,12 @@ viasmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf) if (*count < 1 || *count > 32) return (SMB_EINVAL); + VIAPM_LOCK(viapm); viapm_clear(viapm); - if (viapm_busy(viapm)) + if (viapm_busy(viapm)) { + VIAPM_UNLOCK(viapm); return (SMB_EBUSY); + } VIAPM_OUTB(SMBHADDR, slave | LSB); VIAPM_OUTB(SMBHCMD, cmd); @@ -872,6 +926,7 @@ viasmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf) error: VIAPM_DEBUG(printf("viapm: READBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, *count, cmd, error)); + VIAPM_UNLOCK(viapm); return (error); } |