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