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