nfsmb.c revision 162234
1160814Ssimon#include <sys/cdefs.h> 2160814Ssimon__FBSDID("$FreeBSD: head/sys/pci/nfsmb.c 162234 2006-09-11 20:52:41Z jhb $"); 3160814Ssimon 4160814Ssimon#include <sys/param.h> 5160814Ssimon#include <sys/kernel.h> 6160814Ssimon#include <sys/systm.h> 7160814Ssimon#include <sys/module.h> 8160814Ssimon#include <sys/bus.h> 9160814Ssimon#include <sys/uio.h> 10160814Ssimon 11160814Ssimon#include <machine/bus.h> 12160814Ssimon#include <machine/resource.h> 13160814Ssimon#include <sys/rman.h> 14160814Ssimon 15160814Ssimon#include <dev/pci/pcivar.h> 16160814Ssimon#include <dev/pci/pcireg.h> 17160814Ssimon 18160814Ssimon#include <dev/iicbus/iiconf.h> 19160814Ssimon#include <dev/smbus/smbconf.h> 20160814Ssimon#include "smbus_if.h" 21160814Ssimon 22160814Ssimon#define NFSMB_DEBUG(x) if (nfsmb_debug) (x) 23160814Ssimon 24160814Ssimon#ifdef DEBUG 25160814Ssimonstatic int nfsmb_debug = 1; 26160814Ssimon#else 27160814Ssimonstatic int nfsmb_debug = 0; 28160814Ssimon#endif 29160814Ssimon 30160814Ssimon/* NVIDIA nForce2/3/4 MCP */ 31160814Ssimon#define NFSMB_VENDORID_NVIDIA 0x10de 32160814Ssimon#define NFSMB_DEVICEID_NF2_SMB 0x0064 33160814Ssimon#define NFSMB_DEVICEID_NF2_ULTRA_SMB 0x0084 34160814Ssimon#define NFSMB_DEVICEID_NF3_PRO150_SMB 0x00d4 35160814Ssimon#define NFSMB_DEVICEID_NF3_250GB_SMB 0x00e4 36160814Ssimon#define NFSMB_DEVICEID_NF4_SMB 0x0052 37160814Ssimon#define NFSMB_DEVICEID_NF4_04_SMB 0x0034 38160814Ssimon#define NFSMB_DEVICEID_NF4_51_SMB 0x0264 39160814Ssimon#define NFSMB_DEVICEID_NF4_55_SMB 0x0368 40160814Ssimon 41160814Ssimon/* PCI Configuration space registers */ 42160814Ssimon#define NF2PCI_SMBASE_1 PCIR_BAR(4) 43160814Ssimon#define NF2PCI_SMBASE_2 PCIR_BAR(5) 44160814Ssimon 45160814Ssimon/* 46160814Ssimon * ACPI 3.0, Chapter 12, SMBus Host Controller Interface. 47160814Ssimon */ 48160814Ssimon#define SMB_PRTCL 0x00 /* protocol */ 49160814Ssimon#define SMB_STS 0x01 /* status */ 50160814Ssimon#define SMB_ADDR 0x02 /* address */ 51160814Ssimon#define SMB_CMD 0x03 /* command */ 52160814Ssimon#define SMB_DATA 0x04 /* 32 data registers */ 53160814Ssimon#define SMB_BCNT 0x24 /* number of data bytes */ 54160814Ssimon#define SMB_ALRM_A 0x25 /* alarm address */ 55160814Ssimon#define SMB_ALRM_D 0x26 /* 2 bytes alarm data */ 56160814Ssimon 57160814Ssimon#define SMB_STS_DONE 0x80 58160814Ssimon#define SMB_STS_ALRM 0x40 59160814Ssimon#define SMB_STS_RES 0x20 60160814Ssimon#define SMB_STS_STATUS 0x1f 61160814Ssimon#define SMB_STS_OK 0x00 /* OK */ 62160814Ssimon#define SMB_STS_UF 0x07 /* Unknown Failure */ 63160814Ssimon#define SMB_STS_DANA 0x10 /* Device Address Not Acknowledged */ 64160814Ssimon#define SMB_STS_DED 0x11 /* Device Error Detected */ 65160814Ssimon#define SMB_STS_DCAD 0x12 /* Device Command Access Denied */ 66160814Ssimon#define SMB_STS_UE 0x13 /* Unknown Error */ 67160814Ssimon#define SMB_STS_DAD 0x17 /* Device Access Denied */ 68160814Ssimon#define SMB_STS_T 0x18 /* Timeout */ 69160814Ssimon#define SMB_STS_HUP 0x19 /* Host Unsupported Protocol */ 70160814Ssimon#define SMB_STS_B 0x1A /* Busy */ 71160814Ssimon#define SMB_STS_PEC 0x1F /* PEC (CRC-8) Error */ 72160814Ssimon 73160814Ssimon#define SMB_PRTCL_WRITE 0x00 74160814Ssimon#define SMB_PRTCL_READ 0x01 75160814Ssimon#define SMB_PRTCL_QUICK 0x02 76160814Ssimon#define SMB_PRTCL_BYTE 0x04 77160814Ssimon#define SMB_PRTCL_BYTE_DATA 0x06 78160814Ssimon#define SMB_PRTCL_WORD_DATA 0x08 79160814Ssimon#define SMB_PRTCL_BLOCK_DATA 0x0a 80160814Ssimon#define SMB_PRTCL_PROC_CALL 0x0c 81160814Ssimon#define SMB_PRTCL_BLOCK_PROC_CALL 0x0d 82160814Ssimon#define SMB_PRTCL_PEC 0x80 83160814Ssimon 84160814Ssimonstruct nfsmb_softc { 85160814Ssimon int rid; 86160814Ssimon struct resource *res; 87160814Ssimon bus_space_tag_t smbst; 88160814Ssimon bus_space_handle_t smbsh; 89160814Ssimon 90160814Ssimon device_t smbus; 91160814Ssimon device_t subdev; 92160814Ssimon}; 93160814Ssimon 94160814Ssimon#define NFSMB_SMBINB(nfsmb, register) \ 95160814Ssimon (bus_space_read_1(nfsmb->smbst, nfsmb->smbsh, register)) 96160814Ssimon#define NFSMB_SMBOUTB(nfsmb, register, value) \ 97160814Ssimon (bus_space_write_1(nfsmb->smbst, nfsmb->smbsh, register, value)) 98160814Ssimon 99160814Ssimonstatic int 100160814Ssimonnfsmbsub_probe(device_t dev) 101160814Ssimon{ 102160814Ssimon 103160814Ssimon device_set_desc(dev, "nForce2/3/4 MCP SMBus Controller"); 104160814Ssimon return (BUS_PROBE_DEFAULT); 105160814Ssimon} 106160814Ssimon 107160814Ssimonstatic int 108160814Ssimonnfsmb_probe(device_t dev) 109160814Ssimon{ 110160814Ssimon u_int16_t vid; 111160814Ssimon u_int16_t did; 112160814Ssimon 113160814Ssimon vid = pci_get_vendor(dev); 114160814Ssimon did = pci_get_device(dev); 115160814Ssimon 116160814Ssimon if (vid == NFSMB_VENDORID_NVIDIA) { 117160814Ssimon switch(did) { 118160814Ssimon case NFSMB_DEVICEID_NF2_SMB: 119160814Ssimon case NFSMB_DEVICEID_NF2_ULTRA_SMB: 120160814Ssimon case NFSMB_DEVICEID_NF3_PRO150_SMB: 121160814Ssimon case NFSMB_DEVICEID_NF3_250GB_SMB: 122160814Ssimon case NFSMB_DEVICEID_NF4_SMB: 123160814Ssimon case NFSMB_DEVICEID_NF4_04_SMB: 124160814Ssimon case NFSMB_DEVICEID_NF4_51_SMB: 125160814Ssimon case NFSMB_DEVICEID_NF4_55_SMB: 126160814Ssimon device_set_desc(dev, "nForce2/3/4 MCP SMBus Controller"); 127160814Ssimon return (BUS_PROBE_DEFAULT); 128160814Ssimon } 129160814Ssimon } 130160814Ssimon 131160814Ssimon return (ENXIO); 132160814Ssimon} 133160814Ssimon 134160814Ssimonstatic int 135160814Ssimonnfsmbsub_attach(device_t dev) 136160814Ssimon{ 137160814Ssimon device_t parent; 138160814Ssimon struct nfsmb_softc *nfsmbsub_sc = device_get_softc(dev); 139160814Ssimon 140160814Ssimon parent = device_get_parent(dev); 141160814Ssimon 142160814Ssimon nfsmbsub_sc->rid = NF2PCI_SMBASE_2; 143160814Ssimon 144160814Ssimon nfsmbsub_sc->res = bus_alloc_resource_any(parent, SYS_RES_IOPORT, 145160814Ssimon &nfsmbsub_sc->rid, RF_ACTIVE); 146160814Ssimon if (nfsmbsub_sc->res == NULL) { 147160814Ssimon device_printf(dev, "could not map i/o space\n"); 148160814Ssimon return (ENXIO); 149160814Ssimon } 150160814Ssimon nfsmbsub_sc->smbst = rman_get_bustag(nfsmbsub_sc->res); 151194206Ssimon nfsmbsub_sc->smbsh = rman_get_bushandle(nfsmbsub_sc->res); 152160814Ssimon 153160814Ssimon nfsmbsub_sc->smbus = device_add_child(dev, "smbus", -1); 154160814Ssimon if (nfsmbsub_sc->smbus == NULL) 155160814Ssimon return (EINVAL); 156160814Ssimon 157160814Ssimon bus_generic_attach(dev); 158160814Ssimon 159160814Ssimon return (0); 160160814Ssimon} 161238405Sjkim 162160814Ssimonstatic int 163160814Ssimonnfsmb_attach(device_t dev) 164160814Ssimon{ 165160814Ssimon struct nfsmb_softc *nfsmb_sc = device_get_softc(dev); 166160814Ssimon 167238405Sjkim /* Allocate I/O space */ 168160814Ssimon nfsmb_sc->rid = NF2PCI_SMBASE_1; 169160814Ssimon 170160814Ssimon nfsmb_sc->res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, 171160814Ssimon &nfsmb_sc->rid, RF_ACTIVE); 172160814Ssimon 173160814Ssimon if (nfsmb_sc->res == NULL) { 174160814Ssimon device_printf(dev, "could not map i/o space\n"); 175160814Ssimon return (ENXIO); 176160814Ssimon } 177160814Ssimon 178194206Ssimon nfsmb_sc->smbst = rman_get_bustag(nfsmb_sc->res); 179160814Ssimon nfsmb_sc->smbsh = rman_get_bushandle(nfsmb_sc->res); 180160814Ssimon 181160814Ssimon /* Allocate a new smbus device */ 182160814Ssimon nfsmb_sc->smbus = device_add_child(dev, "smbus", -1); 183160814Ssimon if (!nfsmb_sc->smbus) 184160814Ssimon return (EINVAL); 185160814Ssimon 186160814Ssimon nfsmb_sc->subdev = NULL; 187160814Ssimon switch (pci_get_device(dev)) { 188238405Sjkim case NFSMB_DEVICEID_NF2_SMB: 189160814Ssimon case NFSMB_DEVICEID_NF2_ULTRA_SMB: 190160814Ssimon case NFSMB_DEVICEID_NF3_PRO150_SMB: 191160814Ssimon case NFSMB_DEVICEID_NF3_250GB_SMB: 192160814Ssimon case NFSMB_DEVICEID_NF4_SMB: 193160814Ssimon case NFSMB_DEVICEID_NF4_04_SMB: 194238405Sjkim case NFSMB_DEVICEID_NF4_51_SMB: 195160814Ssimon case NFSMB_DEVICEID_NF4_55_SMB: 196160814Ssimon /* Trying to add secondary device as slave */ 197160814Ssimon nfsmb_sc->subdev = device_add_child(dev, "nfsmb", -1); 198160814Ssimon if (!nfsmb_sc->subdev) 199160814Ssimon return (EINVAL); 200160814Ssimon break; 201160814Ssimon default: 202160814Ssimon break; 203160814Ssimon } 204160814Ssimon 205160814Ssimon bus_generic_attach(dev); 206194206Ssimon 207160814Ssimon return (0); 208160814Ssimon} 209160814Ssimon 210160814Ssimonstatic int 211160814Ssimonnfsmbsub_detach(device_t dev) 212160814Ssimon{ 213160814Ssimon device_t parent; 214160814Ssimon struct nfsmb_softc *nfsmbsub_sc = device_get_softc(dev); 215160814Ssimon 216160814Ssimon parent = device_get_parent(dev); 217160814Ssimon 218160814Ssimon if (nfsmbsub_sc->smbus) { 219160814Ssimon device_delete_child(dev, nfsmbsub_sc->smbus); 220160814Ssimon nfsmbsub_sc->smbus = NULL; 221160814Ssimon } 222160814Ssimon if (nfsmbsub_sc->res) { 223194206Ssimon bus_release_resource(parent, SYS_RES_IOPORT, nfsmbsub_sc->rid, 224160814Ssimon nfsmbsub_sc->res); 225160814Ssimon nfsmbsub_sc->res = NULL; 226160814Ssimon } 227160814Ssimon return (0); 228160814Ssimon} 229160814Ssimon 230160814Ssimonstatic int 231160814Ssimonnfsmb_detach(device_t dev) 232160814Ssimon{ 233160814Ssimon struct nfsmb_softc *nfsmb_sc = device_get_softc(dev); 234160814Ssimon 235160814Ssimon if (nfsmb_sc->subdev) { 236160814Ssimon device_delete_child(dev, nfsmb_sc->subdev); 237160814Ssimon nfsmb_sc->subdev = NULL; 238160814Ssimon } 239160814Ssimon 240194206Ssimon if (nfsmb_sc->smbus) { 241160814Ssimon device_delete_child(dev, nfsmb_sc->smbus); 242160814Ssimon nfsmb_sc->smbus = NULL; 243160814Ssimon } 244160814Ssimon 245160814Ssimon if (nfsmb_sc->res) { 246160814Ssimon bus_release_resource(dev, SYS_RES_IOPORT, nfsmb_sc->rid, 247160814Ssimon nfsmb_sc->res); 248160814Ssimon nfsmb_sc->res = NULL; 249160814Ssimon } 250160814Ssimon 251160814Ssimon return (0); 252160814Ssimon} 253160814Ssimon 254160814Ssimonstatic int 255160814Ssimonnfsmb_callback(device_t dev, int index, void *data) 256160814Ssimon{ 257160814Ssimon int error = 0; 258160814Ssimon 259160814Ssimon switch (index) { 260160814Ssimon case SMB_REQUEST_BUS: 261160814Ssimon case SMB_RELEASE_BUS: 262160814Ssimon break; 263160814Ssimon default: 264160814Ssimon error = EINVAL; 265160814Ssimon } 266160814Ssimon 267160814Ssimon return (error); 268160814Ssimon} 269160814Ssimon 270160814Ssimonstatic int 271160814Ssimonnfsmb_wait(struct nfsmb_softc *sc) 272160814Ssimon{ 273160814Ssimon u_char sts; 274160814Ssimon int error, count; 275160814Ssimon 276160814Ssimon if (NFSMB_SMBINB(sc, SMB_PRTCL) != 0) 277160814Ssimon { 278160814Ssimon count = 10000; 279160814Ssimon do { 280160814Ssimon DELAY(500); 281160814Ssimon } while (NFSMB_SMBINB(sc, SMB_PRTCL) != 0 && count--); 282160814Ssimon if (count == 0) 283160814Ssimon return (SMB_ETIMEOUT); 284160814Ssimon } 285160814Ssimon 286160814Ssimon sts = NFSMB_SMBINB(sc, SMB_STS) & SMB_STS_STATUS; 287160814Ssimon NFSMB_DEBUG(printf("nfsmb: STS=0x%x\n", sts)); 288160814Ssimon 289160814Ssimon switch (sts) { 290160814Ssimon case SMB_STS_OK: 291160814Ssimon error = SMB_ENOERR; 292160814Ssimon break; 293160814Ssimon case SMB_STS_DANA: 294160814Ssimon error = SMB_ENOACK; 295160814Ssimon break; 296160814Ssimon case SMB_STS_B: 297160814Ssimon error = SMB_EBUSY; 298160814Ssimon break; 299160814Ssimon case SMB_STS_T: 300160814Ssimon error = SMB_ETIMEOUT; 301160814Ssimon break; 302160814Ssimon case SMB_STS_DCAD: 303160814Ssimon case SMB_STS_DAD: 304160814Ssimon case SMB_STS_HUP: 305160814Ssimon error = SMB_ENOTSUPP; 306160814Ssimon break; 307160814Ssimon default: 308160814Ssimon error = SMB_EBUSERR; 309160814Ssimon break; 310160814Ssimon } 311160814Ssimon 312160814Ssimon return (error); 313160814Ssimon} 314160814Ssimon 315160814Ssimonstatic int 316160814Ssimonnfsmb_quick(device_t dev, u_char slave, int how) 317160814Ssimon{ 318160814Ssimon struct nfsmb_softc *sc = (struct nfsmb_softc *)device_get_softc(dev); 319160814Ssimon u_char protocol; 320160814Ssimon int error; 321160814Ssimon 322160814Ssimon protocol = SMB_PRTCL_QUICK; 323160814Ssimon 324160814Ssimon switch (how) { 325160814Ssimon case SMB_QWRITE: 326160814Ssimon protocol |= SMB_PRTCL_WRITE; 327160814Ssimon NFSMB_DEBUG(printf("nfsmb: QWRITE to 0x%x", slave)); 328160814Ssimon break; 329160814Ssimon case SMB_QREAD: 330160814Ssimon protocol |= SMB_PRTCL_READ; 331238405Sjkim NFSMB_DEBUG(printf("nfsmb: QREAD to 0x%x", slave)); 332160814Ssimon break; 333160814Ssimon default: 334160814Ssimon panic("%s: unknown QUICK command (%x)!", __func__, how); 335160814Ssimon } 336160814Ssimon 337160814Ssimon NFSMB_SMBOUTB(sc, SMB_ADDR, slave); 338160814Ssimon NFSMB_SMBOUTB(sc, SMB_PRTCL, protocol); 339160814Ssimon 340160814Ssimon error = nfsmb_wait(sc); 341160814Ssimon 342160814Ssimon NFSMB_DEBUG(printf(", error=0x%x\n", error)); 343238405Sjkim 344160814Ssimon return (error); 345160814Ssimon} 346160814Ssimon 347160814Ssimonstatic int 348160814Ssimonnfsmb_sendb(device_t dev, u_char slave, char byte) 349160814Ssimon{ 350160814Ssimon struct nfsmb_softc *sc = (struct nfsmb_softc *)device_get_softc(dev); 351160814Ssimon int error; 352238405Sjkim 353160814Ssimon NFSMB_SMBOUTB(sc, SMB_CMD, byte); 354160814Ssimon NFSMB_SMBOUTB(sc, SMB_ADDR, slave); 355160814Ssimon NFSMB_SMBOUTB(sc, SMB_PRTCL, SMB_PRTCL_WRITE | SMB_PRTCL_BYTE); 356160814Ssimon 357160814Ssimon error = nfsmb_wait(sc); 358160814Ssimon 359160814Ssimon NFSMB_DEBUG(printf("nfsmb: SENDB to 0x%x, byte=0x%x, error=0x%x\n", slave, byte, error)); 360160814Ssimon 361160814Ssimon return (error); 362160814Ssimon} 363160814Ssimon 364160814Ssimonstatic int 365160814Ssimonnfsmb_recvb(device_t dev, u_char slave, char *byte) 366160814Ssimon{ 367160814Ssimon struct nfsmb_softc *sc = (struct nfsmb_softc *)device_get_softc(dev); 368160814Ssimon int error; 369160814Ssimon 370160814Ssimon NFSMB_SMBOUTB(sc, SMB_ADDR, slave); 371160814Ssimon NFSMB_SMBOUTB(sc, SMB_PRTCL, SMB_PRTCL_READ | SMB_PRTCL_BYTE); 372160814Ssimon 373160814Ssimon if ((error = nfsmb_wait(sc)) == SMB_ENOERR) 374160814Ssimon *byte = NFSMB_SMBINB(sc, SMB_DATA); 375 376 NFSMB_DEBUG(printf("nfsmb: RECVB from 0x%x, byte=0x%x, error=0x%x\n", slave, *byte, error)); 377 378 return (error); 379} 380 381static int 382nfsmb_writeb(device_t dev, u_char slave, char cmd, char byte) 383{ 384 struct nfsmb_softc *sc = (struct nfsmb_softc *)device_get_softc(dev); 385 int error; 386 387 NFSMB_SMBOUTB(sc, SMB_CMD, cmd); 388 NFSMB_SMBOUTB(sc, SMB_DATA, byte); 389 NFSMB_SMBOUTB(sc, SMB_ADDR, slave); 390 NFSMB_SMBOUTB(sc, SMB_PRTCL, SMB_PRTCL_WRITE | SMB_PRTCL_BYTE_DATA); 391 392 error = nfsmb_wait(sc); 393 394 NFSMB_DEBUG(printf("nfsmb: WRITEB to 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, byte, error)); 395 396 return (error); 397} 398 399static int 400nfsmb_readb(device_t dev, u_char slave, char cmd, char *byte) 401{ 402 struct nfsmb_softc *sc = (struct nfsmb_softc *)device_get_softc(dev); 403 int error; 404 405 NFSMB_SMBOUTB(sc, SMB_CMD, cmd); 406 NFSMB_SMBOUTB(sc, SMB_ADDR, slave); 407 NFSMB_SMBOUTB(sc, SMB_PRTCL, SMB_PRTCL_READ | SMB_PRTCL_BYTE_DATA); 408 409 if ((error = nfsmb_wait(sc)) == SMB_ENOERR) 410 *byte = NFSMB_SMBINB(sc, SMB_DATA); 411 412 NFSMB_DEBUG(printf("nfsmb: READB from 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, (unsigned char)*byte, error)); 413 414 return (error); 415} 416 417static int 418nfsmb_writew(device_t dev, u_char slave, char cmd, short word) 419{ 420 struct nfsmb_softc *sc = (struct nfsmb_softc *)device_get_softc(dev); 421 int error; 422 423 NFSMB_SMBOUTB(sc, SMB_CMD, cmd); 424 NFSMB_SMBOUTB(sc, SMB_DATA, word); 425 NFSMB_SMBOUTB(sc, SMB_DATA + 1, word >> 8); 426 NFSMB_SMBOUTB(sc, SMB_ADDR, slave); 427 NFSMB_SMBOUTB(sc, SMB_PRTCL, SMB_PRTCL_WRITE | SMB_PRTCL_WORD_DATA); 428 429 error = nfsmb_wait(sc); 430 431 NFSMB_DEBUG(printf("nfsmb: WRITEW to 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, word, error)); 432 433 return (error); 434} 435 436static int 437nfsmb_readw(device_t dev, u_char slave, char cmd, short *word) 438{ 439 struct nfsmb_softc *sc = (struct nfsmb_softc *)device_get_softc(dev); 440 int error; 441 442 NFSMB_SMBOUTB(sc, SMB_CMD, cmd); 443 NFSMB_SMBOUTB(sc, SMB_ADDR, slave); 444 NFSMB_SMBOUTB(sc, SMB_PRTCL, SMB_PRTCL_READ | SMB_PRTCL_WORD_DATA); 445 446 if ((error = nfsmb_wait(sc)) == SMB_ENOERR) 447 *word = NFSMB_SMBINB(sc, SMB_DATA) | 448 (NFSMB_SMBINB(sc, SMB_DATA + 1) << 8); 449 450 NFSMB_DEBUG(printf("nfsmb: READW from 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, (unsigned short)*word, error)); 451 452 return (error); 453} 454 455static int 456nfsmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf) 457{ 458 struct nfsmb_softc *sc = (struct nfsmb_softc *)device_get_softc(dev); 459 u_char i; 460 int error; 461 462 if (count < 1 || count > 32) 463 return (SMB_EINVAL); 464 NFSMB_SMBOUTB(sc, SMB_CMD, cmd); 465 NFSMB_SMBOUTB(sc, SMB_BCNT, count); 466 for (i = 0; i < count; i++) 467 NFSMB_SMBOUTB(sc, SMB_DATA + i, buf[i]); 468 NFSMB_SMBOUTB(sc, SMB_ADDR, slave); 469 NFSMB_SMBOUTB(sc, SMB_PRTCL, SMB_PRTCL_WRITE | SMB_PRTCL_BLOCK_DATA); 470 471 error = nfsmb_wait(sc); 472 473 NFSMB_DEBUG(printf("nfsmb: WRITEBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error)); 474 475 return (error); 476} 477 478static int 479nfsmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf) 480{ 481 struct nfsmb_softc *sc = (struct nfsmb_softc *)device_get_softc(dev); 482 u_char data, len, i; 483 int error; 484 485 if (*count < 1 || *count > 32) 486 return (SMB_EINVAL); 487 NFSMB_SMBOUTB(sc, SMB_CMD, cmd); 488 NFSMB_SMBOUTB(sc, SMB_ADDR, slave); 489 NFSMB_SMBOUTB(sc, SMB_PRTCL, SMB_PRTCL_READ | SMB_PRTCL_BLOCK_DATA); 490 491 if ((error = nfsmb_wait(sc)) == SMB_ENOERR) { 492 len = NFSMB_SMBINB(sc, SMB_BCNT); 493 for (i = 0; i < len; i++) { 494 data = NFSMB_SMBINB(sc, SMB_DATA + i); 495 if (i < *count) 496 buf[i] = data; 497 } 498 *count = len; 499 } 500 501 NFSMB_DEBUG(printf("nfsmb: READBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, *count, cmd, error)); 502 503 return (error); 504} 505 506static device_method_t nfsmb_methods[] = { 507 /* Device interface */ 508 DEVMETHOD(device_probe, nfsmb_probe), 509 DEVMETHOD(device_attach, nfsmb_attach), 510 DEVMETHOD(device_detach, nfsmb_detach), 511 512 /* SMBus interface */ 513 DEVMETHOD(smbus_callback, nfsmb_callback), 514 DEVMETHOD(smbus_quick, nfsmb_quick), 515 DEVMETHOD(smbus_sendb, nfsmb_sendb), 516 DEVMETHOD(smbus_recvb, nfsmb_recvb), 517 DEVMETHOD(smbus_writeb, nfsmb_writeb), 518 DEVMETHOD(smbus_readb, nfsmb_readb), 519 DEVMETHOD(smbus_writew, nfsmb_writew), 520 DEVMETHOD(smbus_readw, nfsmb_readw), 521 DEVMETHOD(smbus_bwrite, nfsmb_bwrite), 522 DEVMETHOD(smbus_bread, nfsmb_bread), 523 524 { 0, 0 } 525}; 526 527static device_method_t nfsmbsub_methods[] = { 528 /* Device interface */ 529 DEVMETHOD(device_probe, nfsmbsub_probe), 530 DEVMETHOD(device_attach, nfsmbsub_attach), 531 DEVMETHOD(device_detach, nfsmbsub_detach), 532 533 /* SMBus interface */ 534 DEVMETHOD(smbus_callback, nfsmb_callback), 535 DEVMETHOD(smbus_quick, nfsmb_quick), 536 DEVMETHOD(smbus_sendb, nfsmb_sendb), 537 DEVMETHOD(smbus_recvb, nfsmb_recvb), 538 DEVMETHOD(smbus_writeb, nfsmb_writeb), 539 DEVMETHOD(smbus_readb, nfsmb_readb), 540 DEVMETHOD(smbus_writew, nfsmb_writew), 541 DEVMETHOD(smbus_readw, nfsmb_readw), 542 DEVMETHOD(smbus_bwrite, nfsmb_bwrite), 543 DEVMETHOD(smbus_bread, nfsmb_bread), 544 545 { 0, 0 } 546}; 547 548static devclass_t nfsmb_devclass; 549 550static driver_t nfsmb_driver = { 551 "nfsmb", 552 nfsmb_methods, 553 sizeof(struct nfsmb_softc), 554}; 555 556static driver_t nfsmbsub_driver = { 557 "nfsmb", 558 nfsmbsub_methods, 559 sizeof(struct nfsmb_softc), 560}; 561 562DRIVER_MODULE(nfsmb, pci, nfsmb_driver, nfsmb_devclass, 0, 0); 563DRIVER_MODULE(nfsmb, nfsmb, nfsmbsub_driver, nfsmb_devclass, 0, 0); 564DRIVER_MODULE(smbus, nfsmb, smbus_driver, smbus_devclass, 0, 0); 565 566MODULE_DEPEND(nfsmb, pci, 1, 1, 1); 567MODULE_DEPEND(nfsmb, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER); 568MODULE_VERSION(nfsmb, 1); 569