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