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