nfsmb.c revision 179860
1/*- 2 * Copyright (c) 2005 Ruslan Ermilov 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 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD: head/sys/pci/nfsmb.c 179860 2008-06-18 20:39:56Z joerg $"); 29 30#include <sys/param.h> 31#include <sys/bus.h> 32#include <sys/kernel.h> 33#include <sys/lock.h> 34#include <sys/module.h> 35#include <sys/mutex.h> 36#include <sys/systm.h> 37 38#include <machine/bus.h> 39#include <machine/resource.h> 40#include <sys/rman.h> 41 42#include <dev/pci/pcivar.h> 43#include <dev/pci/pcireg.h> 44 45#include <dev/smbus/smbconf.h> 46#include "smbus_if.h" 47 48#define NFSMB_DEBUG(x) if (nfsmb_debug) (x) 49 50#ifdef DEBUG 51static int nfsmb_debug = 1; 52#else 53static int nfsmb_debug = 0; 54#endif 55 56/* NVIDIA nForce2/3/4 MCP */ 57#define NFSMB_VENDORID_NVIDIA 0x10de 58#define NFSMB_DEVICEID_NF2_SMB 0x0064 59#define NFSMB_DEVICEID_NF2_ULTRA_SMB 0x0084 60#define NFSMB_DEVICEID_NF3_PRO150_SMB 0x00d4 61#define NFSMB_DEVICEID_NF3_250GB_SMB 0x00e4 62#define NFSMB_DEVICEID_NF4_SMB 0x0052 63#define NFSMB_DEVICEID_NF4_04_SMB 0x0034 64#define NFSMB_DEVICEID_NF4_51_SMB 0x0264 65#define NFSMB_DEVICEID_NF4_55_SMB 0x0368 66#define NFSMB_DEVICEID_NF4_61_SMB 0x03eb 67#define NFSMB_DEVICEID_NF4_65_SMB 0x0446 68 69/* PCI Configuration space registers */ 70#define NF2PCI_SMBASE_1 PCIR_BAR(4) 71#define NF2PCI_SMBASE_2 PCIR_BAR(5) 72 73/* 74 * ACPI 3.0, Chapter 12, SMBus Host Controller Interface. 75 */ 76#define SMB_PRTCL 0x00 /* protocol */ 77#define SMB_STS 0x01 /* status */ 78#define SMB_ADDR 0x02 /* address */ 79#define SMB_CMD 0x03 /* command */ 80#define SMB_DATA 0x04 /* 32 data registers */ 81#define SMB_BCNT 0x24 /* number of data bytes */ 82#define SMB_ALRM_A 0x25 /* alarm address */ 83#define SMB_ALRM_D 0x26 /* 2 bytes alarm data */ 84 85#define SMB_STS_DONE 0x80 86#define SMB_STS_ALRM 0x40 87#define SMB_STS_RES 0x20 88#define SMB_STS_STATUS 0x1f 89#define SMB_STS_OK 0x00 /* OK */ 90#define SMB_STS_UF 0x07 /* Unknown Failure */ 91#define SMB_STS_DANA 0x10 /* Device Address Not Acknowledged */ 92#define SMB_STS_DED 0x11 /* Device Error Detected */ 93#define SMB_STS_DCAD 0x12 /* Device Command Access Denied */ 94#define SMB_STS_UE 0x13 /* Unknown Error */ 95#define SMB_STS_DAD 0x17 /* Device Access Denied */ 96#define SMB_STS_T 0x18 /* Timeout */ 97#define SMB_STS_HUP 0x19 /* Host Unsupported Protocol */ 98#define SMB_STS_B 0x1A /* Busy */ 99#define SMB_STS_PEC 0x1F /* PEC (CRC-8) Error */ 100 101#define SMB_PRTCL_WRITE 0x00 102#define SMB_PRTCL_READ 0x01 103#define SMB_PRTCL_QUICK 0x02 104#define SMB_PRTCL_BYTE 0x04 105#define SMB_PRTCL_BYTE_DATA 0x06 106#define SMB_PRTCL_WORD_DATA 0x08 107#define SMB_PRTCL_BLOCK_DATA 0x0a 108#define SMB_PRTCL_PROC_CALL 0x0c 109#define SMB_PRTCL_BLOCK_PROC_CALL 0x0d 110#define SMB_PRTCL_PEC 0x80 111 112struct nfsmb_softc { 113 int rid; 114 struct resource *res; 115 device_t smbus; 116 device_t subdev; 117 struct mtx lock; 118}; 119 120#define NFSMB_LOCK(nfsmb) mtx_lock(&(nfsmb)->lock) 121#define NFSMB_UNLOCK(nfsmb) mtx_unlock(&(nfsmb)->lock) 122#define NFSMB_LOCK_ASSERT(nfsmb) mtx_assert(&(nfsmb)->lock, MA_OWNED) 123 124#define NFSMB_SMBINB(nfsmb, register) \ 125 (bus_read_1(nfsmb->res, register)) 126#define NFSMB_SMBOUTB(nfsmb, register, value) \ 127 (bus_write_1(nfsmb->res, register, value)) 128 129static int nfsmb_detach(device_t dev); 130static int nfsmbsub_detach(device_t dev); 131 132static int 133nfsmbsub_probe(device_t dev) 134{ 135 136 device_set_desc(dev, "nForce2/3/4 MCP SMBus Controller"); 137 return (BUS_PROBE_DEFAULT); 138} 139 140static int 141nfsmb_probe(device_t dev) 142{ 143 u_int16_t vid; 144 u_int16_t did; 145 146 vid = pci_get_vendor(dev); 147 did = pci_get_device(dev); 148 149 if (vid == NFSMB_VENDORID_NVIDIA) { 150 switch(did) { 151 case NFSMB_DEVICEID_NF2_SMB: 152 case NFSMB_DEVICEID_NF2_ULTRA_SMB: 153 case NFSMB_DEVICEID_NF3_PRO150_SMB: 154 case NFSMB_DEVICEID_NF3_250GB_SMB: 155 case NFSMB_DEVICEID_NF4_SMB: 156 case NFSMB_DEVICEID_NF4_04_SMB: 157 case NFSMB_DEVICEID_NF4_51_SMB: 158 case NFSMB_DEVICEID_NF4_55_SMB: 159 case NFSMB_DEVICEID_NF4_61_SMB: 160 case NFSMB_DEVICEID_NF4_65_SMB: 161 device_set_desc(dev, "nForce2/3/4 MCP SMBus Controller"); 162 return (BUS_PROBE_DEFAULT); 163 } 164 } 165 166 return (ENXIO); 167} 168 169static int 170nfsmbsub_attach(device_t dev) 171{ 172 device_t parent; 173 struct nfsmb_softc *nfsmbsub_sc = device_get_softc(dev); 174 175 parent = device_get_parent(dev); 176 177 nfsmbsub_sc->rid = NF2PCI_SMBASE_2; 178 179 nfsmbsub_sc->res = bus_alloc_resource_any(parent, SYS_RES_IOPORT, 180 &nfsmbsub_sc->rid, RF_ACTIVE); 181 if (nfsmbsub_sc->res == NULL) { 182 /* Older incarnations of the device used non-standard BARs. */ 183 nfsmbsub_sc->rid = 0x54; 184 nfsmbsub_sc->res = bus_alloc_resource_any(parent, 185 SYS_RES_IOPORT, &nfsmbsub_sc->rid, RF_ACTIVE); 186 if (nfsmbsub_sc->res == NULL) { 187 device_printf(dev, "could not map i/o space\n"); 188 return (ENXIO); 189 } 190 } 191 mtx_init(&nfsmbsub_sc->lock, device_get_nameunit(dev), "nfsmb", 192 MTX_DEF); 193 194 nfsmbsub_sc->smbus = device_add_child(dev, "smbus", -1); 195 if (nfsmbsub_sc->smbus == NULL) { 196 nfsmbsub_detach(dev); 197 return (EINVAL); 198 } 199 200 bus_generic_attach(dev); 201 202 return (0); 203} 204 205static int 206nfsmb_attach(device_t dev) 207{ 208 struct nfsmb_softc *nfsmb_sc = device_get_softc(dev); 209 210 /* Allocate I/O space */ 211 nfsmb_sc->rid = NF2PCI_SMBASE_1; 212 213 nfsmb_sc->res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, 214 &nfsmb_sc->rid, RF_ACTIVE); 215 216 if (nfsmb_sc->res == NULL) { 217 /* Older incarnations of the device used non-standard BARs. */ 218 nfsmb_sc->rid = 0x50; 219 nfsmb_sc->res = bus_alloc_resource_any(dev, 220 SYS_RES_IOPORT, &nfsmb_sc->rid, RF_ACTIVE); 221 if (nfsmb_sc->res == NULL) { 222 device_printf(dev, "could not map i/o space\n"); 223 return (ENXIO); 224 } 225 } 226 227 mtx_init(&nfsmb_sc->lock, device_get_nameunit(dev), "nfsmb", MTX_DEF); 228 229 /* Allocate a new smbus device */ 230 nfsmb_sc->smbus = device_add_child(dev, "smbus", -1); 231 if (!nfsmb_sc->smbus) { 232 nfsmb_detach(dev); 233 return (EINVAL); 234 } 235 236 nfsmb_sc->subdev = NULL; 237 switch (pci_get_device(dev)) { 238 case NFSMB_DEVICEID_NF2_SMB: 239 case NFSMB_DEVICEID_NF2_ULTRA_SMB: 240 case NFSMB_DEVICEID_NF3_PRO150_SMB: 241 case NFSMB_DEVICEID_NF3_250GB_SMB: 242 case NFSMB_DEVICEID_NF4_SMB: 243 case NFSMB_DEVICEID_NF4_04_SMB: 244 case NFSMB_DEVICEID_NF4_51_SMB: 245 case NFSMB_DEVICEID_NF4_55_SMB: 246 case NFSMB_DEVICEID_NF4_61_SMB: 247 case NFSMB_DEVICEID_NF4_65_SMB: 248 /* Trying to add secondary device as slave */ 249 nfsmb_sc->subdev = device_add_child(dev, "nfsmb", -1); 250 if (!nfsmb_sc->subdev) { 251 nfsmb_detach(dev); 252 return (EINVAL); 253 } 254 break; 255 default: 256 break; 257 } 258 259 bus_generic_attach(dev); 260 261 return (0); 262} 263 264static int 265nfsmbsub_detach(device_t dev) 266{ 267 device_t parent; 268 struct nfsmb_softc *nfsmbsub_sc = device_get_softc(dev); 269 270 parent = device_get_parent(dev); 271 272 if (nfsmbsub_sc->smbus) { 273 device_delete_child(dev, nfsmbsub_sc->smbus); 274 nfsmbsub_sc->smbus = NULL; 275 } 276 mtx_destroy(&nfsmbsub_sc->lock); 277 if (nfsmbsub_sc->res) { 278 bus_release_resource(parent, SYS_RES_IOPORT, nfsmbsub_sc->rid, 279 nfsmbsub_sc->res); 280 nfsmbsub_sc->res = NULL; 281 } 282 return (0); 283} 284 285static int 286nfsmb_detach(device_t dev) 287{ 288 struct nfsmb_softc *nfsmb_sc = device_get_softc(dev); 289 290 if (nfsmb_sc->subdev) { 291 device_delete_child(dev, nfsmb_sc->subdev); 292 nfsmb_sc->subdev = NULL; 293 } 294 295 if (nfsmb_sc->smbus) { 296 device_delete_child(dev, nfsmb_sc->smbus); 297 nfsmb_sc->smbus = NULL; 298 } 299 300 mtx_destroy(&nfsmb_sc->lock); 301 if (nfsmb_sc->res) { 302 bus_release_resource(dev, SYS_RES_IOPORT, nfsmb_sc->rid, 303 nfsmb_sc->res); 304 nfsmb_sc->res = NULL; 305 } 306 307 return (0); 308} 309 310static int 311nfsmb_callback(device_t dev, int index, void *data) 312{ 313 int error = 0; 314 315 switch (index) { 316 case SMB_REQUEST_BUS: 317 case SMB_RELEASE_BUS: 318 break; 319 default: 320 error = EINVAL; 321 } 322 323 return (error); 324} 325 326static int 327nfsmb_wait(struct nfsmb_softc *sc) 328{ 329 u_char sts; 330 int error, count; 331 332 NFSMB_LOCK_ASSERT(sc); 333 if (NFSMB_SMBINB(sc, SMB_PRTCL) != 0) 334 { 335 count = 10000; 336 do { 337 DELAY(500); 338 } while (NFSMB_SMBINB(sc, SMB_PRTCL) != 0 && count--); 339 if (count == 0) 340 return (SMB_ETIMEOUT); 341 } 342 343 sts = NFSMB_SMBINB(sc, SMB_STS) & SMB_STS_STATUS; 344 NFSMB_DEBUG(printf("nfsmb: STS=0x%x\n", sts)); 345 346 switch (sts) { 347 case SMB_STS_OK: 348 error = SMB_ENOERR; 349 break; 350 case SMB_STS_DANA: 351 error = SMB_ENOACK; 352 break; 353 case SMB_STS_B: 354 error = SMB_EBUSY; 355 break; 356 case SMB_STS_T: 357 error = SMB_ETIMEOUT; 358 break; 359 case SMB_STS_DCAD: 360 case SMB_STS_DAD: 361 case SMB_STS_HUP: 362 error = SMB_ENOTSUPP; 363 break; 364 default: 365 error = SMB_EBUSERR; 366 break; 367 } 368 369 return (error); 370} 371 372static int 373nfsmb_quick(device_t dev, u_char slave, int how) 374{ 375 struct nfsmb_softc *sc = (struct nfsmb_softc *)device_get_softc(dev); 376 u_char protocol; 377 int error; 378 379 protocol = SMB_PRTCL_QUICK; 380 381 switch (how) { 382 case SMB_QWRITE: 383 protocol |= SMB_PRTCL_WRITE; 384 NFSMB_DEBUG(printf("nfsmb: QWRITE to 0x%x", slave)); 385 break; 386 case SMB_QREAD: 387 protocol |= SMB_PRTCL_READ; 388 NFSMB_DEBUG(printf("nfsmb: QREAD to 0x%x", slave)); 389 break; 390 default: 391 panic("%s: unknown QUICK command (%x)!", __func__, how); 392 } 393 394 NFSMB_LOCK(sc); 395 NFSMB_SMBOUTB(sc, SMB_ADDR, slave); 396 NFSMB_SMBOUTB(sc, SMB_PRTCL, protocol); 397 398 error = nfsmb_wait(sc); 399 400 NFSMB_DEBUG(printf(", error=0x%x\n", error)); 401 NFSMB_UNLOCK(sc); 402 403 return (error); 404} 405 406static int 407nfsmb_sendb(device_t dev, u_char slave, char byte) 408{ 409 struct nfsmb_softc *sc = (struct nfsmb_softc *)device_get_softc(dev); 410 int error; 411 412 NFSMB_LOCK(sc); 413 NFSMB_SMBOUTB(sc, SMB_CMD, byte); 414 NFSMB_SMBOUTB(sc, SMB_ADDR, slave); 415 NFSMB_SMBOUTB(sc, SMB_PRTCL, SMB_PRTCL_WRITE | SMB_PRTCL_BYTE); 416 417 error = nfsmb_wait(sc); 418 419 NFSMB_DEBUG(printf("nfsmb: SENDB to 0x%x, byte=0x%x, error=0x%x\n", slave, byte, error)); 420 NFSMB_UNLOCK(sc); 421 422 return (error); 423} 424 425static int 426nfsmb_recvb(device_t dev, u_char slave, char *byte) 427{ 428 struct nfsmb_softc *sc = (struct nfsmb_softc *)device_get_softc(dev); 429 int error; 430 431 NFSMB_LOCK(sc); 432 NFSMB_SMBOUTB(sc, SMB_ADDR, slave); 433 NFSMB_SMBOUTB(sc, SMB_PRTCL, SMB_PRTCL_READ | SMB_PRTCL_BYTE); 434 435 if ((error = nfsmb_wait(sc)) == SMB_ENOERR) 436 *byte = NFSMB_SMBINB(sc, SMB_DATA); 437 438 NFSMB_DEBUG(printf("nfsmb: RECVB from 0x%x, byte=0x%x, error=0x%x\n", slave, *byte, error)); 439 NFSMB_UNLOCK(sc); 440 441 return (error); 442} 443 444static int 445nfsmb_writeb(device_t dev, u_char slave, char cmd, char byte) 446{ 447 struct nfsmb_softc *sc = (struct nfsmb_softc *)device_get_softc(dev); 448 int error; 449 450 NFSMB_LOCK(sc); 451 NFSMB_SMBOUTB(sc, SMB_CMD, cmd); 452 NFSMB_SMBOUTB(sc, SMB_DATA, byte); 453 NFSMB_SMBOUTB(sc, SMB_ADDR, slave); 454 NFSMB_SMBOUTB(sc, SMB_PRTCL, SMB_PRTCL_WRITE | SMB_PRTCL_BYTE_DATA); 455 456 error = nfsmb_wait(sc); 457 458 NFSMB_DEBUG(printf("nfsmb: WRITEB to 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, byte, error)); 459 NFSMB_UNLOCK(sc); 460 461 return (error); 462} 463 464static int 465nfsmb_readb(device_t dev, u_char slave, char cmd, char *byte) 466{ 467 struct nfsmb_softc *sc = (struct nfsmb_softc *)device_get_softc(dev); 468 int error; 469 470 NFSMB_LOCK(sc); 471 NFSMB_SMBOUTB(sc, SMB_CMD, cmd); 472 NFSMB_SMBOUTB(sc, SMB_ADDR, slave); 473 NFSMB_SMBOUTB(sc, SMB_PRTCL, SMB_PRTCL_READ | SMB_PRTCL_BYTE_DATA); 474 475 if ((error = nfsmb_wait(sc)) == SMB_ENOERR) 476 *byte = NFSMB_SMBINB(sc, SMB_DATA); 477 478 NFSMB_DEBUG(printf("nfsmb: READB from 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, (unsigned char)*byte, error)); 479 NFSMB_UNLOCK(sc); 480 481 return (error); 482} 483 484static int 485nfsmb_writew(device_t dev, u_char slave, char cmd, short word) 486{ 487 struct nfsmb_softc *sc = (struct nfsmb_softc *)device_get_softc(dev); 488 int error; 489 490 NFSMB_LOCK(sc); 491 NFSMB_SMBOUTB(sc, SMB_CMD, cmd); 492 NFSMB_SMBOUTB(sc, SMB_DATA, word); 493 NFSMB_SMBOUTB(sc, SMB_DATA + 1, word >> 8); 494 NFSMB_SMBOUTB(sc, SMB_ADDR, slave); 495 NFSMB_SMBOUTB(sc, SMB_PRTCL, SMB_PRTCL_WRITE | SMB_PRTCL_WORD_DATA); 496 497 error = nfsmb_wait(sc); 498 499 NFSMB_DEBUG(printf("nfsmb: WRITEW to 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, word, error)); 500 NFSMB_UNLOCK(sc); 501 502 return (error); 503} 504 505static int 506nfsmb_readw(device_t dev, u_char slave, char cmd, short *word) 507{ 508 struct nfsmb_softc *sc = (struct nfsmb_softc *)device_get_softc(dev); 509 int error; 510 511 NFSMB_LOCK(sc); 512 NFSMB_SMBOUTB(sc, SMB_CMD, cmd); 513 NFSMB_SMBOUTB(sc, SMB_ADDR, slave); 514 NFSMB_SMBOUTB(sc, SMB_PRTCL, SMB_PRTCL_READ | SMB_PRTCL_WORD_DATA); 515 516 if ((error = nfsmb_wait(sc)) == SMB_ENOERR) 517 *word = NFSMB_SMBINB(sc, SMB_DATA) | 518 (NFSMB_SMBINB(sc, SMB_DATA + 1) << 8); 519 520 NFSMB_DEBUG(printf("nfsmb: READW from 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, (unsigned short)*word, error)); 521 NFSMB_UNLOCK(sc); 522 523 return (error); 524} 525 526static int 527nfsmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf) 528{ 529 struct nfsmb_softc *sc = (struct nfsmb_softc *)device_get_softc(dev); 530 u_char i; 531 int error; 532 533 if (count < 1 || count > 32) 534 return (SMB_EINVAL); 535 536 NFSMB_LOCK(sc); 537 NFSMB_SMBOUTB(sc, SMB_CMD, cmd); 538 NFSMB_SMBOUTB(sc, SMB_BCNT, count); 539 for (i = 0; i < count; i++) 540 NFSMB_SMBOUTB(sc, SMB_DATA + i, buf[i]); 541 NFSMB_SMBOUTB(sc, SMB_ADDR, slave); 542 NFSMB_SMBOUTB(sc, SMB_PRTCL, SMB_PRTCL_WRITE | SMB_PRTCL_BLOCK_DATA); 543 544 error = nfsmb_wait(sc); 545 546 NFSMB_DEBUG(printf("nfsmb: WRITEBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error)); 547 NFSMB_UNLOCK(sc); 548 549 return (error); 550} 551 552static int 553nfsmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf) 554{ 555 struct nfsmb_softc *sc = (struct nfsmb_softc *)device_get_softc(dev); 556 u_char data, len, i; 557 int error; 558 559 if (*count < 1 || *count > 32) 560 return (SMB_EINVAL); 561 562 NFSMB_LOCK(sc); 563 NFSMB_SMBOUTB(sc, SMB_CMD, cmd); 564 NFSMB_SMBOUTB(sc, SMB_ADDR, slave); 565 NFSMB_SMBOUTB(sc, SMB_PRTCL, SMB_PRTCL_READ | SMB_PRTCL_BLOCK_DATA); 566 567 if ((error = nfsmb_wait(sc)) == SMB_ENOERR) { 568 len = NFSMB_SMBINB(sc, SMB_BCNT); 569 for (i = 0; i < len; i++) { 570 data = NFSMB_SMBINB(sc, SMB_DATA + i); 571 if (i < *count) 572 buf[i] = data; 573 } 574 *count = len; 575 } 576 577 NFSMB_DEBUG(printf("nfsmb: READBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, *count, cmd, error)); 578 NFSMB_UNLOCK(sc); 579 580 return (error); 581} 582 583static device_method_t nfsmb_methods[] = { 584 /* Device interface */ 585 DEVMETHOD(device_probe, nfsmb_probe), 586 DEVMETHOD(device_attach, nfsmb_attach), 587 DEVMETHOD(device_detach, nfsmb_detach), 588 589 /* SMBus interface */ 590 DEVMETHOD(smbus_callback, nfsmb_callback), 591 DEVMETHOD(smbus_quick, nfsmb_quick), 592 DEVMETHOD(smbus_sendb, nfsmb_sendb), 593 DEVMETHOD(smbus_recvb, nfsmb_recvb), 594 DEVMETHOD(smbus_writeb, nfsmb_writeb), 595 DEVMETHOD(smbus_readb, nfsmb_readb), 596 DEVMETHOD(smbus_writew, nfsmb_writew), 597 DEVMETHOD(smbus_readw, nfsmb_readw), 598 DEVMETHOD(smbus_bwrite, nfsmb_bwrite), 599 DEVMETHOD(smbus_bread, nfsmb_bread), 600 601 { 0, 0 } 602}; 603 604static device_method_t nfsmbsub_methods[] = { 605 /* Device interface */ 606 DEVMETHOD(device_probe, nfsmbsub_probe), 607 DEVMETHOD(device_attach, nfsmbsub_attach), 608 DEVMETHOD(device_detach, nfsmbsub_detach), 609 610 /* SMBus interface */ 611 DEVMETHOD(smbus_callback, nfsmb_callback), 612 DEVMETHOD(smbus_quick, nfsmb_quick), 613 DEVMETHOD(smbus_sendb, nfsmb_sendb), 614 DEVMETHOD(smbus_recvb, nfsmb_recvb), 615 DEVMETHOD(smbus_writeb, nfsmb_writeb), 616 DEVMETHOD(smbus_readb, nfsmb_readb), 617 DEVMETHOD(smbus_writew, nfsmb_writew), 618 DEVMETHOD(smbus_readw, nfsmb_readw), 619 DEVMETHOD(smbus_bwrite, nfsmb_bwrite), 620 DEVMETHOD(smbus_bread, nfsmb_bread), 621 622 { 0, 0 } 623}; 624 625static devclass_t nfsmb_devclass; 626 627static driver_t nfsmb_driver = { 628 "nfsmb", 629 nfsmb_methods, 630 sizeof(struct nfsmb_softc), 631}; 632 633static driver_t nfsmbsub_driver = { 634 "nfsmb", 635 nfsmbsub_methods, 636 sizeof(struct nfsmb_softc), 637}; 638 639DRIVER_MODULE(nfsmb, pci, nfsmb_driver, nfsmb_devclass, 0, 0); 640DRIVER_MODULE(nfsmb, nfsmb, nfsmbsub_driver, nfsmb_devclass, 0, 0); 641DRIVER_MODULE(smbus, nfsmb, smbus_driver, smbus_devclass, 0, 0); 642 643MODULE_DEPEND(nfsmb, pci, 1, 1, 1); 644MODULE_DEPEND(nfsmb, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER); 645MODULE_VERSION(nfsmb, 1); 646