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