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