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