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