1 /*- 2 * Copyright (c) 1998, 1999 Takanori Watanabe 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/param.h> 28 #include <sys/systm.h> 29 #include <sys/bus.h> 30 #include <sys/kernel.h> 31 #include <sys/lock.h> 32 #include <sys/module.h> 33 #include <sys/mutex.h> 34 #include <sys/rman.h> 35 #include <machine/bus.h> 36 #include <dev/smbus/smbconf.h> 37 38 #include "smbus_if.h" 39 40 #include <dev/pci/pcireg.h> 41 #include <dev/pci/pcivar.h> 42 #include <dev/intpm/intpmreg.h> 43 #include <dev/amdsbwd/amd_chipset.h> 44 45 #include "opt_intpm.h" 46 47 struct intsmb_softc { 48 device_t dev; 49 struct resource *io_res; 50 struct resource *irq_res; 51 void *irq_hand; 52 device_t smbus; 53 int io_rid; 54 int isbusy; 55 int cfg_irq9; 56 int sb8xx; 57 int poll; 58 struct mtx lock; 59 }; 60 61 #define INTSMB_LOCK(sc) mtx_lock(&(sc)->lock) 62 #define INTSMB_UNLOCK(sc) mtx_unlock(&(sc)->lock) 63 #define INTSMB_LOCK_ASSERT(sc) mtx_assert(&(sc)->lock, MA_OWNED) 64 65 static int intsmb_probe(device_t); 66 static int intsmb_attach(device_t); 67 static int intsmb_detach(device_t); 68 static int intsmb_intr(struct intsmb_softc *sc); 69 static int intsmb_slvintr(struct intsmb_softc *sc); 70 static void intsmb_alrintr(struct intsmb_softc *sc); 71 static int intsmb_callback(device_t dev, int index, void *data); 72 static int intsmb_quick(device_t dev, u_char slave, int how); 73 static int intsmb_sendb(device_t dev, u_char slave, char byte); 74 static int intsmb_recvb(device_t dev, u_char slave, char *byte); 75 static int intsmb_writeb(device_t dev, u_char slave, char cmd, char byte); 76 static int intsmb_writew(device_t dev, u_char slave, char cmd, short word); 77 static int intsmb_readb(device_t dev, u_char slave, char cmd, char *byte); 78 static int intsmb_readw(device_t dev, u_char slave, char cmd, short *word); 79 static int intsmb_pcall(device_t dev, u_char slave, char cmd, short sdata, short *rdata); 80 static int intsmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf); 81 static int intsmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf); 82 static void intsmb_start(struct intsmb_softc *sc, u_char cmd, int nointr); 83 static int intsmb_stop(struct intsmb_softc *sc); 84 static int intsmb_stop_poll(struct intsmb_softc *sc); 85 static int intsmb_free(struct intsmb_softc *sc); 86 static void intsmb_rawintr(void *arg); 87 88 const struct intsmb_device { 89 uint32_t devid; 90 const char *description; 91 } intsmb_products[] = { 92 { 0x71138086, "Intel PIIX4 SMBUS Interface" }, 93 { 0x719b8086, "Intel PIIX4 SMBUS Interface" }, 94 #if 0 95 /* Not a good idea yet, this stops isab0 functioning */ 96 { 0x02001166, "ServerWorks OSB4" }, 97 #endif 98 { 0x43721002, "ATI IXP400 SMBus Controller" }, 99 { AMDSB_SMBUS_DEVID, "AMD SB600/7xx/8xx/9xx SMBus Controller" }, 100 { AMDFCH_SMBUS_DEVID, "AMD FCH SMBus Controller" }, 101 { AMDCZ_SMBUS_DEVID, "AMD FCH SMBus Controller" }, 102 { HYGONCZ_SMBUS_DEVID, "Hygon FCH SMBus Controller" }, 103 }; 104 105 static int 106 intsmb_probe(device_t dev) 107 { 108 const struct intsmb_device *isd; 109 uint32_t devid; 110 size_t i; 111 112 devid = pci_get_devid(dev); 113 for (i = 0; i < nitems(intsmb_products); i++) { 114 isd = &intsmb_products[i]; 115 if (isd->devid == devid) { 116 device_set_desc(dev, isd->description); 117 return (BUS_PROBE_DEFAULT); 118 } 119 } 120 return (ENXIO); 121 } 122 123 static uint8_t 124 amd_pmio_read(struct resource *res, uint8_t reg) 125 { 126 bus_write_1(res, 0, reg); /* Index */ 127 return (bus_read_1(res, 1)); /* Data */ 128 } 129 130 static int 131 sb8xx_attach(device_t dev) 132 { 133 static const int AMDSB_SMBIO_WIDTH = 0x10; 134 struct intsmb_softc *sc; 135 struct resource *res; 136 uint32_t devid; 137 uint8_t revid; 138 uint16_t addr; 139 int rid; 140 int rc; 141 bool enabled; 142 143 sc = device_get_softc(dev); 144 rid = 0; 145 rc = bus_set_resource(dev, SYS_RES_IOPORT, rid, AMDSB_PMIO_INDEX, 146 AMDSB_PMIO_WIDTH); 147 if (rc != 0) { 148 device_printf(dev, "bus_set_resource for PM IO failed\n"); 149 return (ENXIO); 150 } 151 res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, 152 RF_ACTIVE); 153 if (res == NULL) { 154 device_printf(dev, "bus_alloc_resource for PM IO failed\n"); 155 return (ENXIO); 156 } 157 158 devid = pci_get_devid(dev); 159 revid = pci_get_revid(dev); 160 if (devid == AMDSB_SMBUS_DEVID || 161 (devid == AMDFCH_SMBUS_DEVID && revid < AMDFCH41_SMBUS_REVID) || 162 (devid == AMDCZ_SMBUS_DEVID && revid < AMDCZ49_SMBUS_REVID)) { 163 addr = amd_pmio_read(res, AMDSB8_PM_SMBUS_EN + 1); 164 addr <<= 8; 165 addr |= amd_pmio_read(res, AMDSB8_PM_SMBUS_EN); 166 enabled = (addr & AMDSB8_SMBUS_EN) != 0; 167 addr &= AMDSB8_SMBUS_ADDR_MASK; 168 } else { 169 addr = amd_pmio_read(res, AMDFCH41_PM_DECODE_EN0); 170 enabled = (addr & AMDFCH41_SMBUS_EN) != 0; 171 addr = amd_pmio_read(res, AMDFCH41_PM_DECODE_EN1); 172 addr <<= 8; 173 } 174 175 bus_release_resource(dev, SYS_RES_IOPORT, rid, res); 176 bus_delete_resource(dev, SYS_RES_IOPORT, rid); 177 178 if (!enabled) { 179 device_printf(dev, "SB8xx/SB9xx/FCH SMBus not enabled\n"); 180 return (ENXIO); 181 } 182 183 sc->io_rid = 0; 184 rc = bus_set_resource(dev, SYS_RES_IOPORT, sc->io_rid, addr, 185 AMDSB_SMBIO_WIDTH); 186 if (rc != 0) { 187 device_printf(dev, "bus_set_resource for SMBus IO failed\n"); 188 return (ENXIO); 189 } 190 sc->io_res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &sc->io_rid, 191 RF_ACTIVE); 192 if (sc->io_res == NULL) { 193 device_printf(dev, "Could not allocate I/O space\n"); 194 return (ENXIO); 195 } 196 sc->poll = 1; 197 return (0); 198 } 199 200 static void 201 intsmb_release_resources(device_t dev) 202 { 203 struct intsmb_softc *sc = device_get_softc(dev); 204 205 device_delete_children(dev); 206 if (sc->irq_hand) 207 bus_teardown_intr(dev, sc->irq_res, sc->irq_hand); 208 if (sc->irq_res) 209 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res); 210 if (sc->io_res) 211 bus_release_resource(dev, SYS_RES_IOPORT, sc->io_rid, 212 sc->io_res); 213 mtx_destroy(&sc->lock); 214 } 215 216 static int 217 intsmb_attach(device_t dev) 218 { 219 struct intsmb_softc *sc = device_get_softc(dev); 220 int error, rid, value; 221 int intr; 222 char *str; 223 224 sc->dev = dev; 225 226 mtx_init(&sc->lock, device_get_nameunit(dev), "intsmb", MTX_DEF); 227 228 sc->cfg_irq9 = 0; 229 switch (pci_get_devid(dev)) { 230 #ifndef NO_CHANGE_PCICONF 231 case 0x71138086: /* Intel 82371AB */ 232 case 0x719b8086: /* Intel 82443MX */ 233 /* Changing configuration is allowed. */ 234 sc->cfg_irq9 = 1; 235 break; 236 #endif 237 case AMDSB_SMBUS_DEVID: 238 if (pci_get_revid(dev) >= AMDSB8_SMBUS_REVID) 239 sc->sb8xx = 1; 240 break; 241 case AMDFCH_SMBUS_DEVID: 242 case AMDCZ_SMBUS_DEVID: 243 case HYGONCZ_SMBUS_DEVID: 244 sc->sb8xx = 1; 245 break; 246 } 247 248 if (sc->sb8xx) { 249 error = sb8xx_attach(dev); 250 if (error != 0) 251 goto fail; 252 else 253 goto no_intr; 254 } 255 256 sc->io_rid = PCI_BASE_ADDR_SMB; 257 sc->io_res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &sc->io_rid, 258 RF_ACTIVE); 259 if (sc->io_res == NULL) { 260 device_printf(dev, "Could not allocate I/O space\n"); 261 error = ENXIO; 262 goto fail; 263 } 264 265 if (sc->cfg_irq9) { 266 pci_write_config(dev, PCIR_INTLINE, 0x9, 1); 267 pci_write_config(dev, PCI_HST_CFG_SMB, 268 PCI_INTR_SMB_IRQ9 | PCI_INTR_SMB_ENABLE, 1); 269 } 270 value = pci_read_config(dev, PCI_HST_CFG_SMB, 1); 271 sc->poll = (value & PCI_INTR_SMB_ENABLE) == 0; 272 intr = value & PCI_INTR_SMB_MASK; 273 switch (intr) { 274 case PCI_INTR_SMB_SMI: 275 str = "SMI"; 276 break; 277 case PCI_INTR_SMB_IRQ9: 278 str = "IRQ 9"; 279 break; 280 case PCI_INTR_SMB_IRQ_PCI: 281 str = "PCI IRQ"; 282 break; 283 default: 284 str = "BOGUS"; 285 } 286 287 device_printf(dev, "intr %s %s ", str, 288 sc->poll == 0 ? "enabled" : "disabled"); 289 printf("revision %d\n", pci_read_config(dev, PCI_REVID_SMB, 1)); 290 291 if (!sc->poll && intr == PCI_INTR_SMB_SMI) { 292 device_printf(dev, 293 "using polling mode when configured interrupt is SMI\n"); 294 sc->poll = 1; 295 } 296 297 if (sc->poll) 298 goto no_intr; 299 300 if (intr != PCI_INTR_SMB_IRQ9 && intr != PCI_INTR_SMB_IRQ_PCI) { 301 device_printf(dev, "Unsupported interrupt mode\n"); 302 error = ENXIO; 303 goto fail; 304 } 305 306 /* Force IRQ 9. */ 307 rid = 0; 308 if (sc->cfg_irq9) 309 bus_set_resource(dev, SYS_RES_IRQ, rid, 9, 1); 310 311 sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 312 RF_SHAREABLE | RF_ACTIVE); 313 if (sc->irq_res == NULL) { 314 device_printf(dev, "Could not allocate irq\n"); 315 error = ENXIO; 316 goto fail; 317 } 318 319 error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE, 320 NULL, intsmb_rawintr, sc, &sc->irq_hand); 321 if (error) { 322 device_printf(dev, "Failed to map intr\n"); 323 goto fail; 324 } 325 326 no_intr: 327 sc->isbusy = 0; 328 sc->smbus = device_add_child(dev, "smbus", DEVICE_UNIT_ANY); 329 if (sc->smbus == NULL) { 330 device_printf(dev, "failed to add smbus child\n"); 331 error = ENXIO; 332 goto fail; 333 } 334 error = device_probe_and_attach(sc->smbus); 335 if (error) { 336 device_printf(dev, "failed to probe+attach smbus child\n"); 337 goto fail; 338 } 339 340 #ifdef ENABLE_ALART 341 /* Enable Arart */ 342 bus_write_1(sc->io_res, PIIX4_SMBSLVCNT, PIIX4_SMBSLVCNT_ALTEN); 343 #endif 344 return (0); 345 346 fail: 347 intsmb_release_resources(dev); 348 return (error); 349 } 350 351 static int 352 intsmb_detach(device_t dev) 353 { 354 int error; 355 356 error = bus_generic_detach(dev); 357 if (error) { 358 device_printf(dev, "bus detach failed\n"); 359 return (error); 360 } 361 362 intsmb_release_resources(dev); 363 return (0); 364 } 365 366 static void 367 intsmb_rawintr(void *arg) 368 { 369 struct intsmb_softc *sc = arg; 370 371 INTSMB_LOCK(sc); 372 intsmb_intr(sc); 373 intsmb_slvintr(sc); 374 INTSMB_UNLOCK(sc); 375 } 376 377 static int 378 intsmb_callback(device_t dev, int index, void *data) 379 { 380 int error = 0; 381 382 switch (index) { 383 case SMB_REQUEST_BUS: 384 break; 385 case SMB_RELEASE_BUS: 386 break; 387 default: 388 error = SMB_EINVAL; 389 } 390 391 return (error); 392 } 393 394 /* Counterpart of smbtx_smb_free(). */ 395 static int 396 intsmb_free(struct intsmb_softc *sc) 397 { 398 399 INTSMB_LOCK_ASSERT(sc); 400 if ((bus_read_1(sc->io_res, PIIX4_SMBHSTSTS) & PIIX4_SMBHSTSTAT_BUSY) || 401 #ifdef ENABLE_ALART 402 (bus_read_1(sc->io_res, PIIX4_SMBSLVSTS) & PIIX4_SMBSLVSTS_BUSY) || 403 #endif 404 sc->isbusy) 405 return (SMB_EBUSY); 406 407 sc->isbusy = 1; 408 /* Disable Interrupt in slave part. */ 409 #ifndef ENABLE_ALART 410 bus_write_1(sc->io_res, PIIX4_SMBSLVCNT, 0); 411 #endif 412 /* Reset INTR Flag to prepare INTR. */ 413 bus_write_1(sc->io_res, PIIX4_SMBHSTSTS, 414 PIIX4_SMBHSTSTAT_INTR | PIIX4_SMBHSTSTAT_ERR | 415 PIIX4_SMBHSTSTAT_BUSC | PIIX4_SMBHSTSTAT_FAIL); 416 return (0); 417 } 418 419 static int 420 intsmb_intr(struct intsmb_softc *sc) 421 { 422 int status, tmp; 423 424 status = bus_read_1(sc->io_res, PIIX4_SMBHSTSTS); 425 if (status & PIIX4_SMBHSTSTAT_BUSY) 426 return (1); 427 428 if (status & (PIIX4_SMBHSTSTAT_INTR | PIIX4_SMBHSTSTAT_ERR | 429 PIIX4_SMBHSTSTAT_BUSC | PIIX4_SMBHSTSTAT_FAIL)) { 430 431 tmp = bus_read_1(sc->io_res, PIIX4_SMBHSTCNT); 432 bus_write_1(sc->io_res, PIIX4_SMBHSTCNT, 433 tmp & ~PIIX4_SMBHSTCNT_INTREN); 434 if (sc->isbusy) { 435 sc->isbusy = 0; 436 wakeup(sc); 437 } 438 return (0); 439 } 440 return (1); /* Not Completed */ 441 } 442 443 static int 444 intsmb_slvintr(struct intsmb_softc *sc) 445 { 446 int status; 447 448 status = bus_read_1(sc->io_res, PIIX4_SMBSLVSTS); 449 if (status & PIIX4_SMBSLVSTS_BUSY) 450 return (1); 451 if (status & PIIX4_SMBSLVSTS_ALART) 452 intsmb_alrintr(sc); 453 else if (status & ~(PIIX4_SMBSLVSTS_ALART | PIIX4_SMBSLVSTS_SDW2 454 | PIIX4_SMBSLVSTS_SDW1)) { 455 } 456 457 /* Reset Status Register */ 458 bus_write_1(sc->io_res, PIIX4_SMBSLVSTS, 459 PIIX4_SMBSLVSTS_ALART | PIIX4_SMBSLVSTS_SDW2 | 460 PIIX4_SMBSLVSTS_SDW1 | PIIX4_SMBSLVSTS_SLV); 461 return (0); 462 } 463 464 static void 465 intsmb_alrintr(struct intsmb_softc *sc) 466 { 467 int slvcnt __unused; 468 #ifdef ENABLE_ALART 469 int error; 470 uint8_t addr; 471 #endif 472 473 /* Stop generating INTR from ALART. */ 474 slvcnt = bus_read_1(sc->io_res, PIIX4_SMBSLVCNT); 475 #ifdef ENABLE_ALART 476 bus_write_1(sc->io_res, PIIX4_SMBSLVCNT, 477 slvcnt & ~PIIX4_SMBSLVCNT_ALTEN); 478 #endif 479 DELAY(5); 480 481 /* Ask bus who asserted it and then ask it what's the matter. */ 482 #ifdef ENABLE_ALART 483 error = intsmb_free(sc); 484 if (error) 485 return; 486 487 bus_write_1(sc->io_res, PIIX4_SMBHSTADD, SMBALTRESP | LSB); 488 intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_BYTE, 1); 489 error = intsmb_stop_poll(sc); 490 if (error) 491 device_printf(sc->dev, "ALART: ERROR\n"); 492 else { 493 addr = bus_read_1(sc->io_res, PIIX4_SMBHSTDAT0); 494 device_printf(sc->dev, "ALART_RESPONSE: 0x%x\n", addr); 495 } 496 497 /* Re-enable INTR from ALART. */ 498 bus_write_1(sc->io_res, PIIX4_SMBSLVCNT, 499 slvcnt | PIIX4_SMBSLVCNT_ALTEN); 500 DELAY(5); 501 #endif 502 } 503 504 static void 505 intsmb_start(struct intsmb_softc *sc, unsigned char cmd, int nointr) 506 { 507 unsigned char tmp; 508 509 INTSMB_LOCK_ASSERT(sc); 510 tmp = bus_read_1(sc->io_res, PIIX4_SMBHSTCNT); 511 tmp &= 0xe0; 512 tmp |= cmd; 513 tmp |= PIIX4_SMBHSTCNT_START; 514 515 /* While not in autoconfiguration enable interrupts. */ 516 if (!sc->poll && !cold && !nointr) 517 tmp |= PIIX4_SMBHSTCNT_INTREN; 518 bus_write_1(sc->io_res, PIIX4_SMBHSTCNT, tmp); 519 } 520 521 static int 522 intsmb_error(device_t dev, int status) 523 { 524 int error = 0; 525 526 /* 527 * PIIX4_SMBHSTSTAT_ERR can mean either of 528 * - SMB_ENOACK ("Unclaimed cycle"), 529 * - SMB_ETIMEOUT ("Host device time-out"), 530 * - SMB_EINVAL ("Illegal command field"). 531 * SMB_ENOACK seems to be most typical. 532 */ 533 if (status & PIIX4_SMBHSTSTAT_ERR) 534 error |= SMB_ENOACK; 535 if (status & PIIX4_SMBHSTSTAT_BUSC) 536 error |= SMB_ECOLLI; 537 if (status & PIIX4_SMBHSTSTAT_FAIL) 538 error |= SMB_EABORT; 539 540 if (error != 0 && bootverbose) 541 device_printf(dev, "error = %d, status = %#x\n", error, status); 542 543 return (error); 544 } 545 546 /* 547 * Polling Code. 548 * 549 * Polling is not encouraged because it requires waiting for the 550 * device if it is busy. 551 * (29063505.pdf from Intel) But during boot, interrupt cannot be used, so use 552 * polling code then. 553 */ 554 static int 555 intsmb_stop_poll(struct intsmb_softc *sc) 556 { 557 int error, i, status, tmp; 558 559 INTSMB_LOCK_ASSERT(sc); 560 561 /* First, wait for busy to be set. */ 562 for (i = 0; i < 0x7fff; i++) 563 if (bus_read_1(sc->io_res, PIIX4_SMBHSTSTS) & 564 PIIX4_SMBHSTSTAT_BUSY) 565 break; 566 567 /* Wait for busy to clear. */ 568 for (i = 0; i < 0x7fff; i++) { 569 status = bus_read_1(sc->io_res, PIIX4_SMBHSTSTS); 570 if (!(status & PIIX4_SMBHSTSTAT_BUSY)) { 571 sc->isbusy = 0; 572 error = intsmb_error(sc->dev, status); 573 return (error); 574 } 575 } 576 577 /* Timed out waiting for busy to clear. */ 578 sc->isbusy = 0; 579 tmp = bus_read_1(sc->io_res, PIIX4_SMBHSTCNT); 580 bus_write_1(sc->io_res, PIIX4_SMBHSTCNT, tmp & ~PIIX4_SMBHSTCNT_INTREN); 581 return (SMB_ETIMEOUT); 582 } 583 584 /* 585 * Wait for completion and return result. 586 */ 587 static int 588 intsmb_stop(struct intsmb_softc *sc) 589 { 590 int error, status; 591 592 INTSMB_LOCK_ASSERT(sc); 593 594 if (sc->poll || cold) 595 /* So that it can use device during device probe on SMBus. */ 596 return (intsmb_stop_poll(sc)); 597 598 error = msleep(sc, &sc->lock, PWAIT | PCATCH, "SMBWAI", hz / 8); 599 if (error == 0) { 600 status = bus_read_1(sc->io_res, PIIX4_SMBHSTSTS); 601 if (!(status & PIIX4_SMBHSTSTAT_BUSY)) { 602 error = intsmb_error(sc->dev, status); 603 if (error == 0 && !(status & PIIX4_SMBHSTSTAT_INTR)) 604 device_printf(sc->dev, "unknown cause why?\n"); 605 #ifdef ENABLE_ALART 606 bus_write_1(sc->io_res, PIIX4_SMBSLVCNT, 607 PIIX4_SMBSLVCNT_ALTEN); 608 #endif 609 return (error); 610 } 611 } 612 613 /* Timeout Procedure. */ 614 sc->isbusy = 0; 615 616 /* Re-enable suppressed interrupt from slave part. */ 617 bus_write_1(sc->io_res, PIIX4_SMBSLVCNT, PIIX4_SMBSLVCNT_ALTEN); 618 if (error == EWOULDBLOCK) 619 return (SMB_ETIMEOUT); 620 else 621 return (SMB_EABORT); 622 } 623 624 static int 625 intsmb_quick(device_t dev, u_char slave, int how) 626 { 627 struct intsmb_softc *sc = device_get_softc(dev); 628 int error; 629 u_char data; 630 631 data = slave; 632 633 /* Quick command is part of Address, I think. */ 634 switch(how) { 635 case SMB_QWRITE: 636 data &= ~LSB; 637 break; 638 case SMB_QREAD: 639 data |= LSB; 640 break; 641 default: 642 return (SMB_EINVAL); 643 } 644 645 INTSMB_LOCK(sc); 646 error = intsmb_free(sc); 647 if (error) { 648 INTSMB_UNLOCK(sc); 649 return (error); 650 } 651 bus_write_1(sc->io_res, PIIX4_SMBHSTADD, data); 652 intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_QUICK, 0); 653 error = intsmb_stop(sc); 654 INTSMB_UNLOCK(sc); 655 return (error); 656 } 657 658 static int 659 intsmb_sendb(device_t dev, u_char slave, char byte) 660 { 661 struct intsmb_softc *sc = device_get_softc(dev); 662 int error; 663 664 INTSMB_LOCK(sc); 665 error = intsmb_free(sc); 666 if (error) { 667 INTSMB_UNLOCK(sc); 668 return (error); 669 } 670 bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave & ~LSB); 671 bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, byte); 672 intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_BYTE, 0); 673 error = intsmb_stop(sc); 674 INTSMB_UNLOCK(sc); 675 return (error); 676 } 677 678 static int 679 intsmb_recvb(device_t dev, u_char slave, char *byte) 680 { 681 struct intsmb_softc *sc = device_get_softc(dev); 682 int error; 683 684 INTSMB_LOCK(sc); 685 error = intsmb_free(sc); 686 if (error) { 687 INTSMB_UNLOCK(sc); 688 return (error); 689 } 690 bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave | LSB); 691 intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_BYTE, 0); 692 error = intsmb_stop(sc); 693 if (error == 0) { 694 #ifdef RECV_IS_IN_CMD 695 /* 696 * Linux SMBus stuff also troubles 697 * Because Intel's datasheet does not make clear. 698 */ 699 *byte = bus_read_1(sc->io_res, PIIX4_SMBHSTCMD); 700 #else 701 *byte = bus_read_1(sc->io_res, PIIX4_SMBHSTDAT0); 702 #endif 703 } 704 INTSMB_UNLOCK(sc); 705 return (error); 706 } 707 708 static int 709 intsmb_writeb(device_t dev, u_char slave, char cmd, char byte) 710 { 711 struct intsmb_softc *sc = device_get_softc(dev); 712 int error; 713 714 INTSMB_LOCK(sc); 715 error = intsmb_free(sc); 716 if (error) { 717 INTSMB_UNLOCK(sc); 718 return (error); 719 } 720 bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave & ~LSB); 721 bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, cmd); 722 bus_write_1(sc->io_res, PIIX4_SMBHSTDAT0, byte); 723 intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_BDATA, 0); 724 error = intsmb_stop(sc); 725 INTSMB_UNLOCK(sc); 726 return (error); 727 } 728 729 static int 730 intsmb_writew(device_t dev, u_char slave, char cmd, short word) 731 { 732 struct intsmb_softc *sc = device_get_softc(dev); 733 int error; 734 735 INTSMB_LOCK(sc); 736 error = intsmb_free(sc); 737 if (error) { 738 INTSMB_UNLOCK(sc); 739 return (error); 740 } 741 bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave & ~LSB); 742 bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, cmd); 743 bus_write_1(sc->io_res, PIIX4_SMBHSTDAT0, word & 0xff); 744 bus_write_1(sc->io_res, PIIX4_SMBHSTDAT1, (word >> 8) & 0xff); 745 intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_WDATA, 0); 746 error = intsmb_stop(sc); 747 INTSMB_UNLOCK(sc); 748 return (error); 749 } 750 751 static int 752 intsmb_readb(device_t dev, u_char slave, char cmd, char *byte) 753 { 754 struct intsmb_softc *sc = device_get_softc(dev); 755 int error; 756 757 INTSMB_LOCK(sc); 758 error = intsmb_free(sc); 759 if (error) { 760 INTSMB_UNLOCK(sc); 761 return (error); 762 } 763 bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave | LSB); 764 bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, cmd); 765 intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_BDATA, 0); 766 error = intsmb_stop(sc); 767 if (error == 0) 768 *byte = bus_read_1(sc->io_res, PIIX4_SMBHSTDAT0); 769 INTSMB_UNLOCK(sc); 770 return (error); 771 } 772 773 static int 774 intsmb_readw(device_t dev, u_char slave, char cmd, short *word) 775 { 776 struct intsmb_softc *sc = device_get_softc(dev); 777 int error; 778 779 INTSMB_LOCK(sc); 780 error = intsmb_free(sc); 781 if (error) { 782 INTSMB_UNLOCK(sc); 783 return (error); 784 } 785 bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave | LSB); 786 bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, cmd); 787 intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_WDATA, 0); 788 error = intsmb_stop(sc); 789 if (error == 0) { 790 *word = bus_read_1(sc->io_res, PIIX4_SMBHSTDAT0); 791 *word |= bus_read_1(sc->io_res, PIIX4_SMBHSTDAT1) << 8; 792 } 793 INTSMB_UNLOCK(sc); 794 return (error); 795 } 796 797 static int 798 intsmb_pcall(device_t dev, u_char slave, char cmd, short sdata, short *rdata) 799 { 800 801 return (SMB_ENOTSUPP); 802 } 803 804 static int 805 intsmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf) 806 { 807 struct intsmb_softc *sc = device_get_softc(dev); 808 int error, i; 809 810 if (count > SMBBLOCKTRANS_MAX || count == 0) 811 return (SMB_EINVAL); 812 813 INTSMB_LOCK(sc); 814 error = intsmb_free(sc); 815 if (error) { 816 INTSMB_UNLOCK(sc); 817 return (error); 818 } 819 820 /* Reset internal array index. */ 821 bus_read_1(sc->io_res, PIIX4_SMBHSTCNT); 822 823 bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave & ~LSB); 824 bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, cmd); 825 for (i = 0; i < count; i++) 826 bus_write_1(sc->io_res, PIIX4_SMBBLKDAT, buf[i]); 827 bus_write_1(sc->io_res, PIIX4_SMBHSTDAT0, count); 828 intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_BLOCK, 0); 829 error = intsmb_stop(sc); 830 INTSMB_UNLOCK(sc); 831 return (error); 832 } 833 834 static int 835 intsmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf) 836 { 837 struct intsmb_softc *sc = device_get_softc(dev); 838 int error, i; 839 u_char nread; 840 841 INTSMB_LOCK(sc); 842 error = intsmb_free(sc); 843 if (error) { 844 INTSMB_UNLOCK(sc); 845 return (error); 846 } 847 848 /* Reset internal array index. */ 849 bus_read_1(sc->io_res, PIIX4_SMBHSTCNT); 850 851 bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave | LSB); 852 bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, cmd); 853 intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_BLOCK, 0); 854 error = intsmb_stop(sc); 855 if (error == 0) { 856 nread = bus_read_1(sc->io_res, PIIX4_SMBHSTDAT0); 857 if (nread != 0 && nread <= SMBBLOCKTRANS_MAX) { 858 *count = nread; 859 for (i = 0; i < nread; i++) 860 bus_read_1(sc->io_res, PIIX4_SMBBLKDAT); 861 } else 862 error = SMB_EBUSERR; 863 } 864 INTSMB_UNLOCK(sc); 865 return (error); 866 } 867 868 static device_method_t intsmb_methods[] = { 869 /* Device interface */ 870 DEVMETHOD(device_probe, intsmb_probe), 871 DEVMETHOD(device_attach, intsmb_attach), 872 DEVMETHOD(device_detach, intsmb_detach), 873 874 /* SMBus interface */ 875 DEVMETHOD(smbus_callback, intsmb_callback), 876 DEVMETHOD(smbus_quick, intsmb_quick), 877 DEVMETHOD(smbus_sendb, intsmb_sendb), 878 DEVMETHOD(smbus_recvb, intsmb_recvb), 879 DEVMETHOD(smbus_writeb, intsmb_writeb), 880 DEVMETHOD(smbus_writew, intsmb_writew), 881 DEVMETHOD(smbus_readb, intsmb_readb), 882 DEVMETHOD(smbus_readw, intsmb_readw), 883 DEVMETHOD(smbus_pcall, intsmb_pcall), 884 DEVMETHOD(smbus_bwrite, intsmb_bwrite), 885 DEVMETHOD(smbus_bread, intsmb_bread), 886 887 DEVMETHOD_END 888 }; 889 890 static driver_t intsmb_driver = { 891 "intsmb", 892 intsmb_methods, 893 sizeof(struct intsmb_softc), 894 }; 895 896 DRIVER_MODULE_ORDERED(intsmb, pci, intsmb_driver, 0, 0, SI_ORDER_ANY); 897 DRIVER_MODULE(smbus, intsmb, smbus_driver, 0, 0); 898 MODULE_DEPEND(intsmb, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER); 899 MODULE_VERSION(intsmb, 1); 900 MODULE_PNP_INFO("W32:vendor/device;D:#", pci, intpm, intsmb_products, 901 nitems(intsmb_products)); 902