File:  [DragonFly] / src / sys / bus / smbus / smb.c
Revision 1.6: download - view: text, annotated - select for diffs
Thu May 13 23:49:13 2004 UTC (10 years, 4 months ago) by dillon
Branches: MAIN
CVS tags: HEAD
device switch 1/many: Remove d_autoq, add d_clone (where d_autoq was).

d_autoq was used to allow the device port dispatch to mix old-style synchronous
calls with new style messaging calls within a particular device.  It was never
used for that purpose.

d_clone will be more fully implemented as work continues.  We are going to
install d_port in the dev_t (struct specinfo) structure itself and d_clone
will be needed to allow devices to 'revector' the port on a minor-number
by minor-number basis, in particular allowing minor numbers to be directly
dispatched to distinct threads.  This is something we will be needing later
on.

    1: /*-
    2:  * Copyright (c) 1998 Nicolas Souchu
    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:  * $FreeBSD: src/sys/dev/smbus/smb.c,v 1.20 1999/11/18 05:44:56 peter Exp $
   27:  * $DragonFly: src/sys/bus/smbus/smb.c,v 1.6 2004/05/13 23:49:13 dillon Exp $
   28:  *
   29:  */
   30: #include <sys/param.h>
   31: #include <sys/kernel.h>
   32: #include <sys/systm.h>
   33: #include <sys/module.h>
   34: #include <sys/bus.h>
   35: #include <sys/conf.h>
   36: #include <sys/buf.h>
   37: #include <sys/uio.h>
   38: #include <sys/malloc.h>
   39: #include <sys/fcntl.h>
   40: 
   41: #include <machine/clock.h>
   42: 
   43: #include "smbconf.h"
   44: #include "smbus.h"
   45: #include <machine/smb.h>
   46: 
   47: #include "smbus_if.h"
   48: 
   49: #define BUFSIZE 1024
   50: 
   51: struct smb_softc {
   52: 
   53: 	int sc_addr;			/* address on smbus */
   54: 	int sc_count;			/* >0 if device opened */
   55: 
   56: 	char *sc_cp;			/* output buffer pointer */
   57: 
   58: 	char sc_buffer[BUFSIZE];	/* output buffer */
   59: 	char sc_inbuf[BUFSIZE];		/* input buffer */
   60: };
   61: 
   62: #define IIC_SOFTC(unit) \
   63: 	((struct smb_softc *)devclass_get_softc(smb_devclass, (unit)))
   64: 
   65: #define IIC_DEVICE(unit) \
   66: 	(devclass_get_device(smb_devclass, (unit)))
   67: 
   68: static int smb_probe(device_t);
   69: static int smb_attach(device_t);
   70: 
   71: static devclass_t smb_devclass;
   72: 
   73: static device_method_t smb_methods[] = {
   74: 	/* device interface */
   75: 	DEVMETHOD(device_probe,		smb_probe),
   76: 	DEVMETHOD(device_attach,	smb_attach),
   77: 
   78: 	/* smbus interface */
   79: 	DEVMETHOD(smbus_intr,		smbus_generic_intr),
   80: 
   81: 	{ 0, 0 }
   82: };
   83: 
   84: static driver_t smb_driver = {
   85: 	"smb",
   86: 	smb_methods,
   87: 	sizeof(struct smb_softc),
   88: };
   89: 
   90: static	d_open_t	smbopen;
   91: static	d_close_t	smbclose;
   92: static	d_write_t	smbwrite;
   93: static	d_read_t	smbread;
   94: static	d_ioctl_t	smbioctl;
   95: 
   96: #define CDEV_MAJOR 106
   97: static struct cdevsw smb_cdevsw = {
   98: 	/* name */	"smb",
   99: 	/* maj */	CDEV_MAJOR,
  100: 	/* flags */	0,
  101: 	/* port */	NULL,
  102: 	/* clone */	NULL,
  103: 
  104: 	/* open */	smbopen,
  105: 	/* close */	smbclose,
  106: 	/* read */	smbread,
  107: 	/* write */	smbwrite,
  108: 	/* ioctl */	smbioctl,
  109: 	/* poll */	nopoll,
  110: 	/* mmap */	nommap,
  111: 	/* strategy */	nostrategy,
  112: 	/* dump */	nodump,
  113: 	/* psize */	nopsize
  114: };
  115: 
  116: /*
  117:  * smbprobe()
  118:  */
  119: static int
  120: smb_probe(device_t dev)
  121: {
  122: 	struct smb_softc *sc = (struct smb_softc *)device_get_softc(dev);
  123: 
  124: 	sc->sc_addr = smbus_get_addr(dev);
  125: 
  126: 	/* XXX detect chip with start/stop conditions */
  127: 
  128: 	return (0);
  129: }
  130: 	
  131: /*
  132:  * smbattach()
  133:  */
  134: static int
  135: smb_attach(device_t dev)
  136: {
  137: 	make_dev(&smb_cdevsw, device_get_unit(dev),	/* XXX cleanup */
  138: 			UID_ROOT, GID_WHEEL,
  139: 			0600, "smb%d", device_get_unit(dev));
  140: 	return (0);
  141: }
  142: 
  143: static int
  144: smbopen (dev_t dev, int flags, int fmt, struct thread *td)
  145: {
  146: 	struct smb_softc *sc = IIC_SOFTC(minor(dev));
  147: 
  148: 	if (!sc)
  149: 		return (EINVAL);
  150: 
  151: 	if (sc->sc_count)
  152: 		return (EBUSY);
  153: 
  154: 	sc->sc_count++;
  155: 
  156: 	return (0);
  157: }
  158: 
  159: static int
  160: smbclose(dev_t dev, int flags, int fmt, struct thread *td)
  161: {
  162: 	struct smb_softc *sc = IIC_SOFTC(minor(dev));
  163: 
  164: 	if (!sc)
  165: 		return (EINVAL);
  166: 
  167: 	if (!sc->sc_count)
  168: 		return (EINVAL);
  169: 
  170: 	sc->sc_count--;
  171: 
  172: 	return (0);
  173: }
  174: 
  175: static int
  176: smbwrite(dev_t dev, struct uio * uio, int ioflag)
  177: {
  178: 	/* not supported */
  179: 
  180: 	return (EINVAL);
  181: }
  182: 
  183: static int
  184: smbread(dev_t dev, struct uio * uio, int ioflag)
  185: {
  186: 	/* not supported */
  187: 
  188: 	return (EINVAL);
  189: }
  190: 
  191: static int
  192: smbioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct thread *td)
  193: {
  194: 	device_t smbdev = IIC_DEVICE(minor(dev));
  195: 	struct smb_softc *sc = IIC_SOFTC(minor(dev));
  196: 	device_t parent = device_get_parent(smbdev);
  197: 
  198: 	int error = 0;
  199: 	struct smbcmd *s = (struct smbcmd *)data;
  200: 
  201: 	if (!sc || !s)
  202: 		return (EINVAL);
  203: 
  204: 	/* allocate the bus */
  205: 	if ((error = smbus_request_bus(parent, smbdev,
  206: 			(flags & O_NONBLOCK) ? SMB_DONTWAIT : (SMB_WAIT | SMB_INTR))))
  207: 		return (error);
  208: 
  209: 	switch (cmd) {
  210: 	case SMB_QUICK_WRITE:
  211: 		error = smbus_error(smbus_quick(parent, s->slave, SMB_QWRITE));
  212: 		break;
  213: 
  214: 	case SMB_QUICK_READ:
  215: 		error = smbus_error(smbus_quick(parent, s->slave, SMB_QREAD));
  216: 		break;
  217: 
  218: 	case SMB_SENDB:
  219: 		error = smbus_error(smbus_sendb(parent, s->slave, s->cmd));
  220: 		break;
  221: 
  222: 	case SMB_RECVB:
  223: 		error = smbus_error(smbus_recvb(parent, s->slave, &s->cmd));
  224: 		break;
  225: 
  226: 	case SMB_WRITEB:
  227: 		error = smbus_error(smbus_writeb(parent, s->slave, s->cmd,
  228: 						s->data.byte));
  229: 		break;
  230: 
  231: 	case SMB_WRITEW:
  232: 		error = smbus_error(smbus_writew(parent, s->slave,
  233: 						s->cmd, s->data.word));
  234: 		break;
  235: 
  236: 	case SMB_READB:
  237: 		if (s->data.byte_ptr)
  238: 			error = smbus_error(smbus_readb(parent, s->slave,
  239: 						s->cmd, s->data.byte_ptr));
  240: 		break;
  241: 
  242: 	case SMB_READW:
  243: 		if (s->data.word_ptr)
  244: 			error = smbus_error(smbus_readw(parent, s->slave,
  245: 						s->cmd, s->data.word_ptr));
  246: 		break;
  247: 
  248: 	case SMB_PCALL:
  249: 		if (s->data.process.rdata)
  250: 			error = smbus_error(smbus_pcall(parent, s->slave, s->cmd,
  251: 				s->data.process.sdata, s->data.process.rdata));
  252: 		break;
  253: 
  254: 	case SMB_BWRITE:
  255: 		if (s->count && s->data.byte_ptr)
  256: 			error = smbus_error(smbus_bwrite(parent, s->slave,
  257: 						s->cmd, s->count, s->data.byte_ptr));
  258: 		break;
  259: 
  260: 	case SMB_BREAD:
  261: 		if (s->count && s->data.byte_ptr)
  262: 			error = smbus_error(smbus_bread(parent, s->slave,
  263: 						s->cmd, s->count, s->data.byte_ptr));
  264: 		break;
  265: 		
  266: 	default:
  267: 		error = ENODEV;
  268: 	}
  269: 
  270: 	/* release the bus */
  271: 	smbus_release_bus(parent, smbdev);
  272: 
  273: 	return (error);
  274: }
  275: 
  276: DRIVER_MODULE(smb, smbus, smb_driver, smb_devclass, 0, 0);