alpm.c revision 43973
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$ 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 DRIVER_TYPE_MISC, 194 sizeof(struct alsmb_softc), 195}; 196 197static const char* alpm_pci_probe(pcici_t tag, pcidi_t type); 198static void alpm_pci_attach(pcici_t tag, int unit); 199 200static u_long alpm_count; 201 202static struct pci_device alpm_device = { 203 "alpm", 204 alpm_pci_probe, 205 alpm_pci_attach, 206 &alpm_count 207}; 208 209DATA_SET (pcidevice_set, alpm_device); 210 211static const char* 212alpm_pci_probe(pcici_t tag, pcidi_t type) 213{ 214 if (type == ACER_M1543_PMU_ID) 215 return ("AcerLabs M15x3 Power Management Unit"); 216 217 return ((char *)0); 218} 219 220static void 221alpm_pci_attach(pcici_t tag, int unit) 222{ 223 struct alpm_data *alpm; 224 u_long l; 225 226 if (unit >= NALPM) { 227 printf("alpm%d: attach: only %d units configured.\n", 228 unit, NALPM); 229 return; 230 } 231 alpm = &alpmdata[unit]; 232 233 alpm->tag = tag; 234 235 /* Unlock SMBIO base register access */ 236 l = pci_cfgread(tag, ATPC, 1); 237 pci_cfgwrite(tag, ATPC, l & ~ATPC_SMBCTRL, 1); 238 239 if (bootverbose) { 240 l = pci_cfgread(tag, SMBHSI, 1); 241 printf("alsmb%d: %s/%s", unit, 242 (l & SMBHSI_HOST) ? "host":"nohost", 243 (l & SMBHSI_SLAVE) ? "slave":"noslave"); 244 245 l = pci_cfgread(tag, SMBHCBC, 1); 246 switch (l & SMBHCBC_CLOCK) { 247 case SMBCLOCK_149K: 248 printf(" 149K"); 249 break; 250 case SMBCLOCK_74K: 251 printf(" 74K"); 252 break; 253 case SMBCLOCK_37K: 254 printf(" 37K"); 255 break; 256 case SMBCLOCK_223K: 257 printf(" 223K"); 258 break; 259 case SMBCLOCK_111K: 260 printf(" 111K"); 261 break; 262 case SMBCLOCK_55K: 263 printf(" 55K"); 264 break; 265 } 266 } 267 268 alpm->smbst = I386_BUS_SPACE_IO; 269 270#ifdef ALPM_SMBIO_BASE_ADDR 271 /* disable I/O */ 272 l = pci_cfgread(tag, COM, 2); 273 pci_cfgwrite(tag, COM, l & ~COM_ENABLE_IO, 2); 274 275 /* set the I/O base address */ 276 pci_cfgwrite(tag, SMBBA, ALPM_SMBIO_BASE_ADDR | 0x1, 4); 277 278 /* enable I/O */ 279 pci_cfgwrite(tag, COM, l | COM_ENABLE_IO, 2); 280 281 alpm->smbsh = ALPM_SMBIO_BASE_ADDR; 282#else 283 alpm->smbsh = pci_cfgread(tag, SMBBA, 4) & ~0x1; 284#endif 285 if (bootverbose) 286 printf(" at 0x%x\n", alpm->smbsh); 287 288 /* XXX add the I2C interface to the root_bus until pcibus is ready */ 289 device_add_child(root_bus, "alsmb", unit, NULL); 290 291 return; 292} 293 294/* 295 * Not a real probe, we know the device exists since the device has 296 * been added after the successfull pci probe. 297 */ 298static int 299alsmb_probe(device_t dev) 300{ 301 struct alsmb_softc *sc = (struct alsmb_softc *)device_get_softc(dev); 302 303 sc->alpm = &alpmdata[device_get_unit(dev)]; 304 305 device_set_desc(dev, "Aladdin IV/V/Pro2 SMBus controller"); 306 307 return (0); 308} 309 310static int 311alsmb_attach(device_t dev) 312{ 313 struct alsmb_softc *sc = (struct alsmb_softc *)device_get_softc(dev); 314 315 /* allocate a new smbus device */ 316 sc->smbus = smbus_alloc_bus(dev); 317 318 /* probe and attach the smbus */ 319 device_probe_and_attach(sc->smbus); 320 321 return (0); 322} 323 324static void 325alsmb_print_child(device_t bus, device_t dev) 326{ 327 printf(" on %s%d", device_get_name(bus), device_get_unit(bus)); 328 329 return; 330} 331 332static int 333alsmb_smb_callback(device_t dev, int index, caddr_t *data) 334{ 335 int error = 0; 336 337 switch (index) { 338 case SMB_REQUEST_BUS: 339 case SMB_RELEASE_BUS: 340 /* ok, bus allocation accepted */ 341 break; 342 default: 343 error = EINVAL; 344 } 345 346 return (error); 347} 348 349static int 350alsmb_clear(struct alsmb_softc *sc) 351{ 352 ALPM_SMBOUTB(sc, SMBSTS, 0xff); 353 DELAY(10); 354 355 return (0); 356} 357 358#if 0 359static int 360alsmb_abort(struct alsmb_softc *sc) 361{ 362 ALPM_SMBOUTB(sc, SMBCMD, T_OUT_CMD | ABORT_HOST); 363 364 return (0); 365} 366#endif 367 368static int 369alsmb_idle(struct alsmb_softc *sc) 370{ 371 u_char sts; 372 373 sts = ALPM_SMBINB(sc, SMBSTS); 374 375 ALPM_DEBUG(printf("alpm: idle? STS=0x%x\n", sts)); 376 377 return (sts & IDL_STS); 378} 379 380/* 381 * Poll the SMBus controller 382 */ 383static int 384alsmb_wait(struct alsmb_softc *sc) 385{ 386 int count = 10000; 387 u_char sts; 388 int error; 389 390 /* wait for command to complete and SMBus controller is idle */ 391 while(count--) { 392 DELAY(10); 393 sts = ALPM_SMBINB(sc, SMBSTS); 394 if (sts & SMI_I_STS) 395 break; 396 } 397 398 ALPM_DEBUG(printf("alpm: STS=0x%x\n", sts)); 399 400 error = SMB_ENOERR; 401 402 if (!count) 403 error |= SMB_ETIMEOUT; 404 405 if (sts & TERMINATE) 406 error |= SMB_EABORT; 407 408 if (sts & BUS_COLLI) 409 error |= SMB_ENOACK; 410 411 if (sts & DEVICE_ERR) 412 error |= SMB_EBUSERR; 413 414 if (error != SMB_ENOERR) 415 alsmb_clear(sc); 416 417 return (error); 418} 419 420static int 421alsmb_smb_quick(device_t dev, u_char slave, int how) 422{ 423 struct alsmb_softc *sc = (struct alsmb_softc *)device_get_softc(dev); 424 int error; 425 426 alsmb_clear(sc); 427 if (!alsmb_idle(sc)) 428 return (EBUSY); 429 430 switch (how) { 431 case SMB_QWRITE: 432 ALPM_DEBUG(printf("alpm: QWRITE to 0x%x", slave)); 433 ALPM_SMBOUTB(sc, SMBHADDR, slave & ~LSB); 434 break; 435 case SMB_QREAD: 436 ALPM_DEBUG(printf("alpm: QREAD to 0x%x", slave)); 437 ALPM_SMBOUTB(sc, SMBHADDR, slave | LSB); 438 break; 439 default: 440 panic("%s: unknown QUICK command (%x)!", __FUNCTION__, 441 how); 442 } 443 ALPM_SMBOUTB(sc, SMBCMD, SMBQUICK); 444 ALPM_SMBOUTB(sc, SMBSTART, 0xff); 445 446 error = alsmb_wait(sc); 447 448 ALPM_DEBUG(printf(", error=0x%x\n", error)); 449 450 return (error); 451} 452 453static int 454alsmb_smb_sendb(device_t dev, u_char slave, char byte) 455{ 456 struct alsmb_softc *sc = (struct alsmb_softc *)device_get_softc(dev); 457 int error; 458 459 alsmb_clear(sc); 460 if (!alsmb_idle(sc)) 461 return (SMB_EBUSY); 462 463 ALPM_SMBOUTB(sc, SMBHADDR, slave & ~LSB); 464 ALPM_SMBOUTB(sc, SMBCMD, SMBSRBYTE); 465 ALPM_SMBOUTB(sc, SMBHDATA, byte); 466 ALPM_SMBOUTB(sc, SMBSTART, 0xff); 467 468 error = alsmb_wait(sc); 469 470 ALPM_DEBUG(printf("alpm: SENDB to 0x%x, byte=0x%x, error=0x%x\n", slave, byte, error)); 471 472 return (error); 473} 474 475static int 476alsmb_smb_recvb(device_t dev, u_char slave, char *byte) 477{ 478 struct alsmb_softc *sc = (struct alsmb_softc *)device_get_softc(dev); 479 int error; 480 481 alsmb_clear(sc); 482 if (!alsmb_idle(sc)) 483 return (SMB_EBUSY); 484 485 ALPM_SMBOUTB(sc, SMBHADDR, slave | LSB); 486 ALPM_SMBOUTB(sc, SMBCMD, SMBSRBYTE); 487 ALPM_SMBOUTB(sc, SMBSTART, 0xff); 488 489 if ((error = alsmb_wait(sc)) == SMB_ENOERR) 490 *byte = ALPM_SMBINB(sc, SMBHDATA); 491 492 ALPM_DEBUG(printf("alpm: RECVB from 0x%x, byte=0x%x, error=0x%x\n", slave, *byte, error)); 493 494 return (error); 495} 496 497static int 498alsmb_smb_writeb(device_t dev, u_char slave, char cmd, char byte) 499{ 500 struct alsmb_softc *sc = (struct alsmb_softc *)device_get_softc(dev); 501 int error; 502 503 alsmb_clear(sc); 504 if (!alsmb_idle(sc)) 505 return (SMB_EBUSY); 506 507 ALPM_SMBOUTB(sc, SMBHADDR, slave & ~LSB); 508 ALPM_SMBOUTB(sc, SMBCMD, SMBWRBYTE); 509 ALPM_SMBOUTB(sc, SMBHDATA, byte); 510 ALPM_SMBOUTB(sc, SMBHCMD, cmd); 511 ALPM_SMBOUTB(sc, SMBSTART, 0xff); 512 513 error = alsmb_wait(sc); 514 515 ALPM_DEBUG(printf("alpm: WRITEB to 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, byte, error)); 516 517 return (error); 518} 519 520static int 521alsmb_smb_readb(device_t dev, u_char slave, char cmd, char *byte) 522{ 523 struct alsmb_softc *sc = (struct alsmb_softc *)device_get_softc(dev); 524 int error; 525 526 alsmb_clear(sc); 527 if (!alsmb_idle(sc)) 528 return (SMB_EBUSY); 529 530 ALPM_SMBOUTB(sc, SMBHADDR, slave | LSB); 531 ALPM_SMBOUTB(sc, SMBCMD, SMBWRBYTE); 532 ALPM_SMBOUTB(sc, SMBHCMD, cmd); 533 ALPM_SMBOUTB(sc, SMBSTART, 0xff); 534 535 if ((error = alsmb_wait(sc)) == SMB_ENOERR) 536 *byte = ALPM_SMBINB(sc, SMBHDATA); 537 538 ALPM_DEBUG(printf("alpm: READB from 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, *byte, error)); 539 540 return (error); 541} 542 543static int 544alsmb_smb_writew(device_t dev, u_char slave, char cmd, short word) 545{ 546 struct alsmb_softc *sc = (struct alsmb_softc *)device_get_softc(dev); 547 int error; 548 549 alsmb_clear(sc); 550 if (!alsmb_idle(sc)) 551 return (SMB_EBUSY); 552 553 ALPM_SMBOUTB(sc, SMBHADDR, slave & ~LSB); 554 ALPM_SMBOUTB(sc, SMBCMD, SMBWRWORD); 555 ALPM_SMBOUTB(sc, SMBHDATA, word & 0x00ff); 556 ALPM_SMBOUTB(sc, SMBHDATB, (word & 0xff00) >> 8); 557 ALPM_SMBOUTB(sc, SMBHCMD, cmd); 558 ALPM_SMBOUTB(sc, SMBSTART, 0xff); 559 560 error = alsmb_wait(sc); 561 562 ALPM_DEBUG(printf("alpm: WRITEW to 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, word, error)); 563 564 return (error); 565} 566 567static int 568alsmb_smb_readw(device_t dev, u_char slave, char cmd, short *word) 569{ 570 struct alsmb_softc *sc = (struct alsmb_softc *)device_get_softc(dev); 571 int error; 572 u_char high, low; 573 574 alsmb_clear(sc); 575 if (!alsmb_idle(sc)) 576 return (SMB_EBUSY); 577 578 ALPM_SMBOUTB(sc, SMBHADDR, slave | LSB); 579 ALPM_SMBOUTB(sc, SMBCMD, SMBWRWORD); 580 ALPM_SMBOUTB(sc, SMBHCMD, cmd); 581 ALPM_SMBOUTB(sc, SMBSTART, 0xff); 582 583 if ((error = alsmb_wait(sc)) == SMB_ENOERR) { 584 low = ALPM_SMBINB(sc, SMBHDATA); 585 high = ALPM_SMBINB(sc, SMBHDATB); 586 587 *word = ((high & 0xff) << 8) | (low & 0xff); 588 } 589 590 ALPM_DEBUG(printf("alpm: READW from 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, *word, error)); 591 592 return (error); 593} 594 595static int 596alsmb_smb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf) 597{ 598 struct alsmb_softc *sc = (struct alsmb_softc *)device_get_softc(dev); 599 u_char remain, len, i; 600 int error = SMB_ENOERR; 601 602 alsmb_clear(sc); 603 if(!alsmb_idle(sc)) 604 return (SMB_EBUSY); 605 606 remain = count; 607 while (remain) { 608 len = min(remain, 32); 609 610 ALPM_SMBOUTB(sc, SMBHADDR, slave & ~LSB); 611 612 /* set the cmd and reset the 613 * 32-byte long internal buffer */ 614 ALPM_SMBOUTB(sc, SMBCMD, SMBWRBLOCK | SMB_BLK_CLR); 615 616 ALPM_SMBOUTB(sc, SMBHDATA, len); 617 618 /* fill the 32-byte internal buffer */ 619 for (i=0; i<len; i++) { 620 ALPM_SMBOUTB(sc, SMBHBLOCK, buf[count-remain+i]); 621 DELAY(2); 622 } 623 ALPM_SMBOUTB(sc, SMBHCMD, cmd); 624 ALPM_SMBOUTB(sc, SMBSTART, 0xff); 625 626 if ((error = alsmb_wait(sc)) != SMB_ENOERR) 627 goto error; 628 629 remain -= len; 630 } 631 632error: 633 ALPM_DEBUG(printf("alpm: WRITEBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error)); 634 635 return (error); 636} 637 638static int 639alsmb_smb_bread(device_t dev, u_char slave, char cmd, u_char count, char *buf) 640{ 641 struct alsmb_softc *sc = (struct alsmb_softc *)device_get_softc(dev); 642 u_char remain, len, i; 643 int error = SMB_ENOERR; 644 645 alsmb_clear(sc); 646 if (!alsmb_idle(sc)) 647 return (SMB_EBUSY); 648 649 remain = count; 650 while (remain) { 651 ALPM_SMBOUTB(sc, SMBHADDR, slave | LSB); 652 653 /* set the cmd and reset the 654 * 32-byte long internal buffer */ 655 ALPM_SMBOUTB(sc, SMBCMD, SMBWRBLOCK | SMB_BLK_CLR); 656 657 ALPM_SMBOUTB(sc, SMBHCMD, cmd); 658 ALPM_SMBOUTB(sc, SMBSTART, 0xff); 659 660 if ((error = alsmb_wait(sc)) != SMB_ENOERR) 661 goto error; 662 663 len = ALPM_SMBINB(sc, SMBHDATA); 664 665 /* read the 32-byte internal buffer */ 666 for (i=0; i<len; i++) { 667 buf[count-remain+i] = ALPM_SMBINB(sc, SMBHBLOCK); 668 DELAY(2); 669 } 670 671 remain -= len; 672 } 673error: 674 ALPM_DEBUG(printf("alpm: READBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error)); 675 676 return (error); 677} 678 679DRIVER_MODULE(alsmb, root, alsmb_driver, alsmb_devclass, 0, 0); 680#endif 681