intpm.c revision 306814
143166Snsouch/*- 243166Snsouch * Copyright (c) 1998, 1999 Takanori Watanabe 343166Snsouch * All rights reserved. 443166Snsouch * 543166Snsouch * Redistribution and use in source and binary forms, with or without 643166Snsouch * modification, are permitted provided that the following conditions 743166Snsouch * are met: 843166Snsouch * 1. Redistributions of source code must retain the above copyright 943166Snsouch * notice, this list of conditions and the following disclaimer. 1043166Snsouch * 2. Redistributions in binary form must reproduce the above copyright 1143166Snsouch * notice, this list of conditions and the following disclaimer in the 1243166Snsouch * documentation and/or other materials provided with the distribution. 1343166Snsouch * 1443166Snsouch * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1543166Snsouch * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1643166Snsouch * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1743166Snsouch * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1843166Snsouch * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1943166Snsouch * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2043166Snsouch * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2143166Snsouch * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2243166Snsouch * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2343166Snsouch * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2443166Snsouch * SUCH DAMAGE. 2543166Snsouch */ 2643166Snsouch 27116192Sobrien#include <sys/cdefs.h> 28116192Sobrien__FBSDID("$FreeBSD: stable/11/sys/dev/intpm/intpm.c 306814 2016-10-07 18:50:50Z avg $"); 29116192Sobrien 3043166Snsouch#include <sys/param.h> 3143166Snsouch#include <sys/systm.h> 32165951Sjhb#include <sys/bus.h> 3343166Snsouch#include <sys/kernel.h> 34165951Sjhb#include <sys/lock.h> 3543166Snsouch#include <sys/module.h> 36165951Sjhb#include <sys/mutex.h> 3746651Speter#include <sys/rman.h> 38165951Sjhb#include <machine/bus.h> 3943166Snsouch#include <dev/smbus/smbconf.h> 4043166Snsouch 4143166Snsouch#include "smbus_if.h" 4243166Snsouch 43119288Simp#include <dev/pci/pcireg.h> 44119288Simp#include <dev/pci/pcivar.h> 45272017Srpaulo#include <dev/intpm/intpmreg.h> 46306814Savg#include <dev/amdsbwd/amd_chipset.h> 4743166Snsouch 4843166Snsouch#include "opt_intpm.h" 4943166Snsouch 50165951Sjhbstruct intsmb_softc { 51165951Sjhb device_t dev; 52165951Sjhb struct resource *io_res; 53165951Sjhb struct resource *irq_res; 54165951Sjhb void *irq_hand; 55165951Sjhb device_t smbus; 56305462Savg int io_rid; 57165951Sjhb int isbusy; 58197128Savg int cfg_irq9; 59305462Savg int sb8xx; 60197128Savg int poll; 61165951Sjhb struct mtx lock; 6243166Snsouch}; 63162289Sjhb 64165951Sjhb#define INTSMB_LOCK(sc) mtx_lock(&(sc)->lock) 65165951Sjhb#define INTSMB_UNLOCK(sc) mtx_unlock(&(sc)->lock) 66165951Sjhb#define INTSMB_LOCK_ASSERT(sc) mtx_assert(&(sc)->lock, MA_OWNED) 67165951Sjhb 6843166Snsouchstatic int intsmb_probe(device_t); 6943166Snsouchstatic int intsmb_attach(device_t); 70165951Sjhbstatic int intsmb_detach(device_t); 71165951Sjhbstatic int intsmb_intr(struct intsmb_softc *sc); 72165951Sjhbstatic int intsmb_slvintr(struct intsmb_softc *sc); 73165951Sjhbstatic void intsmb_alrintr(struct intsmb_softc *sc); 74162234Sjhbstatic int intsmb_callback(device_t dev, int index, void *data); 7543166Snsouchstatic int intsmb_quick(device_t dev, u_char slave, int how); 7643166Snsouchstatic int intsmb_sendb(device_t dev, u_char slave, char byte); 7743166Snsouchstatic int intsmb_recvb(device_t dev, u_char slave, char *byte); 7843166Snsouchstatic int intsmb_writeb(device_t dev, u_char slave, char cmd, char byte); 7943166Snsouchstatic int intsmb_writew(device_t dev, u_char slave, char cmd, short word); 8043166Snsouchstatic int intsmb_readb(device_t dev, u_char slave, char cmd, char *byte); 8143166Snsouchstatic int intsmb_readw(device_t dev, u_char slave, char cmd, short *word); 8243166Snsouchstatic int intsmb_pcall(device_t dev, u_char slave, char cmd, short sdata, short *rdata); 8343166Snsouchstatic int intsmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf); 84162234Sjhbstatic int intsmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf); 85165951Sjhbstatic void intsmb_start(struct intsmb_softc *sc, u_char cmd, int nointr); 86165951Sjhbstatic int intsmb_stop(struct intsmb_softc *sc); 87165951Sjhbstatic int intsmb_stop_poll(struct intsmb_softc *sc); 88165951Sjhbstatic int intsmb_free(struct intsmb_softc *sc); 89165951Sjhbstatic void intsmb_rawintr(void *arg); 90162289Sjhb 91165951Sjhbstatic int 92165951Sjhbintsmb_probe(device_t dev) 93165951Sjhb{ 9443166Snsouch 95165951Sjhb switch (pci_get_devid(dev)) { 96165951Sjhb case 0x71138086: /* Intel 82371AB */ 97165951Sjhb case 0x719b8086: /* Intel 82443MX */ 98165951Sjhb#if 0 99165951Sjhb /* Not a good idea yet, this stops isab0 functioning */ 100165951Sjhb case 0x02001166: /* ServerWorks OSB4 */ 101165951Sjhb#endif 102165951Sjhb device_set_desc(dev, "Intel PIIX4 SMBUS Interface"); 103165951Sjhb break; 104234338Savg case 0x43721002: 105234338Savg device_set_desc(dev, "ATI IXP400 SMBus Controller"); 106234338Savg break; 107306814Savg case AMDSB_SMBUS_DEVID: 108306120Savg device_set_desc(dev, "AMD SB600/7xx/8xx/9xx SMBus Controller"); 109197128Savg break; 110306814Savg case AMDFCH_SMBUS_DEVID: /* AMD FCH */ 111306814Savg case AMDCZ_SMBUS_DEVID: /* AMD Carizzo FCH */ 112306120Savg device_set_desc(dev, "AMD FCH SMBus Controller"); 113306120Savg break; 114165951Sjhb default: 115165951Sjhb return (ENXIO); 116165951Sjhb } 11743166Snsouch 118165951Sjhb return (BUS_PROBE_DEFAULT); 119165951Sjhb} 120162289Sjhb 121305462Savgstatic uint8_t 122306814Savgamd_pmio_read(struct resource *res, uint8_t reg) 123305462Savg{ 124305462Savg bus_write_1(res, 0, reg); /* Index */ 125305462Savg return (bus_read_1(res, 1)); /* Data */ 126305462Savg} 127305462Savg 128165951Sjhbstatic int 129305462Savgsb8xx_attach(device_t dev) 130305462Savg{ 131305462Savg static const int AMDSB_SMBIO_WIDTH = 0x14; 132305462Savg struct intsmb_softc *sc; 133305462Savg struct resource *res; 134306814Savg uint32_t devid; 135306814Savg uint8_t revid; 136305462Savg uint16_t addr; 137305462Savg int rid; 138305462Savg int rc; 139306814Savg bool enabled; 140305462Savg 141305462Savg sc = device_get_softc(dev); 142306814Savg rid = 0; 143305462Savg rc = bus_set_resource(dev, SYS_RES_IOPORT, rid, AMDSB_PMIO_INDEX, 144305462Savg AMDSB_PMIO_WIDTH); 145305462Savg if (rc != 0) { 146305462Savg device_printf(dev, "bus_set_resource for PM IO failed\n"); 147305462Savg return (ENXIO); 148305462Savg } 149305462Savg res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, 150306814Savg RF_ACTIVE); 151305462Savg if (res == NULL) { 152305462Savg device_printf(dev, "bus_alloc_resource for PM IO failed\n"); 153305462Savg return (ENXIO); 154305462Savg } 155305462Savg 156306814Savg devid = pci_get_devid(dev); 157306814Savg revid = pci_get_revid(dev); 158306814Savg if (devid == AMDSB_SMBUS_DEVID || 159306814Savg (devid == AMDFCH_SMBUS_DEVID && revid < AMDFCH41_SMBUS_REVID) || 160306814Savg (devid == AMDCZ_SMBUS_DEVID && revid < AMDCZ49_SMBUS_REVID)) { 161306814Savg addr = amd_pmio_read(res, AMDSB8_PM_SMBUS_EN + 1); 162306814Savg addr <<= 8; 163306814Savg addr |= amd_pmio_read(res, AMDSB8_PM_SMBUS_EN); 164306814Savg enabled = (addr & AMDSB8_SMBUS_EN) != 0; 165306814Savg addr &= AMDSB8_SMBUS_ADDR_MASK; 166306814Savg } else { 167306814Savg addr = amd_pmio_read(res, AMDFCH41_PM_DECODE_EN0); 168306814Savg enabled = (addr & AMDFCH41_SMBUS_EN) != 0; 169306814Savg addr = amd_pmio_read(res, AMDFCH41_PM_DECODE_EN1); 170306814Savg addr <<= 8; 171306814Savg } 172305462Savg 173305462Savg bus_release_resource(dev, SYS_RES_IOPORT, rid, res); 174305462Savg bus_delete_resource(dev, SYS_RES_IOPORT, rid); 175305462Savg 176306814Savg if (!enabled) { 177306814Savg device_printf(dev, "SB8xx/SB9xx/FCH SMBus not enabled\n"); 178305462Savg return (ENXIO); 179305462Savg } 180305462Savg 181306814Savg sc->io_rid = 0; 182305462Savg rc = bus_set_resource(dev, SYS_RES_IOPORT, sc->io_rid, addr, 183305462Savg AMDSB_SMBIO_WIDTH); 184305462Savg if (rc != 0) { 185305462Savg device_printf(dev, "bus_set_resource for SMBus IO failed\n"); 186305462Savg return (ENXIO); 187305462Savg } 188305462Savg if (res == NULL) { 189305462Savg device_printf(dev, "bus_alloc_resource for SMBus IO failed\n"); 190305462Savg return (ENXIO); 191305462Savg } 192305462Savg sc->io_res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &sc->io_rid, 193306814Savg RF_ACTIVE); 194305462Savg sc->poll = 1; 195305462Savg return (0); 196305462Savg} 197305462Savg 198306122Savgstatic void 199306122Savgintsmb_release_resources(device_t dev) 200306122Savg{ 201306122Savg struct intsmb_softc *sc = device_get_softc(dev); 202306122Savg 203306122Savg if (sc->smbus) 204306122Savg device_delete_child(dev, sc->smbus); 205306122Savg if (sc->irq_hand) 206306122Savg bus_teardown_intr(dev, sc->irq_res, sc->irq_hand); 207306122Savg if (sc->irq_res) 208306122Savg bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res); 209306122Savg if (sc->io_res) 210306122Savg bus_release_resource(dev, SYS_RES_IOPORT, sc->io_rid, 211306122Savg sc->io_res); 212306122Savg mtx_destroy(&sc->lock); 213306122Savg} 214306122Savg 215305462Savgstatic int 216165951Sjhbintsmb_attach(device_t dev) 217165951Sjhb{ 218165951Sjhb struct intsmb_softc *sc = device_get_softc(dev); 219165951Sjhb int error, rid, value; 220197128Savg int intr; 221165951Sjhb char *str; 222162289Sjhb 223178972Sjhb sc->dev = dev; 224178972Sjhb 225165951Sjhb mtx_init(&sc->lock, device_get_nameunit(dev), "intsmb", MTX_DEF); 22643166Snsouch 227197128Savg sc->cfg_irq9 = 0; 228305462Savg switch (pci_get_devid(dev)) { 229197128Savg#ifndef NO_CHANGE_PCICONF 230197128Savg case 0x71138086: /* Intel 82371AB */ 231197128Savg case 0x719b8086: /* Intel 82443MX */ 232197128Savg /* Changing configuration is allowed. */ 233197128Savg sc->cfg_irq9 = 1; 234197128Savg break; 235305462Savg#endif 236306814Savg case AMDSB_SMBUS_DEVID: 237306814Savg if (pci_get_revid(dev) >= AMDSB8_SMBUS_REVID) 238305462Savg sc->sb8xx = 1; 239305462Savg break; 240306814Savg case AMDFCH_SMBUS_DEVID: 241306814Savg case AMDCZ_SMBUS_DEVID: 242306140Savg sc->sb8xx = 1; 243306140Savg break; 244197128Savg } 245197128Savg 246305462Savg if (sc->sb8xx) { 247305462Savg error = sb8xx_attach(dev); 248305462Savg if (error != 0) 249305462Savg goto fail; 250305462Savg else 251305462Savg goto no_intr; 252305462Savg } 253305462Savg 254305462Savg sc->io_rid = PCI_BASE_ADDR_SMB; 255305462Savg sc->io_res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &sc->io_rid, 256165951Sjhb RF_ACTIVE); 257165951Sjhb if (sc->io_res == NULL) { 258165951Sjhb device_printf(dev, "Could not allocate I/O space\n"); 259165951Sjhb error = ENXIO; 260165951Sjhb goto fail; 261165951Sjhb } 26243166Snsouch 263197128Savg if (sc->cfg_irq9) { 264197128Savg pci_write_config(dev, PCIR_INTLINE, 0x9, 1); 265197128Savg pci_write_config(dev, PCI_HST_CFG_SMB, 266197128Savg PCI_INTR_SMB_IRQ9 | PCI_INTR_SMB_ENABLE, 1); 267197128Savg } 268165951Sjhb value = pci_read_config(dev, PCI_HST_CFG_SMB, 1); 269197128Savg sc->poll = (value & PCI_INTR_SMB_ENABLE) == 0; 270197128Savg intr = value & PCI_INTR_SMB_MASK; 271197128Savg switch (intr) { 272165951Sjhb case PCI_INTR_SMB_SMI: 273165951Sjhb str = "SMI"; 274165951Sjhb break; 275165951Sjhb case PCI_INTR_SMB_IRQ9: 276165951Sjhb str = "IRQ 9"; 277165951Sjhb break; 278197128Savg case PCI_INTR_SMB_IRQ_PCI: 279197128Savg str = "PCI IRQ"; 280197128Savg break; 281165951Sjhb default: 282165951Sjhb str = "BOGUS"; 283165951Sjhb } 284197128Savg 285165951Sjhb device_printf(dev, "intr %s %s ", str, 286197128Savg sc->poll == 0 ? "enabled" : "disabled"); 287168870Sjhb printf("revision %d\n", pci_read_config(dev, PCI_REVID_SMB, 1)); 28843166Snsouch 289197325Savg if (!sc->poll && intr == PCI_INTR_SMB_SMI) { 290197325Savg device_printf(dev, 291197325Savg "using polling mode when configured interrupt is SMI\n"); 292197325Savg sc->poll = 1; 293197325Savg } 294197325Savg 295197128Savg if (sc->poll) 296197128Savg goto no_intr; 297197128Savg 298197128Savg if (intr != PCI_INTR_SMB_IRQ9 && intr != PCI_INTR_SMB_IRQ_PCI) { 299165951Sjhb device_printf(dev, "Unsupported interrupt mode\n"); 300165951Sjhb error = ENXIO; 301165951Sjhb goto fail; 302165951Sjhb } 30346651Speter 304165951Sjhb /* Force IRQ 9. */ 305165951Sjhb rid = 0; 306197128Savg if (sc->cfg_irq9) 307197128Savg bus_set_resource(dev, SYS_RES_IRQ, rid, 9, 1); 308197128Savg 309165951Sjhb sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 310165951Sjhb RF_SHAREABLE | RF_ACTIVE); 311165951Sjhb if (sc->irq_res == NULL) { 312165951Sjhb device_printf(dev, "Could not allocate irq\n"); 313165951Sjhb error = ENXIO; 314165951Sjhb goto fail; 315165951Sjhb } 31643166Snsouch 317179622Sjhb error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE, 318179622Sjhb NULL, intsmb_rawintr, sc, &sc->irq_hand); 319165951Sjhb if (error) { 320165951Sjhb device_printf(dev, "Failed to map intr\n"); 321165951Sjhb goto fail; 322165951Sjhb } 323162289Sjhb 324197128Savgno_intr: 325165951Sjhb sc->isbusy = 0; 326165951Sjhb sc->smbus = device_add_child(dev, "smbus", -1); 327165951Sjhb if (sc->smbus == NULL) { 328306122Savg device_printf(dev, "failed to add smbus child\n"); 329165951Sjhb error = ENXIO; 330165951Sjhb goto fail; 331165951Sjhb } 332165951Sjhb error = device_probe_and_attach(sc->smbus); 333306122Savg if (error) { 334306122Savg device_printf(dev, "failed to probe+attach smbus child\n"); 335165951Sjhb goto fail; 336306122Savg } 337162289Sjhb 338165951Sjhb#ifdef ENABLE_ALART 339165951Sjhb /* Enable Arart */ 340165951Sjhb bus_write_1(sc->io_res, PIIX4_SMBSLVCNT, PIIX4_SMBSLVCNT_ALTEN); 341165951Sjhb#endif 342165951Sjhb return (0); 34343166Snsouch 344165951Sjhbfail: 345306122Savg intsmb_release_resources(dev); 346165951Sjhb return (error); 347165951Sjhb} 348165951Sjhb 349162289Sjhbstatic int 350165951Sjhbintsmb_detach(device_t dev) 35143166Snsouch{ 352165951Sjhb int error; 353162289Sjhb 354165951Sjhb error = bus_generic_detach(dev); 355306122Savg if (error) { 356306122Savg device_printf(dev, "bus detach failed\n"); 357165951Sjhb return (error); 358306122Savg } 359162289Sjhb 360306122Savg intsmb_release_resources(dev); 361165951Sjhb return (0); 36243166Snsouch} 363165951Sjhb 364165951Sjhbstatic void 365165951Sjhbintsmb_rawintr(void *arg) 36643166Snsouch{ 367165951Sjhb struct intsmb_softc *sc = arg; 368162289Sjhb 369165951Sjhb INTSMB_LOCK(sc); 370165951Sjhb intsmb_intr(sc); 371165951Sjhb intsmb_slvintr(sc); 372165951Sjhb INTSMB_UNLOCK(sc); 37343166Snsouch} 37443166Snsouch 375162289Sjhbstatic int 376162234Sjhbintsmb_callback(device_t dev, int index, void *data) 37743166Snsouch{ 37843166Snsouch int error = 0; 379162289Sjhb 38043166Snsouch switch (index) { 38143166Snsouch case SMB_REQUEST_BUS: 38243166Snsouch break; 38343166Snsouch case SMB_RELEASE_BUS: 38443166Snsouch break; 38543166Snsouch default: 386234043Savg error = SMB_EINVAL; 38743166Snsouch } 388162289Sjhb 38943166Snsouch return (error); 39043166Snsouch} 391162289Sjhb 392162289Sjhb/* Counterpart of smbtx_smb_free(). */ 393162289Sjhbstatic int 394165951Sjhbintsmb_free(struct intsmb_softc *sc) 395162289Sjhb{ 396162289Sjhb 397165951Sjhb INTSMB_LOCK_ASSERT(sc); 398165951Sjhb if ((bus_read_1(sc->io_res, PIIX4_SMBHSTSTS) & PIIX4_SMBHSTSTAT_BUSY) || 39943166Snsouch#ifdef ENABLE_ALART 400165951Sjhb (bus_read_1(sc->io_res, PIIX4_SMBSLVSTS) & PIIX4_SMBSLVSTS_BUSY) || 40143166Snsouch#endif 402162289Sjhb sc->isbusy) 403165951Sjhb return (SMB_EBUSY); 404165951Sjhb 405162289Sjhb sc->isbusy = 1; 406162289Sjhb /* Disable Interrupt in slave part. */ 40743166Snsouch#ifndef ENABLE_ALART 408165951Sjhb bus_write_1(sc->io_res, PIIX4_SMBSLVCNT, 0); 40943166Snsouch#endif 410162289Sjhb /* Reset INTR Flag to prepare INTR. */ 411165951Sjhb bus_write_1(sc->io_res, PIIX4_SMBHSTSTS, 412165951Sjhb PIIX4_SMBHSTSTAT_INTR | PIIX4_SMBHSTSTAT_ERR | 413165951Sjhb PIIX4_SMBHSTSTAT_BUSC | PIIX4_SMBHSTSTAT_FAIL); 414162289Sjhb return (0); 41543166Snsouch} 41643166Snsouch 41743166Snsouchstatic int 418165951Sjhbintsmb_intr(struct intsmb_softc *sc) 41943166Snsouch{ 420165951Sjhb int status, tmp; 421162289Sjhb 422165951Sjhb status = bus_read_1(sc->io_res, PIIX4_SMBHSTSTS); 423162289Sjhb if (status & PIIX4_SMBHSTSTAT_BUSY) 424162289Sjhb return (1); 425162289Sjhb 426162289Sjhb if (status & (PIIX4_SMBHSTSTAT_INTR | PIIX4_SMBHSTSTAT_ERR | 427162289Sjhb PIIX4_SMBHSTSTAT_BUSC | PIIX4_SMBHSTSTAT_FAIL)) { 428162289Sjhb 429165951Sjhb tmp = bus_read_1(sc->io_res, PIIX4_SMBHSTCNT); 430165951Sjhb bus_write_1(sc->io_res, PIIX4_SMBHSTCNT, 431162289Sjhb tmp & ~PIIX4_SMBHSTCNT_INTREN); 432162289Sjhb if (sc->isbusy) { 433162289Sjhb sc->isbusy = 0; 434162289Sjhb wakeup(sc); 43549064Snsouch } 436162289Sjhb return (0); 43743166Snsouch } 438162289Sjhb return (1); /* Not Completed */ 43943166Snsouch} 440162289Sjhb 44143166Snsouchstatic int 442165951Sjhbintsmb_slvintr(struct intsmb_softc *sc) 44343166Snsouch{ 444165951Sjhb int status; 445162289Sjhb 446165951Sjhb status = bus_read_1(sc->io_res, PIIX4_SMBSLVSTS); 447162289Sjhb if (status & PIIX4_SMBSLVSTS_BUSY) 448165951Sjhb return (1); 449165951Sjhb if (status & PIIX4_SMBSLVSTS_ALART) 450165951Sjhb intsmb_alrintr(sc); 451165951Sjhb else if (status & ~(PIIX4_SMBSLVSTS_ALART | PIIX4_SMBSLVSTS_SDW2 452162289Sjhb | PIIX4_SMBSLVSTS_SDW1)) { 45343166Snsouch } 454162289Sjhb 455162289Sjhb /* Reset Status Register */ 456165951Sjhb bus_write_1(sc->io_res, PIIX4_SMBSLVSTS, 457162289Sjhb PIIX4_SMBSLVSTS_ALART | PIIX4_SMBSLVSTS_SDW2 | 458162289Sjhb PIIX4_SMBSLVSTS_SDW1 | PIIX4_SMBSLVSTS_SLV); 459165951Sjhb return (0); 46043166Snsouch} 46143166Snsouch 462162289Sjhbstatic void 463165951Sjhbintsmb_alrintr(struct intsmb_softc *sc) 46443166Snsouch{ 46543166Snsouch int slvcnt; 46643288Sdillon#ifdef ENABLE_ALART 46743288Sdillon int error; 468165951Sjhb uint8_t addr; 46943288Sdillon#endif 47043288Sdillon 471162289Sjhb /* Stop generating INTR from ALART. */ 472165951Sjhb slvcnt = bus_read_1(sc->io_res, PIIX4_SMBSLVCNT); 47343166Snsouch#ifdef ENABLE_ALART 474165951Sjhb bus_write_1(sc->io_res, PIIX4_SMBSLVCNT, 475162289Sjhb slvcnt & ~PIIX4_SMBSLVCNT_ALTEN); 47643166Snsouch#endif 47743166Snsouch DELAY(5); 478162289Sjhb 479162289Sjhb /* Ask bus who asserted it and then ask it what's the matter. */ 48043166Snsouch#ifdef ENABLE_ALART 481165951Sjhb error = intsmb_free(sc); 482165951Sjhb if (error) 483165951Sjhb return; 484162289Sjhb 485165951Sjhb bus_write_1(sc->io_res, PIIX4_SMBHSTADD, SMBALTRESP | LSB); 486165951Sjhb intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_BYTE, 1); 487165951Sjhb error = intsmb_stop_poll(sc); 488165951Sjhb if (error) 489165951Sjhb device_printf(sc->dev, "ALART: ERROR\n"); 490165951Sjhb else { 491165951Sjhb addr = bus_read_1(sc->io_res, PIIX4_SMBHSTDAT0); 492165951Sjhb device_printf(sc->dev, "ALART_RESPONSE: 0x%x\n", addr); 493165951Sjhb } 49443166Snsouch 495162289Sjhb /* Re-enable INTR from ALART. */ 496165951Sjhb bus_write_1(sc->io_res, PIIX4_SMBSLVCNT, 497162289Sjhb slvcnt | PIIX4_SMBSLVCNT_ALTEN); 49843166Snsouch DELAY(5); 49943166Snsouch#endif 500162289Sjhb} 50143166Snsouch 50243166Snsouchstatic void 503165951Sjhbintsmb_start(struct intsmb_softc *sc, unsigned char cmd, int nointr) 50443166Snsouch{ 50543166Snsouch unsigned char tmp; 506162289Sjhb 507165951Sjhb INTSMB_LOCK_ASSERT(sc); 508165951Sjhb tmp = bus_read_1(sc->io_res, PIIX4_SMBHSTCNT); 509162289Sjhb tmp &= 0xe0; 51043166Snsouch tmp |= cmd; 511162289Sjhb tmp |= PIIX4_SMBHSTCNT_START; 512162289Sjhb 513162289Sjhb /* While not in autoconfiguration enable interrupts. */ 514197128Savg if (!sc->poll && !cold && !nointr) 515162289Sjhb tmp |= PIIX4_SMBHSTCNT_INTREN; 516165951Sjhb bus_write_1(sc->io_res, PIIX4_SMBHSTCNT, tmp); 51743166Snsouch} 51843166Snsouch 519165951Sjhbstatic int 520189882Savgintsmb_error(device_t dev, int status) 521165951Sjhb{ 522165951Sjhb int error = 0; 523165951Sjhb 524165951Sjhb if (status & PIIX4_SMBHSTSTAT_ERR) 525165951Sjhb error |= SMB_EBUSERR; 526165951Sjhb if (status & PIIX4_SMBHSTSTAT_BUSC) 527165951Sjhb error |= SMB_ECOLLI; 528165951Sjhb if (status & PIIX4_SMBHSTSTAT_FAIL) 529165951Sjhb error |= SMB_ENOACK; 530189882Savg 531189882Savg if (error != 0 && bootverbose) 532189882Savg device_printf(dev, "error = %d, status = %#x\n", error, status); 533189882Savg 534165951Sjhb return (error); 535165951Sjhb} 536165951Sjhb 537162289Sjhb/* 538162289Sjhb * Polling Code. 539162289Sjhb * 540162289Sjhb * Polling is not encouraged because it requires waiting for the 541162289Sjhb * device if it is busy. 542162289Sjhb * (29063505.pdf from Intel) But during boot, interrupt cannot be used, so use 543162289Sjhb * polling code then. 54443166Snsouch */ 545162289Sjhbstatic int 546165951Sjhbintsmb_stop_poll(struct intsmb_softc *sc) 547162289Sjhb{ 548165951Sjhb int error, i, status, tmp; 54943166Snsouch 550165951Sjhb INTSMB_LOCK_ASSERT(sc); 551165951Sjhb 552165951Sjhb /* First, wait for busy to be set. */ 553162289Sjhb for (i = 0; i < 0x7fff; i++) 554165951Sjhb if (bus_read_1(sc->io_res, PIIX4_SMBHSTSTS) & 555162289Sjhb PIIX4_SMBHSTSTAT_BUSY) 556162289Sjhb break; 557162289Sjhb 558165951Sjhb /* Wait for busy to clear. */ 559162289Sjhb for (i = 0; i < 0x7fff; i++) { 560165951Sjhb status = bus_read_1(sc->io_res, PIIX4_SMBHSTSTS); 561162289Sjhb if (!(status & PIIX4_SMBHSTSTAT_BUSY)) { 562162289Sjhb sc->isbusy = 0; 563189882Savg error = intsmb_error(sc->dev, status); 564162289Sjhb return (error); 56543166Snsouch } 56643166Snsouch } 567162289Sjhb 568165951Sjhb /* Timed out waiting for busy to clear. */ 569162289Sjhb sc->isbusy = 0; 570165951Sjhb tmp = bus_read_1(sc->io_res, PIIX4_SMBHSTCNT); 571165951Sjhb bus_write_1(sc->io_res, PIIX4_SMBHSTCNT, tmp & ~PIIX4_SMBHSTCNT_INTREN); 572165951Sjhb return (SMB_ETIMEOUT); 57343166Snsouch} 574162289Sjhb 57543166Snsouch/* 576162289Sjhb * Wait for completion and return result. 57743166Snsouch */ 578162289Sjhbstatic int 579165951Sjhbintsmb_stop(struct intsmb_softc *sc) 580162289Sjhb{ 581165951Sjhb int error, status; 582162289Sjhb 583165951Sjhb INTSMB_LOCK_ASSERT(sc); 584165951Sjhb 585197128Savg if (sc->poll || cold) 586162289Sjhb /* So that it can use device during device probe on SMBus. */ 587165951Sjhb return (intsmb_stop_poll(sc)); 588162289Sjhb 589172667Sjhb error = msleep(sc, &sc->lock, PWAIT | PCATCH, "SMBWAI", hz / 8); 590165951Sjhb if (error == 0) { 591165951Sjhb status = bus_read_1(sc->io_res, PIIX4_SMBHSTSTS); 592162289Sjhb if (!(status & PIIX4_SMBHSTSTAT_BUSY)) { 593189882Savg error = intsmb_error(sc->dev, status); 594162289Sjhb if (error == 0 && !(status & PIIX4_SMBHSTSTAT_INTR)) 595165951Sjhb device_printf(sc->dev, "unknown cause why?\n"); 59643166Snsouch#ifdef ENABLE_ALART 597165951Sjhb bus_write_1(sc->io_res, PIIX4_SMBSLVCNT, 598162289Sjhb PIIX4_SMBSLVCNT_ALTEN); 59943166Snsouch#endif 600162289Sjhb return (error); 60143166Snsouch } 60243166Snsouch } 603162289Sjhb 604162289Sjhb /* Timeout Procedure. */ 605162289Sjhb sc->isbusy = 0; 606162289Sjhb 607298955Spfg /* Re-enable suppressed interrupt from slave part. */ 608165951Sjhb bus_write_1(sc->io_res, PIIX4_SMBSLVCNT, PIIX4_SMBSLVCNT_ALTEN); 609165951Sjhb if (error == EWOULDBLOCK) 610165951Sjhb return (SMB_ETIMEOUT); 611165951Sjhb else 612165951Sjhb return (SMB_EABORT); 61343166Snsouch} 61443166Snsouch 61543166Snsouchstatic int 61643166Snsouchintsmb_quick(device_t dev, u_char slave, int how) 61743166Snsouch{ 618162289Sjhb struct intsmb_softc *sc = device_get_softc(dev); 619165951Sjhb int error; 620162289Sjhb u_char data; 621162289Sjhb 622162289Sjhb data = slave; 623162289Sjhb 624162289Sjhb /* Quick command is part of Address, I think. */ 625162289Sjhb switch(how) { 626162289Sjhb case SMB_QWRITE: 627162289Sjhb data &= ~LSB; 62843166Snsouch break; 629162289Sjhb case SMB_QREAD: 630162289Sjhb data |= LSB; 631162289Sjhb break; 632162289Sjhb default: 633234043Savg return (SMB_EINVAL); 634162289Sjhb } 635165951Sjhb 636165951Sjhb INTSMB_LOCK(sc); 637165951Sjhb error = intsmb_free(sc); 638165951Sjhb if (error) { 639165951Sjhb INTSMB_UNLOCK(sc); 640165951Sjhb return (error); 641162289Sjhb } 642165951Sjhb bus_write_1(sc->io_res, PIIX4_SMBHSTADD, data); 643165951Sjhb intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_QUICK, 0); 644165951Sjhb error = intsmb_stop(sc); 645165951Sjhb INTSMB_UNLOCK(sc); 646162289Sjhb return (error); 64743166Snsouch} 64843166Snsouch 64943166Snsouchstatic int 65043166Snsouchintsmb_sendb(device_t dev, u_char slave, char byte) 65143166Snsouch{ 652162289Sjhb struct intsmb_softc *sc = device_get_softc(dev); 653162289Sjhb int error; 654162289Sjhb 655165951Sjhb INTSMB_LOCK(sc); 656165951Sjhb error = intsmb_free(sc); 657165951Sjhb if (error) { 658165951Sjhb INTSMB_UNLOCK(sc); 659165951Sjhb return (error); 660162289Sjhb } 661165951Sjhb bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave & ~LSB); 662165951Sjhb bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, byte); 663165951Sjhb intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_BYTE, 0); 664165951Sjhb error = intsmb_stop(sc); 665165951Sjhb INTSMB_UNLOCK(sc); 666162289Sjhb return (error); 66743166Snsouch} 668162289Sjhb 66943166Snsouchstatic int 67043166Snsouchintsmb_recvb(device_t dev, u_char slave, char *byte) 67143166Snsouch{ 672162289Sjhb struct intsmb_softc *sc = device_get_softc(dev); 673162289Sjhb int error; 674162289Sjhb 675165951Sjhb INTSMB_LOCK(sc); 676165951Sjhb error = intsmb_free(sc); 677165951Sjhb if (error) { 678165951Sjhb INTSMB_UNLOCK(sc); 679165951Sjhb return (error); 680165951Sjhb } 681165951Sjhb bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave | LSB); 682165951Sjhb intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_BYTE, 0); 683165951Sjhb error = intsmb_stop(sc); 684165951Sjhb if (error == 0) { 68543166Snsouch#ifdef RECV_IS_IN_CMD 686165951Sjhb /* 687165951Sjhb * Linux SMBus stuff also troubles 688165951Sjhb * Because Intel's datasheet does not make clear. 689165951Sjhb */ 690165951Sjhb *byte = bus_read_1(sc->io_res, PIIX4_SMBHSTCMD); 69143166Snsouch#else 692165951Sjhb *byte = bus_read_1(sc->io_res, PIIX4_SMBHSTDAT0); 69343166Snsouch#endif 694162289Sjhb } 695165951Sjhb INTSMB_UNLOCK(sc); 696162289Sjhb return (error); 69743166Snsouch} 698162289Sjhb 69943166Snsouchstatic int 70043166Snsouchintsmb_writeb(device_t dev, u_char slave, char cmd, char byte) 70143166Snsouch{ 702162289Sjhb struct intsmb_softc *sc = device_get_softc(dev); 703162289Sjhb int error; 704162289Sjhb 705165951Sjhb INTSMB_LOCK(sc); 706165951Sjhb error = intsmb_free(sc); 707165951Sjhb if (error) { 708165951Sjhb INTSMB_UNLOCK(sc); 709165951Sjhb return (error); 710162289Sjhb } 711165951Sjhb bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave & ~LSB); 712165951Sjhb bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, cmd); 713165951Sjhb bus_write_1(sc->io_res, PIIX4_SMBHSTDAT0, byte); 714165951Sjhb intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_BDATA, 0); 715165951Sjhb error = intsmb_stop(sc); 716165951Sjhb INTSMB_UNLOCK(sc); 717162289Sjhb return (error); 71843166Snsouch} 719162289Sjhb 72043166Snsouchstatic int 72143166Snsouchintsmb_writew(device_t dev, u_char slave, char cmd, short word) 72243166Snsouch{ 723162289Sjhb struct intsmb_softc *sc = device_get_softc(dev); 724162289Sjhb int error; 725162289Sjhb 726165951Sjhb INTSMB_LOCK(sc); 727165951Sjhb error = intsmb_free(sc); 728165951Sjhb if (error) { 729165951Sjhb INTSMB_UNLOCK(sc); 730165951Sjhb return (error); 731162289Sjhb } 732165951Sjhb bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave & ~LSB); 733165951Sjhb bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, cmd); 734165951Sjhb bus_write_1(sc->io_res, PIIX4_SMBHSTDAT0, word & 0xff); 735165951Sjhb bus_write_1(sc->io_res, PIIX4_SMBHSTDAT1, (word >> 8) & 0xff); 736165951Sjhb intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_WDATA, 0); 737165951Sjhb error = intsmb_stop(sc); 738165951Sjhb INTSMB_UNLOCK(sc); 739162289Sjhb return (error); 74043166Snsouch} 74143166Snsouch 74243166Snsouchstatic int 74343166Snsouchintsmb_readb(device_t dev, u_char slave, char cmd, char *byte) 74443166Snsouch{ 745162289Sjhb struct intsmb_softc *sc = device_get_softc(dev); 746162289Sjhb int error; 747162289Sjhb 748165951Sjhb INTSMB_LOCK(sc); 749165951Sjhb error = intsmb_free(sc); 750165951Sjhb if (error) { 751165951Sjhb INTSMB_UNLOCK(sc); 752165951Sjhb return (error); 753162289Sjhb } 754165951Sjhb bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave | LSB); 755165951Sjhb bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, cmd); 756165951Sjhb intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_BDATA, 0); 757165951Sjhb error = intsmb_stop(sc); 758165951Sjhb if (error == 0) 759165951Sjhb *byte = bus_read_1(sc->io_res, PIIX4_SMBHSTDAT0); 760165951Sjhb INTSMB_UNLOCK(sc); 761162289Sjhb return (error); 76243166Snsouch} 763165951Sjhb 76443166Snsouchstatic int 76543166Snsouchintsmb_readw(device_t dev, u_char slave, char cmd, short *word) 76643166Snsouch{ 767162289Sjhb struct intsmb_softc *sc = device_get_softc(dev); 768162289Sjhb int error; 769162289Sjhb 770165951Sjhb INTSMB_LOCK(sc); 771165951Sjhb error = intsmb_free(sc); 772165951Sjhb if (error) { 773165951Sjhb INTSMB_UNLOCK(sc); 774165951Sjhb return (error); 775162289Sjhb } 776165951Sjhb bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave | LSB); 777165951Sjhb bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, cmd); 778165951Sjhb intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_WDATA, 0); 779165951Sjhb error = intsmb_stop(sc); 780165951Sjhb if (error == 0) { 781165951Sjhb *word = bus_read_1(sc->io_res, PIIX4_SMBHSTDAT0); 782165951Sjhb *word |= bus_read_1(sc->io_res, PIIX4_SMBHSTDAT1) << 8; 783165951Sjhb } 784165951Sjhb INTSMB_UNLOCK(sc); 785162289Sjhb return (error); 78643166Snsouch} 787162289Sjhb 78843166Snsouch/* 78943166Snsouch * Data sheet claims that it implements all function, but also claims 79043166Snsouch * that it implements 7 function and not mention PCALL. So I don't know 79143166Snsouch * whether it will work. 79243166Snsouch */ 79343166Snsouchstatic int 79443166Snsouchintsmb_pcall(device_t dev, u_char slave, char cmd, short sdata, short *rdata) 79543166Snsouch{ 79643166Snsouch#ifdef PROCCALL_TEST 797162289Sjhb struct intsmb_softc *sc = device_get_softc(dev); 798162289Sjhb int error; 799162289Sjhb 800165951Sjhb INTSMB_LOCK(sc); 801165951Sjhb error = intsmb_free(sc); 802165951Sjhb if (error) { 803165951Sjhb INTSMB_UNLOCK(sc); 804165951Sjhb return (error); 805162289Sjhb } 806165951Sjhb bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave & ~LSB); 807165951Sjhb bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, cmd); 808165951Sjhb bus_write_1(sc->io_res, PIIX4_SMBHSTDAT0, sdata & 0xff); 809165951Sjhb bus_write_1(sc->io_res, PIIX4_SMBHSTDAT1, (sdata & 0xff) >> 8); 810165951Sjhb intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_WDATA, 0); 811165951Sjhb error = intsmb_stop(sc); 812165951Sjhb if (error == 0) { 813165951Sjhb *rdata = bus_read_1(sc->io_res, PIIX4_SMBHSTDAT0); 814165951Sjhb *rdata |= bus_read_1(sc->io_res, PIIX4_SMBHSTDAT1) << 8; 815162289Sjhb } 816165951Sjhb INTSMB_UNLOCK(sc); 817162289Sjhb return (error); 81843166Snsouch#else 819165951Sjhb return (SMB_ENOTSUPP); 82043166Snsouch#endif 82143166Snsouch} 822162289Sjhb 82343166Snsouchstatic int 82443166Snsouchintsmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf) 82543166Snsouch{ 826162289Sjhb struct intsmb_softc *sc = device_get_softc(dev); 827162289Sjhb int error, i; 828162289Sjhb 829162289Sjhb if (count > SMBBLOCKTRANS_MAX || count == 0) 830165951Sjhb return (SMB_EINVAL); 831162289Sjhb 832165951Sjhb INTSMB_LOCK(sc); 833165951Sjhb error = intsmb_free(sc); 834165951Sjhb if (error) { 835165951Sjhb INTSMB_UNLOCK(sc); 836165951Sjhb return (error); 837162289Sjhb } 838165951Sjhb 839165951Sjhb /* Reset internal array index. */ 840165951Sjhb bus_read_1(sc->io_res, PIIX4_SMBHSTCNT); 841165951Sjhb 842165951Sjhb bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave & ~LSB); 843165951Sjhb bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, cmd); 844165951Sjhb for (i = 0; i < count; i++) 845165951Sjhb bus_write_1(sc->io_res, PIIX4_SMBBLKDAT, buf[i]); 846165951Sjhb bus_write_1(sc->io_res, PIIX4_SMBHSTDAT0, count); 847165951Sjhb intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_BLOCK, 0); 848165951Sjhb error = intsmb_stop(sc); 849165951Sjhb INTSMB_UNLOCK(sc); 850162289Sjhb return (error); 85143166Snsouch} 85243166Snsouch 85343166Snsouchstatic int 854162234Sjhbintsmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf) 85543166Snsouch{ 856162289Sjhb struct intsmb_softc *sc = device_get_softc(dev); 857162289Sjhb int error, i; 858162234Sjhb u_char data, nread; 859162289Sjhb 860162289Sjhb if (*count > SMBBLOCKTRANS_MAX || *count == 0) 861165951Sjhb return (SMB_EINVAL); 862162289Sjhb 863165951Sjhb INTSMB_LOCK(sc); 864165951Sjhb error = intsmb_free(sc); 865165951Sjhb if (error) { 866165951Sjhb INTSMB_UNLOCK(sc); 867165951Sjhb return (error); 868165951Sjhb } 869165951Sjhb 870165951Sjhb /* Reset internal array index. */ 871165951Sjhb bus_read_1(sc->io_res, PIIX4_SMBHSTCNT); 872165951Sjhb 873165951Sjhb bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave | LSB); 874165951Sjhb bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, cmd); 875165951Sjhb bus_write_1(sc->io_res, PIIX4_SMBHSTDAT0, *count); 876165951Sjhb intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_BLOCK, 0); 877165951Sjhb error = intsmb_stop(sc); 878165951Sjhb if (error == 0) { 879165951Sjhb nread = bus_read_1(sc->io_res, PIIX4_SMBHSTDAT0); 880165951Sjhb if (nread != 0 && nread <= SMBBLOCKTRANS_MAX) { 881165951Sjhb for (i = 0; i < nread; i++) { 882165951Sjhb data = bus_read_1(sc->io_res, PIIX4_SMBBLKDAT); 883165951Sjhb if (i < *count) 884165951Sjhb buf[i] = data; 88543166Snsouch } 886165951Sjhb *count = nread; 887165951Sjhb } else 888234043Savg error = SMB_EBUSERR; 88943166Snsouch } 890165951Sjhb INTSMB_UNLOCK(sc); 891162289Sjhb return (error); 89243166Snsouch} 89343166Snsouch 894165951Sjhbstatic devclass_t intsmb_devclass; 89543166Snsouch 896165951Sjhbstatic device_method_t intsmb_methods[] = { 897165951Sjhb /* Device interface */ 898165951Sjhb DEVMETHOD(device_probe, intsmb_probe), 899165951Sjhb DEVMETHOD(device_attach, intsmb_attach), 900165951Sjhb DEVMETHOD(device_detach, intsmb_detach), 90146651Speter 902165951Sjhb /* SMBus interface */ 903165951Sjhb DEVMETHOD(smbus_callback, intsmb_callback), 904165951Sjhb DEVMETHOD(smbus_quick, intsmb_quick), 905165951Sjhb DEVMETHOD(smbus_sendb, intsmb_sendb), 906165951Sjhb DEVMETHOD(smbus_recvb, intsmb_recvb), 907165951Sjhb DEVMETHOD(smbus_writeb, intsmb_writeb), 908165951Sjhb DEVMETHOD(smbus_writew, intsmb_writew), 909165951Sjhb DEVMETHOD(smbus_readb, intsmb_readb), 910165951Sjhb DEVMETHOD(smbus_readw, intsmb_readw), 911165951Sjhb DEVMETHOD(smbus_pcall, intsmb_pcall), 912165951Sjhb DEVMETHOD(smbus_bwrite, intsmb_bwrite), 913165951Sjhb DEVMETHOD(smbus_bread, intsmb_bread), 914162289Sjhb 915227843Smarius DEVMETHOD_END 916165951Sjhb}; 91743166Snsouch 918165951Sjhbstatic driver_t intsmb_driver = { 919165951Sjhb "intsmb", 920165951Sjhb intsmb_methods, 921165951Sjhb sizeof(struct intsmb_softc), 922165951Sjhb}; 923162289Sjhb 924306124SavgDRIVER_MODULE_ORDERED(intsmb, pci, intsmb_driver, intsmb_devclass, 0, 0, 925306124Savg SI_ORDER_ANY); 926162289SjhbDRIVER_MODULE(smbus, intsmb, smbus_driver, smbus_devclass, 0, 0); 927165951SjhbMODULE_DEPEND(intsmb, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER); 928165951SjhbMODULE_VERSION(intsmb, 1); 929