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