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