intpm.c revision 142398
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: head/sys/pci/intpm.c 142398 2005-02-24 21:32:56Z imp $"); 29 30#include <sys/param.h> 31#include <sys/systm.h> 32#include <sys/kernel.h> 33#include <machine/bus_pio.h> 34#include <machine/bus_memio.h> 35#include <machine/bus.h> 36 37#include <sys/uio.h> 38#include <sys/module.h> 39#include <sys/bus.h> 40#include <sys/rman.h> 41#include <machine/resource.h> 42#include <dev/smbus/smbconf.h> 43 44#include "smbus_if.h" 45 46/*This should be removed if force_pci_map_int supported*/ 47#include <sys/interrupt.h> 48 49#include <dev/pci/pcireg.h> 50#include <dev/pci/pcivar.h> 51#include <pci/intpmreg.h> 52 53#include "opt_intpm.h" 54 55static struct _pcsid 56{ 57 u_int32_t type; 58 char *desc; 59} pci_ids[] = 60{ 61 { 0x71138086,"Intel 82371AB Power management controller"}, 62 { 0x719b8086,"Intel 82443MX Power management controller"}, 63#if 0 64 /* Not a good idea yet, this stops isab0 functioning */ 65 { 0x02001166,"ServerWorks OSB4 PCI to ISA Bridge"}, 66#endif 67 68 { 0x00000000, NULL } 69}; 70static int intsmb_probe(device_t); 71static int intsmb_attach(device_t); 72 73static int intsmb_intr(device_t dev); 74static int intsmb_slvintr(device_t dev); 75static void intsmb_alrintr(device_t dev); 76static int intsmb_callback(device_t dev, int index, caddr_t data); 77static int intsmb_quick(device_t dev, u_char slave, int how); 78static int intsmb_sendb(device_t dev, u_char slave, char byte); 79static int intsmb_recvb(device_t dev, u_char slave, char *byte); 80static int intsmb_writeb(device_t dev, u_char slave, char cmd, char byte); 81static int intsmb_writew(device_t dev, u_char slave, char cmd, short word); 82static int intsmb_readb(device_t dev, u_char slave, char cmd, char *byte); 83static int intsmb_readw(device_t dev, u_char slave, char cmd, short *word); 84static int intsmb_pcall(device_t dev, u_char slave, char cmd, short sdata, short *rdata); 85static int intsmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf); 86static int intsmb_bread(device_t dev, u_char slave, char cmd, u_char count, char *buf); 87static void intsmb_start(device_t dev,u_char cmd,int nointr); 88static int intsmb_stop(device_t dev); 89static int intsmb_stop_poll(device_t dev); 90static int intsmb_free(device_t dev); 91static int intpm_probe (device_t dev); 92static int intpm_attach (device_t dev); 93static devclass_t intsmb_devclass; 94 95static device_method_t intpm_methods[]={ 96 DEVMETHOD(device_probe,intsmb_probe), 97 DEVMETHOD(device_attach,intsmb_attach), 98 99 DEVMETHOD(bus_print_child, bus_generic_print_child), 100 101 DEVMETHOD(smbus_callback,intsmb_callback), 102 DEVMETHOD(smbus_quick,intsmb_quick), 103 DEVMETHOD(smbus_sendb,intsmb_sendb), 104 DEVMETHOD(smbus_recvb,intsmb_recvb), 105 DEVMETHOD(smbus_writeb,intsmb_writeb), 106 DEVMETHOD(smbus_writew,intsmb_writew), 107 DEVMETHOD(smbus_readb,intsmb_readb), 108 DEVMETHOD(smbus_readw,intsmb_readw), 109 DEVMETHOD(smbus_pcall,intsmb_pcall), 110 DEVMETHOD(smbus_bwrite,intsmb_bwrite), 111 DEVMETHOD(smbus_bread,intsmb_bread), 112 {0,0} 113}; 114 115struct intpm_pci_softc{ 116 bus_space_tag_t smbst; 117 bus_space_handle_t smbsh; 118 bus_space_tag_t pmst; 119 bus_space_handle_t pmsh; 120 device_t smbus; 121}; 122 123 124struct intsmb_softc{ 125 struct intpm_pci_softc *pci_sc; 126 bus_space_tag_t st; 127 bus_space_handle_t sh; 128 device_t smbus; 129 int isbusy; 130}; 131 132static driver_t intpm_driver = { 133 "intsmb", 134 intpm_methods, 135 sizeof(struct intsmb_softc), 136}; 137 138static devclass_t intpm_devclass; 139static device_method_t intpm_pci_methods[] = { 140 DEVMETHOD(device_probe,intpm_probe), 141 DEVMETHOD(device_attach,intpm_attach), 142 {0,0} 143}; 144static driver_t intpm_pci_driver = { 145 "intpm", 146 intpm_pci_methods, 147 sizeof(struct intpm_pci_softc) 148}; 149 150static int 151intsmb_probe(device_t dev) 152{ 153 struct intsmb_softc *sc =(struct intsmb_softc *) device_get_softc(dev); 154 sc->smbus=device_add_child(dev, "smbus", -1); 155 if (!sc->smbus) 156 return (EINVAL); /* XXX don't know what to return else */ 157 device_set_desc(dev,"Intel PIIX4 SMBUS Interface"); 158 159 return (BUS_PROBE_DEFAULT); /* XXX don't know what to return else */ 160} 161static int 162intsmb_attach(device_t dev) 163{ 164 struct intsmb_softc *sc = (struct intsmb_softc *)device_get_softc(dev); 165 sc->pci_sc=device_get_softc(device_get_parent(dev)); 166 sc->isbusy=0; 167 sc->sh=sc->pci_sc->smbsh; 168 sc->st=sc->pci_sc->smbst; 169 sc->pci_sc->smbus=dev; 170 device_probe_and_attach(sc->smbus); 171#ifdef ENABLE_ALART 172 /*Enable Arart*/ 173 bus_space_write_1(sc->st,sc->sh,PIIX4_SMBSLVCNT, 174 PIIX4_SMBSLVCNT_ALTEN); 175#endif 176 return (0); 177} 178 179static int 180intsmb_callback(device_t dev, int index, caddr_t data) 181{ 182 int error = 0; 183 intrmask_t s; 184 s=splnet(); 185 switch (index) { 186 case SMB_REQUEST_BUS: 187 break; 188 case SMB_RELEASE_BUS: 189 break; 190 default: 191 error = EINVAL; 192 } 193 splx(s); 194 return (error); 195} 196/*counterpart of smbtx_smb_free*/ 197static int 198intsmb_free(device_t dev){ 199 intrmask_t s; 200 struct intsmb_softc *sc = (struct intsmb_softc *)device_get_softc(dev); 201 if((bus_space_read_1(sc->st,sc->sh,PIIX4_SMBHSTSTS)& 202 PIIX4_SMBHSTSTAT_BUSY) 203#ifdef ENABLE_ALART 204 ||(bus_space_read_1(sc->st,sc->sh,PIIX4_SMBSLVSTS)& 205 PIIX4_SMBSLVSTS_BUSY) 206#endif 207 || sc->isbusy) 208 return EBUSY; 209 s=splhigh(); 210 sc->isbusy=1; 211 /*Disable Intrrupt in slave part*/ 212#ifndef ENABLE_ALART 213 bus_space_write_1(sc->st,sc->sh,PIIX4_SMBSLVCNT,0); 214#endif 215 /*Reset INTR Flag to prepare INTR*/ 216 bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTSTS, 217 (PIIX4_SMBHSTSTAT_INTR| 218 PIIX4_SMBHSTSTAT_ERR| 219 PIIX4_SMBHSTSTAT_BUSC| 220 PIIX4_SMBHSTSTAT_FAIL) 221 ); 222 splx(s); 223 return 0; 224} 225 226static int 227intsmb_intr(device_t dev) 228{ 229 struct intsmb_softc *sc = (struct intsmb_softc *)device_get_softc(dev); 230 int status; 231 status=bus_space_read_1(sc->st,sc->sh,PIIX4_SMBHSTSTS); 232 if(status&PIIX4_SMBHSTSTAT_BUSY){ 233 return 1; 234 235 } 236 if(status&(PIIX4_SMBHSTSTAT_INTR| 237 PIIX4_SMBHSTSTAT_ERR| 238 PIIX4_SMBHSTSTAT_BUSC| 239 PIIX4_SMBHSTSTAT_FAIL)){ 240 int tmp; 241 tmp=bus_space_read_1(sc->st,sc->sh,PIIX4_SMBHSTCNT); 242 bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTCNT, 243 tmp&~PIIX4_SMBHSTCNT_INTREN); 244 if(sc->isbusy){ 245 sc->isbusy=0; 246 wakeup(sc); 247 } 248 return 0; 249 } 250 return 1;/* Not Completed*/ 251} 252static int 253intsmb_slvintr(device_t dev) 254{ 255 struct intsmb_softc *sc = (struct intsmb_softc *)device_get_softc(dev); 256 int status,retval; 257 retval=1; 258 status=bus_space_read_1(sc->st,sc->sh,PIIX4_SMBSLVSTS); 259 if(status&PIIX4_SMBSLVSTS_BUSY) 260 return retval; 261 if(status&PIIX4_SMBSLVSTS_ALART){ 262 intsmb_alrintr(dev); 263 retval=0; 264 }else if(status&~(PIIX4_SMBSLVSTS_ALART|PIIX4_SMBSLVSTS_SDW2 265 |PIIX4_SMBSLVSTS_SDW1)){ 266 retval=0; 267 } 268 /*Reset Status Register*/ 269 bus_space_write_1(sc->st,sc->sh,PIIX4_SMBSLVSTS,PIIX4_SMBSLVSTS_ALART| 270 PIIX4_SMBSLVSTS_SDW2|PIIX4_SMBSLVSTS_SDW1| 271 PIIX4_SMBSLVSTS_SLV); 272 return retval; 273} 274 275static void intsmb_alrintr(device_t dev) 276{ 277 struct intsmb_softc *sc = (struct intsmb_softc *)device_get_softc(dev); 278 int slvcnt; 279#ifdef ENABLE_ALART 280 int error; 281#endif 282 283 /*stop generating INTR from ALART*/ 284 slvcnt=bus_space_read_1(sc->st,sc->sh,PIIX4_SMBSLVCNT); 285#ifdef ENABLE_ALART 286 bus_space_write_1(sc->st,sc->sh,PIIX4_SMBSLVCNT, 287 slvcnt&~PIIX4_SMBSLVCNT_ALTEN) ; 288#endif 289 DELAY(5); 290 /*ask bus who assert it and then ask it what's the matter. */ 291#ifdef ENABLE_ALART 292 error=intsmb_free(dev); 293 if(!error){ 294 bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTADD,SMBALTRESP 295 |LSB); 296 intsmb_start(dev,PIIX4_SMBHSTCNT_PROT_BYTE,1); 297 if(!(error=intsmb_stop_poll(dev))){ 298 u_int8_t addr; 299 addr=bus_space_read_1(sc->st,sc->sh, 300 PIIX4_SMBHSTDAT0); 301 printf("ALART_RESPONSE: 0x%x\n", addr); 302 } 303 }else{ 304 printf("ERROR\n"); 305 } 306 307 /*Re-enable INTR from ALART*/ 308 bus_space_write_1(sc->st,sc->sh,PIIX4_SMBSLVCNT, 309 slvcnt|PIIX4_SMBSLVCNT_ALTEN) ; 310 DELAY(5); 311#endif 312 313 return; 314} 315static void 316intsmb_start(device_t dev,unsigned char cmd,int nointr) 317{ 318 struct intsmb_softc *sc = (struct intsmb_softc *)device_get_softc(dev); 319 unsigned char tmp; 320 tmp=bus_space_read_1(sc->st,sc->sh,PIIX4_SMBHSTCNT); 321 tmp&= 0xe0; 322 tmp |= cmd; 323 tmp |=PIIX4_SMBHSTCNT_START; 324 /*While not in autoconfiguration Intrrupt Enabled*/ 325 if(!cold||!nointr) 326 tmp |=PIIX4_SMBHSTCNT_INTREN; 327 bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTCNT,tmp); 328} 329 330/*Polling Code. Polling is not encouraged 331 * because It is required to wait for the device get busy. 332 *(29063505.pdf from Intel) 333 * But during boot,intrrupt cannot be used. 334 * so use polling code while in autoconfiguration. 335 */ 336 337static int 338intsmb_stop_poll(device_t dev){ 339 int error,i; 340 struct intsmb_softc *sc = (struct intsmb_softc *)device_get_softc(dev); 341 342 /* 343 * In smbtx driver ,Simply waiting. 344 * This loops 100-200 times. 345 */ 346 for(i=0;i<0x7fff;i++){ 347 if((bus_space_read_1(sc->st,sc->sh,PIIX4_SMBHSTSTS) 348 &PIIX4_SMBHSTSTAT_BUSY)){ 349 break; 350 } 351 } 352 for(i=0;i<0x7fff;i++){ 353 int status; 354 status=bus_space_read_1(sc->st,sc->sh,PIIX4_SMBHSTSTS); 355 if(!(status&PIIX4_SMBHSTSTAT_BUSY)){ 356 sc->isbusy=0; 357 error=(status&PIIX4_SMBHSTSTAT_ERR)?EIO : 358 (status&PIIX4_SMBHSTSTAT_BUSC)?EBUSY: 359 (status&PIIX4_SMBHSTSTAT_FAIL)?EIO:0; 360 if(error==0&&!(status&PIIX4_SMBHSTSTAT_INTR)){ 361 printf("unknown cause why?"); 362 } 363 return error; 364 } 365 } 366 { 367 int tmp; 368 sc->isbusy=0; 369 tmp=bus_space_read_1(sc->st,sc->sh,PIIX4_SMBHSTCNT); 370 bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTCNT, 371 tmp&~PIIX4_SMBHSTCNT_INTREN); 372 } 373 return EIO; 374} 375/* 376 *wait for completion and return result. 377 */ 378static int 379intsmb_stop(device_t dev){ 380 int error; 381 intrmask_t s; 382 struct intsmb_softc *sc = (struct intsmb_softc *)device_get_softc(dev); 383 if(cold){ 384 /*So that it can use device during probing device on SMBus.*/ 385 error=intsmb_stop_poll(dev); 386 return error; 387 }else{ 388 if(!tsleep(sc,(PWAIT)|PCATCH,"SMBWAI",hz/8)){ 389 int status; 390 status=bus_space_read_1(sc->st,sc->sh,PIIX4_SMBHSTSTS); 391 if(!(status&PIIX4_SMBHSTSTAT_BUSY)){ 392 error=(status&PIIX4_SMBHSTSTAT_ERR)?EIO : 393 (status&PIIX4_SMBHSTSTAT_BUSC)?EBUSY: 394 (status&PIIX4_SMBHSTSTAT_FAIL)?EIO:0; 395 if(error==0&&!(status&PIIX4_SMBHSTSTAT_INTR)){ 396 printf("intsmb%d:unknown cause why?\n", 397 device_get_unit(dev)); 398 } 399#ifdef ENABLE_ALART 400 bus_space_write_1(sc->st,sc->sh, 401 PIIX4_SMBSLVCNT,PIIX4_SMBSLVCNT_ALTEN); 402#endif 403 return error; 404 } 405 } 406 } 407 /*Timeout Procedure*/ 408 s=splhigh(); 409 sc->isbusy=0; 410 /*Re-enable supressed intrrupt from slave part*/ 411 bus_space_write_1(sc->st,sc->sh, 412 PIIX4_SMBSLVCNT,PIIX4_SMBSLVCNT_ALTEN); 413 splx(s); 414 return EIO; 415} 416 417static int 418intsmb_quick(device_t dev, u_char slave, int how) 419{ 420 int error=0; 421 u_char data; 422 struct intsmb_softc *sc = (struct intsmb_softc *)device_get_softc(dev); 423 data=slave; 424 /*Quick command is part of Address, I think*/ 425 switch(how){ 426 case SMB_QWRITE: 427 data&=~LSB; 428 break; 429 case SMB_QREAD: 430 data|=LSB; 431 break; 432 default: 433 error=EINVAL; 434 } 435 if(!error){ 436 error=intsmb_free(dev); 437 if(!error){ 438 bus_space_write_1(sc->st,sc->sh, 439 PIIX4_SMBHSTADD,data); 440 intsmb_start(dev,PIIX4_SMBHSTCNT_PROT_QUICK,0); 441 error=intsmb_stop(dev); 442 } 443 } 444 445 return (error); 446} 447 448static int 449intsmb_sendb(device_t dev, u_char slave, char byte) 450{ 451 int error; 452 struct intsmb_softc *sc = (struct intsmb_softc *)device_get_softc(dev); 453 error=intsmb_free(dev); 454 if(!error){ 455 bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTADD,slave&~LSB); 456 bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTCMD,byte); 457 intsmb_start(dev,PIIX4_SMBHSTCNT_PROT_BYTE,0); 458 error=intsmb_stop(dev); 459 } 460 return (error); 461} 462static int 463intsmb_recvb(device_t dev, u_char slave, char *byte) 464{ 465 int error; 466 struct intsmb_softc *sc = (struct intsmb_softc *)device_get_softc(dev); 467 error=intsmb_free(dev); 468 if(!error){ 469 bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTADD,slave 470 |LSB); 471 intsmb_start(dev,PIIX4_SMBHSTCNT_PROT_BYTE,0); 472 if(!(error=intsmb_stop(dev))){ 473#ifdef RECV_IS_IN_CMD 474 /*Linux SMBus stuff also troubles 475 Because Intel's datasheet will not make clear. 476 */ 477 *byte=bus_space_read_1(sc->st,sc->sh, 478 PIIX4_SMBHSTCMD); 479#else 480 *byte=bus_space_read_1(sc->st,sc->sh, 481 PIIX4_SMBHSTDAT0); 482#endif 483 } 484 } 485 return (error); 486} 487static int 488intsmb_writeb(device_t dev, u_char slave, char cmd, char byte) 489{ 490 int error; 491 struct intsmb_softc *sc = (struct intsmb_softc *)device_get_softc(dev); 492 error=intsmb_free(dev); 493 if(!error){ 494 bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTADD,slave&~LSB); 495 bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTCMD,cmd); 496 bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTDAT0,byte); 497 intsmb_start(dev,PIIX4_SMBHSTCNT_PROT_BDATA,0); 498 error=intsmb_stop(dev); 499 } 500 return (error); 501} 502static int 503intsmb_writew(device_t dev, u_char slave, char cmd, short word) 504{ 505 int error; 506 struct intsmb_softc *sc = (struct intsmb_softc *)device_get_softc(dev); 507 error=intsmb_free(dev); 508 if(!error){ 509 bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTADD,slave&~LSB); 510 bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTCMD,cmd); 511 bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTDAT0, 512 word&0xff); 513 bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTDAT1, 514 (word>>8)&0xff); 515 intsmb_start(dev,PIIX4_SMBHSTCNT_PROT_WDATA,0); 516 error=intsmb_stop(dev); 517 } 518 return (error); 519} 520 521static int 522intsmb_readb(device_t dev, u_char slave, char cmd, char *byte) 523{ 524 int error; 525 struct intsmb_softc *sc = (struct intsmb_softc *)device_get_softc(dev); 526 error=intsmb_free(dev); 527 if(!error){ 528 bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTADD,slave|LSB); 529 bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTCMD,cmd); 530 intsmb_start(dev,PIIX4_SMBHSTCNT_PROT_BDATA,0); 531 if(!(error=intsmb_stop(dev))){ 532 *byte=bus_space_read_1(sc->st,sc->sh, 533 PIIX4_SMBHSTDAT0); 534 } 535 } 536 return (error); 537} 538static int 539intsmb_readw(device_t dev, u_char slave, char cmd, short *word) 540{ 541 int error; 542 struct intsmb_softc *sc = (struct intsmb_softc *)device_get_softc(dev); 543 error=intsmb_free(dev); 544 if(!error){ 545 bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTADD,slave|LSB); 546 bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTCMD,cmd); 547 intsmb_start(dev,PIIX4_SMBHSTCNT_PROT_WDATA,0); 548 if(!(error=intsmb_stop(dev))){ 549 *word=bus_space_read_1(sc->st,sc->sh,PIIX4_SMBHSTDAT0)&0xff; 550 *word|=(bus_space_read_1(sc->st,sc->sh,PIIX4_SMBHSTDAT1)&0xff)<<8; 551 } 552 } 553 return (error); 554} 555/* 556 * Data sheet claims that it implements all function, but also claims 557 * that it implements 7 function and not mention PCALL. So I don't know 558 * whether it will work. 559 */ 560static int 561intsmb_pcall(device_t dev, u_char slave, char cmd, short sdata, short *rdata) 562{ 563#ifdef PROCCALL_TEST 564 int error; 565 struct intsmb_softc *sc = (struct intsmb_softc *)device_get_softc(dev); 566 error=intsmb_free(dev); 567 if(!error){ 568 bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTADD,slave&~LSB); 569 bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTCMD,cmd); 570 bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTDAT0,sdata&0xff); 571 bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTDAT1,(sdata&0xff)>>8); 572 intsmb_start(dev,PIIX4_SMBHSTCNT_PROT_WDATA,0); 573 } 574 if(!(error=intsmb_stop(dev))){ 575 *rdata=bus_space_read_1(sc->st,sc->sh,PIIX4_SMBHSTDAT0)&0xff; 576 *rdata|=(bus_space_read_1(sc->st,sc->sh,PIIX4_SMBHSTDAT1)&0xff)<<8; 577 } 578 return error; 579#else 580 return 0; 581#endif 582} 583static int 584intsmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf) 585{ 586 int error,i; 587 struct intsmb_softc *sc = (struct intsmb_softc *)device_get_softc(dev); 588 error=intsmb_free(dev); 589 if(count>SMBBLOCKTRANS_MAX||count==0) 590 error=EINVAL; 591 if(!error){ 592 /*Reset internal array index*/ 593 bus_space_read_1(sc->st,sc->sh,PIIX4_SMBHSTCNT); 594 595 bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTADD,slave&~LSB); 596 bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTCMD,cmd); 597 for(i=0;i<count;i++){ 598 bus_space_write_1(sc->st,sc->sh,PIIX4_SMBBLKDAT,buf[i]); 599 } 600 bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTDAT0,count); 601 intsmb_start(dev,PIIX4_SMBHSTCNT_PROT_BLOCK,0); 602 error=intsmb_stop(dev); 603 } 604 return (error); 605} 606 607static int 608intsmb_bread(device_t dev, u_char slave, char cmd, u_char count, char *buf) 609{ 610 int error,i; 611 struct intsmb_softc *sc = (struct intsmb_softc *)device_get_softc(dev); 612 error=intsmb_free(dev); 613 if(count>SMBBLOCKTRANS_MAX||count==0) 614 error=EINVAL; 615 if(!error){ 616 /*Reset internal array index*/ 617 bus_space_read_1(sc->st,sc->sh,PIIX4_SMBHSTCNT); 618 619 bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTADD,slave|LSB); 620 bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTCMD,cmd); 621 bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTDAT0,count); 622 intsmb_start(dev,PIIX4_SMBHSTCNT_PROT_BLOCK,0); 623 error=intsmb_stop(dev); 624 if(!error){ 625 bzero(buf,count);/*Is it needed?*/ 626 count= bus_space_read_1(sc->st,sc->sh, 627 PIIX4_SMBHSTDAT0); 628 if(count!=0&&count<=SMBBLOCKTRANS_MAX){ 629 for(i=0;i<count;i++){ 630 buf[i]=bus_space_read_1(sc->st, 631 sc->sh, 632 PIIX4_SMBBLKDAT); 633 } 634 } 635 else{ 636 error=EIO; 637 } 638 } 639 } 640 return (error); 641} 642 643DRIVER_MODULE(intsmb, intpm , intpm_driver, intsmb_devclass, 0, 0); 644 645 646static void intpm_intr(void *arg); 647static int 648intpm_attach(device_t dev) 649{ 650 int value; 651 int unit=device_get_unit(dev); 652 void *ih; 653 int error; 654 char * str; 655 { 656 struct intpm_pci_softc *sciic; 657 device_t smbinterface; 658 int rid; 659 struct resource *res; 660 661 sciic=device_get_softc(dev); 662 if(sciic==NULL){ 663 return ENOMEM; 664 } 665 666 rid=PCI_BASE_ADDR_SMB; 667 res=bus_alloc_resource_any(dev,SYS_RES_IOPORT,&rid,RF_ACTIVE); 668 if(res==NULL){ 669 device_printf(dev,"Could not allocate Bus space\n"); 670 return ENXIO; 671 } 672 sciic->smbst=rman_get_bustag(res); 673 sciic->smbsh=rman_get_bushandle(res); 674 675#ifdef __i386__ 676 device_printf(dev,"%s %lx\n", 677 (sciic->smbst==I386_BUS_SPACE_IO)? 678 "I/O mapped":"Memory", 679 rman_get_start(res)); 680#endif 681 682 683#ifndef NO_CHANGE_PCICONF 684 pci_write_config(dev,PCIR_INTLINE,0x9,1); 685 pci_write_config(dev,PCI_HST_CFG_SMB, 686 PCI_INTR_SMB_IRQ9|PCI_INTR_SMB_ENABLE,1); 687#endif 688 value=pci_read_config(dev,PCI_HST_CFG_SMB,1); 689 switch(value&0xe){ 690 case PCI_INTR_SMB_SMI: 691 str="SMI"; 692 break; 693 case PCI_INTR_SMB_IRQ9: 694 str="IRQ 9"; 695 break; 696 default: 697 str="BOGUS"; 698 } 699 device_printf(dev,"intr %s %s ",str,((value&1)? "enabled":"disabled")); 700 value=pci_read_config(dev,PCI_REVID_SMB,1); 701 printf("revision %d\n",value); 702 /* 703 * Install intr HANDLER here 704 */ 705 rid=0; 706 res=bus_alloc_resource(dev,SYS_RES_IRQ,&rid,9,9,1,RF_SHAREABLE|RF_ACTIVE); 707 if(res==NULL){ 708 device_printf(dev,"could not allocate irq"); 709 return ENOMEM; 710 } 711 error=bus_setup_intr(dev,res,INTR_TYPE_MISC, (driver_intr_t *) intpm_intr,sciic,&ih); 712 if(error){ 713 device_printf(dev,"Failed to map intr\n"); 714 return error; 715 } 716 smbinterface=device_add_child(dev,"intsmb",unit); 717 if(!smbinterface){ 718 printf("intsmb%d:could not add SMBus device\n",unit); 719 } 720 device_probe_and_attach(smbinterface); 721 } 722 723 value=pci_read_config(dev,PCI_BASE_ADDR_PM,4); 724 printf("intpm%d: PM %s %x \n",unit,(value&1)?"I/O mapped":"Memory",value&0xfffe); 725 return 0; 726} 727static int 728intpm_probe(device_t dev) 729{ 730 struct _pcsid *ep =pci_ids; 731 u_int32_t device_id=pci_get_devid(dev); 732 733 while (ep->type && ep->type != device_id) 734 ++ep; 735 if(ep->desc!=NULL){ 736 device_set_desc(dev,ep->desc); 737 bus_set_resource(dev,SYS_RES_IRQ,0,9,1); /* XXX setup intr resource */ 738 return (BUS_PROBE_DEFAULT); 739 }else{ 740 return ENXIO; 741 } 742} 743DRIVER_MODULE(intpm, pci , intpm_pci_driver, intpm_devclass, 0, 0); 744MODULE_DEPEND(intpm, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER); 745MODULE_VERSION(intpm, 1); 746 747static void intpm_intr(void *arg) 748{ 749 struct intpm_pci_softc *sc; 750 sc=(struct intpm_pci_softc *)arg; 751 intsmb_intr(sc->smbus); 752 intsmb_slvintr(sc->smbus); 753 754} 755