File:  [DragonFly] / src / sys / dev / misc / spigot / spigot.c
Revision 1.8: download - view: text, annotated - select for diffs
Thu May 13 23:49:17 2004 UTC (10 years, 6 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:  * Video spigot capture driver.
    3:  *
    4:  * Copyright (c) 1995, Jim Lowe.  All rights reserved.
    5:  *
    6:  * Redistribution and use in source and binary forms, with or without
    7:  * modification, are permitted provided that the following conditions are
    8:  * met: 1. Redistributions of source code must retain the above copyright
    9:  * notice, this list of conditions and the following disclaimer. 2.
   10:  * Redistributions in binary form must reproduce the above copyright notice,
   11:  * this list of conditions and the following disclaimer in the documentation
   12:  * and/or other materials provided with the distribution.
   13:  *
   14:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
   15:  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   16:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   17:  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
   18:  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
   20:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
   21:  * 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:  * This is the minimum driver code required to make a spigot work.
   27:  * Unfortunatly, I can't include a real driver since the information
   28:  * on the spigot is under non-disclosure.  You can pick up a library
   29:  * that will work with this driver from
   30:  * ftp://ftp.cs.uwm.edu/pub/FreeBSD-UWM.  The library contains the
   31:  * source that I can release as well as several object modules and
   32:  * functions that allows one to read spigot data.  See the code for
   33:  * spigot_grab.c that is included with the library data.
   34:  *
   35:  * The vendor will not allow me to release the spigot library code.
   36:  * Please don't ask me for it.
   37:  *
   38:  * To use this driver you will need the spigot library.  The library is
   39:  * available from:
   40:  *
   41:  *	ftp.cs.uwm.edu://pub/FreeBSD-UWM/spigot/spigot.tar.gz
   42:  *
   43:  * Version 1.7, December 1995.
   44:  *
   45:  * $FreeBSD: src/sys/i386/isa/spigot.c,v 1.44 2000/01/29 16:17:36 peter Exp $
   46:  * $DragonFly: src/sys/dev/misc/spigot/spigot.c,v 1.8 2004/05/13 23:49:17 dillon Exp $
   47:  *
   48:  */
   49: 
   50: #include	"use_spigot.h"
   51: 
   52: #if NSPIGOT > 1
   53: error "Can only have 1 spigot configured."
   54: #endif
   55: 
   56: #include	"opt_spigot.h"
   57: 
   58: #include	<sys/param.h>
   59: #include	<sys/systm.h>
   60: #include	<sys/conf.h>
   61: #include	<sys/proc.h>
   62: #include	<sys/signalvar.h>
   63: #include	<sys/mman.h>
   64: 
   65: #include	<machine/frame.h>
   66: #include	<machine/md_var.h>
   67: #include	<machine/spigot.h>
   68: #include	<machine/psl.h>
   69: 
   70: #include	<bus/isa/i386/isa_device.h>
   71: 
   72: static struct spigot_softc {
   73: 	u_long		flags;
   74: 	u_long	 	maddr;
   75: 	struct proc	*p;
   76: 	u_long		signal_num;
   77: 	u_short		irq;
   78: } spigot_softc[NSPIGOT];
   79: 
   80: /* flags in softc */
   81: #define	OPEN		0x01
   82: #define	ALIVE		0x02
   83: 
   84: #define	UNIT(dev) minor(dev)
   85: 
   86: static int	spigot_probe(struct isa_device *id);
   87: static int	spigot_attach(struct isa_device *id);
   88: 
   89: struct isa_driver	spigotdriver = {spigot_probe, spigot_attach, "spigot"};
   90: 
   91: static	d_open_t	spigot_open;
   92: static	d_close_t	spigot_close;
   93: static	d_read_t	spigot_read;
   94: static	d_write_t	spigot_write;
   95: static	d_ioctl_t	spigot_ioctl;
   96: static	d_mmap_t	spigot_mmap;
   97: 
   98: #define CDEV_MAJOR 11
   99: static struct cdevsw spigot_cdevsw = {
  100: 	/* name */	"spigot",
  101: 	/* maj */	CDEV_MAJOR,
  102: 	/* flags */	0,
  103: 	/* port */	NULL,
  104: 	/* clone */	NULL,
  105: 
  106: 	/* open */	spigot_open,
  107: 	/* close */	spigot_close,
  108: 	/* read */	spigot_read,
  109: 	/* write */	spigot_write,
  110: 	/* ioctl */	spigot_ioctl,
  111: 	/* poll */	nopoll,
  112: 	/* mmap */	spigot_mmap,
  113: 	/* strategy */	nostrategy,
  114: 	/* dump */	nodump,
  115: 	/* psize */	nopsize
  116: };
  117: 
  118: static ointhand2_t	spigintr;
  119: 
  120: static int
  121: spigot_probe(struct isa_device *devp)
  122: {
  123: int			status;
  124: struct	spigot_softc	*ss=(struct spigot_softc *)&spigot_softc[devp->id_unit];
  125: static int once;
  126: 
  127: 	if (!once++)
  128: 		cdevsw_add(&spigot_cdevsw);
  129: 
  130: 	ss->flags = 0;
  131: 	ss->maddr = 0;
  132: 	ss->irq = 0;
  133: 
  134: 	if(devp->id_iobase != 0xad6 || inb(0xad9) == 0xff) 
  135: 		status = 0;	/* not found */
  136: 	else {
  137: 		status = 1;	/* found */
  138: 		ss->flags |= ALIVE;
  139: 	}
  140: 
  141: 	return(status);
  142: }
  143: 
  144: static int
  145: spigot_attach(struct isa_device *devp)
  146: {
  147: 	int	unit;
  148: 	struct	spigot_softc	*ss= &spigot_softc[unit = devp->id_unit];
  149: 
  150: 	devp->id_ointr = spigintr;
  151: 	ss->maddr = kvtop(devp->id_maddr);
  152: 	ss->irq = devp->id_irq;
  153: 	make_dev(&spigot_cdevsw, unit, 0, 0, 0644, "spigot%d", unit);
  154: 	return 1;
  155: }
  156: 
  157: static	int
  158: spigot_open(dev_t dev, int flags, int fmt, struct thread *td)
  159: {
  160: int			error;
  161: struct	spigot_softc	*ss = (struct spigot_softc *)&spigot_softc[UNIT(dev)];
  162: 
  163: 	if((ss->flags & ALIVE) == 0)
  164: 		return ENXIO;
  165: 
  166: 	if(ss->flags & OPEN)
  167: 		return EBUSY;
  168: 
  169: #if !defined(SPIGOT_UNSECURE)
  170: 	/*
  171: 	 * Don't allow open() unless the process has sufficient privileges,
  172: 	 * since mapping the i/o page and granting i/o privilege would
  173: 	 * require sufficient privilege soon and nothing much can be done
  174: 	 * without them.
  175: 	 */
  176: 	error = suser(td);
  177: 	if (error != 0)
  178: 		return error;
  179: 	if (securelevel > 0)
  180: 		return EPERM;
  181: #endif
  182: 
  183: 	ss->flags |= OPEN;
  184: 	ss->p = 0;
  185: 	ss->signal_num = 0;
  186: 
  187: 	return 0;
  188: }
  189: 
  190: static	int
  191: spigot_close(dev_t dev, int flags, int fmt, struct thread *td)
  192: {
  193: struct	spigot_softc	*ss = (struct spigot_softc *)&spigot_softc[UNIT(dev)];
  194: 
  195: 	ss->flags &= ~OPEN;
  196: 	ss->p = 0;
  197: 	ss->signal_num = 0;
  198: 
  199: 	outb(0xad6, 0);
  200: 
  201: 	return 0;
  202: }
  203: 
  204: static	int
  205: spigot_write(dev_t dev, struct uio *uio, int ioflag)
  206: {
  207: 	return ENXIO;
  208: }
  209: 
  210: static	int
  211: spigot_read(dev_t dev, struct uio *uio, int ioflag)
  212: {
  213: 	return ENXIO;
  214: }
  215: 
  216: 
  217: static	int
  218: spigot_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
  219: {
  220: int			error;
  221: struct	spigot_softc	*ss = (struct spigot_softc *)&spigot_softc[UNIT(dev)];
  222: struct	spigot_info	*info;
  223: 
  224: 	if(!data) return(EINVAL);
  225: 	switch(cmd){
  226: 	case	SPIGOT_SETINT:
  227: 		if (*(int *)data < 0 || *(int *)data > _SIG_MAXSIG)
  228: 			return (EINVAL);
  229: 		ss->p = td->td_proc;
  230: 		ss->signal_num = *((int *)data);
  231: 		break;
  232: 	case	SPIGOT_IOPL_ON:	/* allow access to the IO PAGE */
  233: #if !defined(SPIGOT_UNSECURE)
  234: 		error = suser(td);
  235: 		if (error != 0)
  236: 			return error;
  237: 		if (securelevel > 0)
  238: 			return EPERM;
  239: #endif
  240: 		td->td_proc->p_md.md_regs->tf_eflags |= PSL_IOPL;
  241: 		break;
  242: 	case	SPIGOT_IOPL_OFF: /* deny access to the IO PAGE */
  243: 		td->td_proc->p_md.md_regs->tf_eflags &= ~PSL_IOPL;
  244: 		break;
  245: 	case	SPIGOT_GET_INFO:
  246: 		info = (struct spigot_info *)data;
  247: 		info->maddr  = ss->maddr;
  248: 		info->irq = ss->irq;
  249: 		break;
  250: 	default:
  251: 		return ENOTTY;
  252: 	}
  253: 
  254: 	return 0;
  255: }
  256: 
  257: /*
  258:  * Interrupt procedure.
  259:  * Just call a user level interrupt routine.
  260:  */
  261: static void
  262: spigintr(int unit)
  263: {
  264: struct	spigot_softc	*ss = (struct spigot_softc *)&spigot_softc[unit];
  265: 
  266: 	if(ss->p && ss->signal_num)
  267: 		psignal(ss->p, ss->signal_num);
  268: }
  269: 
  270: static	int
  271: spigot_mmap(dev_t dev, vm_offset_t offset, int nprot)
  272: {
  273: struct	spigot_softc	*ss = (struct spigot_softc *)&spigot_softc[0];
  274: 
  275: 	if(offset != 0) {
  276: 		printf("spigot mmap failed, offset = 0x%x != 0x0\n", offset);
  277: 		return -1;
  278: 	}
  279: 
  280: 	if(nprot & PROT_EXEC)
  281: 		return -1;
  282: 
  283: 	return i386_btop(ss->maddr);
  284: }