alpm.c revision 71134
1/*- 2 * Copyright (c) 1998, 1999, 2001 Nicolas Souchu 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: head/sys/pci/alpm.c 71134 2001-01-17 00:38:06Z peter $ 27 * 28 */ 29 30/* 31 * Power Management support for the Acer M15x3 chipsets 32 */ 33#include <sys/param.h> 34#include <sys/kernel.h> 35#include <sys/systm.h> 36#include <sys/module.h> 37#include <sys/bus.h> 38#include <sys/uio.h> 39 40 41#include <machine/bus_pio.h> 42#include <machine/bus_memio.h> 43#include <machine/bus.h> 44#include <machine/resource.h> 45#include <sys/rman.h> 46 47#include <pci/pcivar.h> 48#include <pci/pcireg.h> 49 50#include <dev/iicbus/iiconf.h> 51#include <dev/smbus/smbconf.h> 52#include "smbus_if.h" 53 54#define ALPM_DEBUG(x) if (alpm_debug) (x) 55 56#ifdef DEBUG 57static int alpm_debug = 1; 58#else 59static int alpm_debug = 0; 60#endif 61 62#define ACER_M1543_PMU_ID 0x710110b9 63 64/* Uncomment this line to force another I/O base address for SMB */ 65/* #define ALPM_SMBIO_BASE_ADDR 0x3a80 */ 66 67/* I/O registers offsets - the base address is programmed via the 68 * SMBBA PCI configuration register 69 */ 70#define SMBSTS 0x0 /* SMBus host/slave status register */ 71#define SMBCMD 0x1 /* SMBus host/slave command register */ 72#define SMBSTART 0x2 /* start to generate programmed cycle */ 73#define SMBHADDR 0x3 /* host address register */ 74#define SMBHDATA 0x4 /* data A register for host controller */ 75#define SMBHDATB 0x5 /* data B register for host controller */ 76#define SMBHBLOCK 0x6 /* block register for host controller */ 77#define SMBHCMD 0x7 /* command register for host controller */ 78 79/* SMBSTS masks */ 80#define TERMINATE 0x80 81#define BUS_COLLI 0x40 82#define DEVICE_ERR 0x20 83#define SMI_I_STS 0x10 84#define HST_BSY 0x08 85#define IDL_STS 0x04 86#define HSTSLV_STS 0x02 87#define HSTSLV_BSY 0x01 88 89/* SMBCMD masks */ 90#define SMB_BLK_CLR 0x80 91#define T_OUT_CMD 0x08 92#define ABORT_HOST 0x04 93 94/* SMBus commands */ 95#define SMBQUICK 0x00 96#define SMBSRBYTE 0x10 /* send/receive byte */ 97#define SMBWRBYTE 0x20 /* write/read byte */ 98#define SMBWRWORD 0x30 /* write/read word */ 99#define SMBWRBLOCK 0x40 /* write/read block */ 100 101/* PCI configuration registers and masks 102 */ 103#define COM 0x4 104#define COM_ENABLE_IO 0x1 105 106#define SMBBA 0x14 107 108#define ATPC 0x5b 109#define ATPC_SMBCTRL 0x04 /* XX linux has this as 0x6 */ 110 111#define SMBHSI 0xe0 112#define SMBHSI_SLAVE 0x2 113#define SMBHSI_HOST 0x1 114 115#define SMBHCBC 0xe2 116#define SMBHCBC_CLOCK 0x70 117 118#define SMBCLOCK_149K 0x0 119#define SMBCLOCK_74K 0x20 120#define SMBCLOCK_37K 0x40 121#define SMBCLOCK_223K 0x80 122#define SMBCLOCK_111K 0xa0 123#define SMBCLOCK_55K 0xc0 124 125struct alpm_data { 126 int base; 127 bus_space_tag_t smbst; 128 bus_space_handle_t smbsh; 129}; 130 131struct alsmb_softc { 132 int base; 133 device_t smbus; 134 struct alpm_data *alpm; 135}; 136 137#define ALPM_SMBINB(alsmb,register) \ 138 (bus_space_read_1(alsmb->alpm->smbst, alsmb->alpm->smbsh, register)) 139#define ALPM_SMBOUTB(alsmb,register,value) \ 140 (bus_space_write_1(alsmb->alpm->smbst, alsmb->alpm->smbsh, register, value)) 141 142static int alsmb_probe(device_t); 143static int alsmb_attach(device_t); 144static int alsmb_smb_callback(device_t, int, caddr_t *); 145static int alsmb_smb_quick(device_t dev, u_char slave, int how); 146static int alsmb_smb_sendb(device_t dev, u_char slave, char byte); 147static int alsmb_smb_recvb(device_t dev, u_char slave, char *byte); 148static int alsmb_smb_writeb(device_t dev, u_char slave, char cmd, char byte); 149static int alsmb_smb_readb(device_t dev, u_char slave, char cmd, char *byte); 150static int alsmb_smb_writew(device_t dev, u_char slave, char cmd, short word); 151static int alsmb_smb_readw(device_t dev, u_char slave, char cmd, short *word); 152static int alsmb_smb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf); 153static int alsmb_smb_bread(device_t dev, u_char slave, char cmd, u_char count, char *byte); 154 155static devclass_t alsmb_devclass; 156 157static device_method_t alsmb_methods[] = { 158 /* device interface */ 159 DEVMETHOD(device_probe, alsmb_probe), 160 DEVMETHOD(device_attach, alsmb_attach), 161 162 /* bus interface */ 163 DEVMETHOD(bus_print_child, bus_generic_print_child), 164 165 /* smbus interface */ 166 DEVMETHOD(smbus_callback, alsmb_smb_callback), 167 DEVMETHOD(smbus_quick, alsmb_smb_quick), 168 DEVMETHOD(smbus_sendb, alsmb_smb_sendb), 169 DEVMETHOD(smbus_recvb, alsmb_smb_recvb), 170 DEVMETHOD(smbus_writeb, alsmb_smb_writeb), 171 DEVMETHOD(smbus_readb, alsmb_smb_readb), 172 DEVMETHOD(smbus_writew, alsmb_smb_writew), 173 DEVMETHOD(smbus_readw, alsmb_smb_readw), 174 DEVMETHOD(smbus_bwrite, alsmb_smb_bwrite), 175 DEVMETHOD(smbus_bread, alsmb_smb_bread), 176 177 { 0, 0 } 178}; 179 180static driver_t alsmb_driver = { 181 "alsmb", 182 alsmb_methods, 183 sizeof(struct alsmb_softc), 184}; 185 186static int alpm_pci_probe(device_t dev); 187static int alpm_pci_attach(device_t dev); 188 189static devclass_t alpm_devclass; 190 191static device_method_t alpm_pci_methods[] = { 192 /* device interface */ 193 DEVMETHOD(device_probe, alpm_pci_probe), 194 DEVMETHOD(device_attach, alpm_pci_attach), 195 196 { 0, 0 } 197}; 198 199static driver_t alpm_pci_driver = { 200 "alpm", 201 alpm_pci_methods, 202 sizeof(struct alpm_data) 203}; 204 205 206static int 207alpm_pci_probe(device_t dev) 208{ 209 if (pci_get_devid(dev) == ACER_M1543_PMU_ID) { 210 device_set_desc(dev, 211 "AcerLabs M15x3 Power Management Unit"); 212 return 0; 213 } else { 214 return ENXIO; 215 } 216} 217 218static int 219alpm_pci_attach(device_t dev) 220{ 221 int rid, unit; 222 u_int32_t l; 223 struct alpm_data *alpm; 224 struct resource *res; 225 device_t smbinterface; 226 227 alpm = device_get_softc(dev); 228 unit = device_get_unit(dev); 229 230 /* Unlock SMBIO base register access */ 231 l = pci_read_config(dev, ATPC, 1); 232 pci_write_config(dev, ATPC, l & ~ATPC_SMBCTRL, 1); 233 234 /* 235 * XX linux sets clock to 74k, should we? 236 l = pci_read_config(dev, SMBHCBC, 1); 237 l &= 0x1f; 238 l |= SMBCLOCK_74K; 239 pci_write_config(dev, SMBHCBC, l, 1); 240 */ 241 242 if (bootverbose) { 243 l = pci_read_config(dev, SMBHSI, 1); 244 printf("alsmb%d: %s/%s", unit, 245 (l & SMBHSI_HOST) ? "host":"nohost", 246 (l & SMBHSI_SLAVE) ? "slave":"noslave"); 247 248 l = pci_read_config(dev, SMBHCBC, 1); 249 switch (l & SMBHCBC_CLOCK) { 250 case SMBCLOCK_149K: 251 printf(" 149K"); 252 break; 253 case SMBCLOCK_74K: 254 printf(" 74K"); 255 break; 256 case SMBCLOCK_37K: 257 printf(" 37K"); 258 break; 259 case SMBCLOCK_223K: 260 printf(" 223K"); 261 break; 262 case SMBCLOCK_111K: 263 printf(" 111K"); 264 break; 265 case SMBCLOCK_55K: 266 printf(" 55K"); 267 break; 268 } 269 } 270 271#ifdef ALPM_SMBIO_BASE_ADDR 272 /* XX will this even work anymore? */ 273 /* disable I/O */ 274 l = pci_read_config(dev, COM, 2); 275 pci_write_config(dev, COM, l & ~COM_ENABLE_IO, 2); 276 277 /* set the I/O base address */ 278 pci_write_config(dev, SMBBA, ALPM_SMBIO_BASE_ADDR | 0x1, 4); 279 280 /* enable I/O */ 281 pci_write_config(dev, COM, l | COM_ENABLE_IO, 2); 282 283#endif 284 rid = SMBBA; 285 res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 286 0,~0,1,RF_ACTIVE); 287 if (res == NULL) { 288 device_printf(dev,"Could not allocate Bus space\n"); 289 return ENXIO; 290 } 291 alpm->smbst = rman_get_bustag(res); 292 alpm->smbsh = rman_get_bushandle(res); 293 294 if (bootverbose) 295 printf(" at 0x%x\n", alpm->smbsh); 296 297 smbinterface = device_add_child(dev, "alsmb", unit); 298 if (!smbinterface) 299 device_printf(dev, "could not add SMBus device\n"); 300 else 301 device_probe_and_attach(smbinterface); 302 return 0; 303} 304 305/* 306 * Not a real probe, we know the device exists since the device has 307 * been added after the successfull pci probe. 308 */ 309static int 310alsmb_probe(device_t dev) 311{ 312 struct alsmb_softc *sc = (struct alsmb_softc *)device_get_softc(dev); 313 314 /* allocate a new smbus device */ 315 sc->smbus = smbus_alloc_bus(dev); 316 if (!sc->smbus) 317 return (EINVAL); 318 device_set_desc(dev, "Aladdin IV/V/Pro2 SMBus controller"); 319 320 return (0); 321} 322 323static int 324alsmb_attach(device_t dev) 325{ 326 struct alsmb_softc *sc = (struct alsmb_softc *)device_get_softc(dev); 327 328 sc->alpm = device_get_softc(device_get_parent(dev)); 329 330 /* probe and attach the smbus */ 331 device_probe_and_attach(sc->smbus); 332 333 return (0); 334} 335 336static int 337alsmb_smb_callback(device_t dev, int index, caddr_t *data) 338{ 339 int error = 0; 340 341 switch (index) { 342 case SMB_REQUEST_BUS: 343 case SMB_RELEASE_BUS: 344 /* ok, bus allocation accepted */ 345 break; 346 default: 347 error = EINVAL; 348 } 349 350 return (error); 351} 352 353static int 354alsmb_clear(struct alsmb_softc *sc) 355{ 356 ALPM_SMBOUTB(sc, SMBSTS, 0xff); 357 DELAY(10); 358 359 return (0); 360} 361 362#if 0 363static int 364alsmb_abort(struct alsmb_softc *sc) 365{ 366 ALPM_SMBOUTB(sc, SMBCMD, T_OUT_CMD | ABORT_HOST); 367 368 return (0); 369} 370#endif 371 372static int 373alsmb_idle(struct alsmb_softc *sc) 374{ 375 u_char sts; 376 377 sts = ALPM_SMBINB(sc, SMBSTS); 378 379 ALPM_DEBUG(printf("alpm: idle? STS=0x%x\n", sts)); 380 381 return (sts & IDL_STS); 382} 383 384/* 385 * Poll the SMBus controller 386 */ 387static int 388alsmb_wait(struct alsmb_softc *sc) 389{ 390 int count = 10000; 391 u_char sts = 0; 392 int error; 393 394 /* wait for command to complete and SMBus controller is idle */ 395 while(count--) { 396 DELAY(10); 397 sts = ALPM_SMBINB(sc, SMBSTS); 398 if (sts & SMI_I_STS) 399 break; 400 } 401 402 ALPM_DEBUG(printf("alpm: STS=0x%x\n", sts)); 403 404 error = SMB_ENOERR; 405 406 if (!count) 407 error |= SMB_ETIMEOUT; 408 409 if (sts & TERMINATE) 410 error |= SMB_EABORT; 411 412 if (sts & BUS_COLLI) 413 error |= SMB_ENOACK; 414 415 if (sts & DEVICE_ERR) 416 error |= SMB_EBUSERR; 417 418 if (error != SMB_ENOERR) 419 alsmb_clear(sc); 420 421 return (error); 422} 423 424static int 425alsmb_smb_quick(device_t dev, u_char slave, int how) 426{ 427 struct alsmb_softc *sc = (struct alsmb_softc *)device_get_softc(dev); 428 int error; 429 430 alsmb_clear(sc); 431 if (!alsmb_idle(sc)) 432 return (EBUSY); 433 434 switch (how) { 435 case SMB_QWRITE: 436 ALPM_DEBUG(printf("alpm: QWRITE to 0x%x", slave)); 437 ALPM_SMBOUTB(sc, SMBHADDR, slave & ~LSB); 438 break; 439 case SMB_QREAD: 440 ALPM_DEBUG(printf("alpm: QREAD to 0x%x", slave)); 441 ALPM_SMBOUTB(sc, SMBHADDR, slave | LSB); 442 break; 443 default: 444 panic("%s: unknown QUICK command (%x)!", __FUNCTION__, 445 how); 446 } 447 ALPM_SMBOUTB(sc, SMBCMD, SMBQUICK); 448 ALPM_SMBOUTB(sc, SMBSTART, 0xff); 449 450 error = alsmb_wait(sc); 451 452 ALPM_DEBUG(printf(", error=0x%x\n", error)); 453 454 return (error); 455} 456 457static int 458alsmb_smb_sendb(device_t dev, u_char slave, char byte) 459{ 460 struct alsmb_softc *sc = (struct alsmb_softc *)device_get_softc(dev); 461 int error; 462 463 alsmb_clear(sc); 464 if (!alsmb_idle(sc)) 465 return (SMB_EBUSY); 466 467 ALPM_SMBOUTB(sc, SMBHADDR, slave & ~LSB); 468 ALPM_SMBOUTB(sc, SMBCMD, SMBSRBYTE); 469 ALPM_SMBOUTB(sc, SMBHDATA, byte); 470 ALPM_SMBOUTB(sc, SMBSTART, 0xff); 471 472 error = alsmb_wait(sc); 473 474 ALPM_DEBUG(printf("alpm: SENDB to 0x%x, byte=0x%x, error=0x%x\n", slave, byte, error)); 475 476 return (error); 477} 478 479static int 480alsmb_smb_recvb(device_t dev, u_char slave, char *byte) 481{ 482 struct alsmb_softc *sc = (struct alsmb_softc *)device_get_softc(dev); 483 int error; 484 485 alsmb_clear(sc); 486 if (!alsmb_idle(sc)) 487 return (SMB_EBUSY); 488 489 ALPM_SMBOUTB(sc, SMBHADDR, slave | LSB); 490 ALPM_SMBOUTB(sc, SMBCMD, SMBSRBYTE); 491 ALPM_SMBOUTB(sc, SMBSTART, 0xff); 492 493 if ((error = alsmb_wait(sc)) == SMB_ENOERR) 494 *byte = ALPM_SMBINB(sc, SMBHDATA); 495 496 ALPM_DEBUG(printf("alpm: RECVB from 0x%x, byte=0x%x, error=0x%x\n", slave, *byte, error)); 497 498 return (error); 499} 500 501static int 502alsmb_smb_writeb(device_t dev, u_char slave, char cmd, char byte) 503{ 504 struct alsmb_softc *sc = (struct alsmb_softc *)device_get_softc(dev); 505 int error; 506 507 alsmb_clear(sc); 508 if (!alsmb_idle(sc)) 509 return (SMB_EBUSY); 510 511 ALPM_SMBOUTB(sc, SMBHADDR, slave & ~LSB); 512 ALPM_SMBOUTB(sc, SMBCMD, SMBWRBYTE); 513 ALPM_SMBOUTB(sc, SMBHDATA, byte); 514 ALPM_SMBOUTB(sc, SMBHCMD, cmd); 515 ALPM_SMBOUTB(sc, SMBSTART, 0xff); 516 517 error = alsmb_wait(sc); 518 519 ALPM_DEBUG(printf("alpm: WRITEB to 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, byte, error)); 520 521 return (error); 522} 523 524static int 525alsmb_smb_readb(device_t dev, u_char slave, char cmd, char *byte) 526{ 527 struct alsmb_softc *sc = (struct alsmb_softc *)device_get_softc(dev); 528 int error; 529 530 alsmb_clear(sc); 531 if (!alsmb_idle(sc)) 532 return (SMB_EBUSY); 533 534 ALPM_SMBOUTB(sc, SMBHADDR, slave | LSB); 535 ALPM_SMBOUTB(sc, SMBCMD, SMBWRBYTE); 536 ALPM_SMBOUTB(sc, SMBHCMD, cmd); 537 ALPM_SMBOUTB(sc, SMBSTART, 0xff); 538 539 if ((error = alsmb_wait(sc)) == SMB_ENOERR) 540 *byte = ALPM_SMBINB(sc, SMBHDATA); 541 542 ALPM_DEBUG(printf("alpm: READB from 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, *byte, error)); 543 544 return (error); 545} 546 547static int 548alsmb_smb_writew(device_t dev, u_char slave, char cmd, short word) 549{ 550 struct alsmb_softc *sc = (struct alsmb_softc *)device_get_softc(dev); 551 int error; 552 553 alsmb_clear(sc); 554 if (!alsmb_idle(sc)) 555 return (SMB_EBUSY); 556 557 ALPM_SMBOUTB(sc, SMBHADDR, slave & ~LSB); 558 ALPM_SMBOUTB(sc, SMBCMD, SMBWRWORD); 559 ALPM_SMBOUTB(sc, SMBHDATA, word & 0x00ff); 560 ALPM_SMBOUTB(sc, SMBHDATB, (word & 0xff00) >> 8); 561 ALPM_SMBOUTB(sc, SMBHCMD, cmd); 562 ALPM_SMBOUTB(sc, SMBSTART, 0xff); 563 564 error = alsmb_wait(sc); 565 566 ALPM_DEBUG(printf("alpm: WRITEW to 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, word, error)); 567 568 return (error); 569} 570 571static int 572alsmb_smb_readw(device_t dev, u_char slave, char cmd, short *word) 573{ 574 struct alsmb_softc *sc = (struct alsmb_softc *)device_get_softc(dev); 575 int error; 576 u_char high, low; 577 578 alsmb_clear(sc); 579 if (!alsmb_idle(sc)) 580 return (SMB_EBUSY); 581 582 ALPM_SMBOUTB(sc, SMBHADDR, slave | LSB); 583 ALPM_SMBOUTB(sc, SMBCMD, SMBWRWORD); 584 ALPM_SMBOUTB(sc, SMBHCMD, cmd); 585 ALPM_SMBOUTB(sc, SMBSTART, 0xff); 586 587 if ((error = alsmb_wait(sc)) == SMB_ENOERR) { 588 low = ALPM_SMBINB(sc, SMBHDATA); 589 high = ALPM_SMBINB(sc, SMBHDATB); 590 591 *word = ((high & 0xff) << 8) | (low & 0xff); 592 } 593 594 ALPM_DEBUG(printf("alpm: READW from 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, *word, error)); 595 596 return (error); 597} 598 599static int 600alsmb_smb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf) 601{ 602 struct alsmb_softc *sc = (struct alsmb_softc *)device_get_softc(dev); 603 u_char remain, len, i; 604 int error = SMB_ENOERR; 605 606 alsmb_clear(sc); 607 if(!alsmb_idle(sc)) 608 return (SMB_EBUSY); 609 610 remain = count; 611 while (remain) { 612 len = min(remain, 32); 613 614 ALPM_SMBOUTB(sc, SMBHADDR, slave & ~LSB); 615 616 /* set the cmd and reset the 617 * 32-byte long internal buffer */ 618 ALPM_SMBOUTB(sc, SMBCMD, SMBWRBLOCK | SMB_BLK_CLR); 619 620 ALPM_SMBOUTB(sc, SMBHDATA, len); 621 622 /* fill the 32-byte internal buffer */ 623 for (i=0; i<len; i++) { 624 ALPM_SMBOUTB(sc, SMBHBLOCK, buf[count-remain+i]); 625 DELAY(2); 626 } 627 ALPM_SMBOUTB(sc, SMBHCMD, cmd); 628 ALPM_SMBOUTB(sc, SMBSTART, 0xff); 629 630 if ((error = alsmb_wait(sc)) != SMB_ENOERR) 631 goto error; 632 633 remain -= len; 634 } 635 636error: 637 ALPM_DEBUG(printf("alpm: WRITEBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error)); 638 639 return (error); 640} 641 642static int 643alsmb_smb_bread(device_t dev, u_char slave, char cmd, u_char count, char *buf) 644{ 645 struct alsmb_softc *sc = (struct alsmb_softc *)device_get_softc(dev); 646 u_char remain, len, i; 647 int error = SMB_ENOERR; 648 649 alsmb_clear(sc); 650 if (!alsmb_idle(sc)) 651 return (SMB_EBUSY); 652 653 remain = count; 654 while (remain) { 655 ALPM_SMBOUTB(sc, SMBHADDR, slave | LSB); 656 657 /* set the cmd and reset the 658 * 32-byte long internal buffer */ 659 ALPM_SMBOUTB(sc, SMBCMD, SMBWRBLOCK | SMB_BLK_CLR); 660 661 ALPM_SMBOUTB(sc, SMBHCMD, cmd); 662 ALPM_SMBOUTB(sc, SMBSTART, 0xff); 663 664 if ((error = alsmb_wait(sc)) != SMB_ENOERR) 665 goto error; 666 667 len = ALPM_SMBINB(sc, SMBHDATA); 668 669 /* read the 32-byte internal buffer */ 670 for (i=0; i<len; i++) { 671 buf[count-remain+i] = ALPM_SMBINB(sc, SMBHBLOCK); 672 DELAY(2); 673 } 674 675 remain -= len; 676 } 677error: 678 ALPM_DEBUG(printf("alpm: READBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error)); 679 680 return (error); 681} 682 683DRIVER_MODULE(alpm, pci, alpm_pci_driver, alpm_devclass, 0, 0); 684DRIVER_MODULE(alsmb, alpm, alsmb_driver, alsmb_devclass, 0, 0); 685