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