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