Index: intpm.c =================================================================== RCS file: /home/ncvs/src/sys/pci/intpm.c,v retrieving revision 1.35 diff -u -r1.35 intpm.c --- intpm.c 13 Sep 2006 18:56:39 -0000 1.35 +++ intpm.c 13 Sep 2006 20:54:54 -0000 @@ -29,47 +29,42 @@ #include #include +#include #include -#include - -#include +#include #include -#include +#include #include -#include +#include #include #include "smbus_if.h" -/*This should be removed if force_pci_map_int supported*/ -#include - #include #include #include #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_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 +76,146 @@ 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 devclass_t intsmb_devclass; +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 device_method_t intpm_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, intsmb_probe), - DEVMETHOD(device_attach, intsmb_attach), - - /* Bus interface */ - DEVMETHOD(bus_print_child, bus_generic_print_child), - - /* 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_probe(device_t dev) +{ - { 0, 0 } -}; + 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); + } -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; -}; + return (BUS_PROBE_DEFAULT); +} +static int +intsmb_attach(device_t dev) +{ + struct intsmb_softc *sc = device_get_softc(dev); + int error, rid, value; + char *str; -struct intsmb_softc { - struct intpm_pci_softc *pci_sc; - bus_space_tag_t st; - bus_space_handle_t sh; - device_t smbus; - int isbusy; -}; + sc = device_get_softc(dev); + mtx_init(&sc->lock, device_get_nameunit(dev), "intsmb", MTX_DEF); -static driver_t intpm_driver = { - "intsmb", - intpm_methods, - sizeof(struct intsmb_softc), -}; + 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 mtx_destroy; + } -static devclass_t intpm_devclass; +#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 device_method_t intpm_pci_methods[] = { - DEVMETHOD(device_probe, intpm_probe), - DEVMETHOD(device_attach, intpm_attach), + if ((value & 0xe) != PCI_INTR_SMB_IRQ9) { + device_printf(dev, "Unsupported interrupt mode\n"); + error = ENXIO; + goto free_io; + } - { 0, 0 } -}; + /* 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 free_io; + } -static driver_t intpm_pci_driver = { - "intpm", - intpm_pci_methods, - sizeof(struct intpm_pci_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 free_irq; + } -static int -intsmb_probe(device_t dev) -{ - struct intsmb_softc *sc = device_get_softc(dev); + 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); + sc->isbusy = 0; 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"); - - return (BUS_PROBE_DEFAULT); /* XXX don't know what to return else */ -} -static int -intsmb_attach(device_t dev) -{ - struct intsmb_softc *sc = device_get_softc(dev); + if (sc->smbus == NULL) { + error = ENXIO; + goto teardown_irq; + } + error = device_probe_and_attach(sc->smbus); + if (error) + goto delete_child; - 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); + /* Enable Arart */ + bus_write_1(sc->io_res, PIIX4_SMBSLVCNT, PIIX4_SMBSLVCNT_ALTEN); #endif return (0); + +delete_child: + device_delete_child(dev, sc->smbus); +teardown_irq: + bus_teardown_intr(dev, sc->irq_res, sc->irq_hand); +free_irq: + bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res); +free_io: + bus_release_resource(dev, SYS_RES_IOPORT, PCI_BASE_ADDR_SMB, + sc->io_res); +mtx_destroy: + mtx_destroy(&sc->lock); + return (error); +} + +static void +intsmb_rawintr(void *arg) +{ + struct intsmb_softc *sc = arg; + + 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 +224,49 @@ 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 +278,73 @@ } 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 +352,21 @@ /* 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 +378,60 @@ * 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 +439,21 @@ } /* 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 +467,19 @@ 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 +489,17 @@ 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 +509,27 @@ 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 +539,18 @@ 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 +560,19 @@ 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 +582,43 @@ 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 +634,26 @@ 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); - } - 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; + 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, 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 +663,27 @@ 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 +694,73 @@ 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 (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); + return (SMB_EINVAL); - 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); + INTSMB_LOCK(sc); + error = intsmb_free(sc); + if (error) { + INTSMB_UNLOCK(sc); + return (error); } - 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 + /* Reset internal array index. */ + bus_read_1(sc->io_res, PIIX4_SMBHSTCNT); -#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"; + 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; } - 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); + INTSMB_UNLOCK(sc); + return (error); +} - /* 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 devclass_t intsmb_devclass; - 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); -} +static device_method_t intsmb_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, intsmb_probe), + DEVMETHOD(device_attach, intsmb_attach), -static int -intpm_probe(device_t dev) -{ - struct _pcsid *ep = pci_ids; - uint32_t device_id = pci_get_devid(dev); + /* Bus interface */ + DEVMETHOD(bus_print_child, bus_generic_print_child), - 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); Index: intpmreg.h =================================================================== RCS file: /home/ncvs/src/sys/pci/intpmreg.h,v retrieving revision 1.3 diff -u -r1.3 intpmreg.h --- intpmreg.h 13 Sep 2006 18:56:39 -0000 1.3 +++ intpmreg.h 13 Sep 2006 20:54:54 -0000 @@ -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