Coherent4.2.10/coh.386/lib/ddi_drv.c

Compare this file to the similar file:
Show the results in this format:

/* $Header: $ */

#define	_DDI_DKI	1
#define	_DDI_DKI_IMPL	1
#define	_SYSV3		1

/*
 * This file contains supplementary definitions used to deal with or aid the
 * implementation of the automatically generated device configuration code
 * in the "conf.c" file.
 *
 * Note that we are in the _SYSV3 world because we touch <sys/uproc.h>
 *
 * $Log: $
 */

#include <common/ccompat.h>
#include <common/xdebug.h>
#include <kernel/strmlib.h>
#include <sys/debug.h>
#include <sys/types.h>
#include <sys/cred.h>
#include <sys/cmn_err.h>
#include <sys/file.h>
#include <sys/open.h>
#include <sys/errno.h>
#include <sys/uio.h>
#include <sys/poll.h>
#include <stddef.h>

#include <sys/confinfo.h>
#include <kernel/ddi_base.h>

/*
 * These are Coherent header files! Treat with all the caution you would
 * normally use for handling toxic waste!
 *
 *	<sys/stat.h>
 *		major ()
 *		minor ()
 *	<sys/con.h>
 *		DFBLK
 *
 * Note that the actual magic u area variable 'u' is extern'ed in
 * <kernel/ddi_base.h>
 */

#include <sys/stat.h>
#include <sys/inode.h>

/*
 * Convert the broken Coherent file-mode flags to something sane.
 */

#if	__USE_PROTO__
int MAKE_MODE (int mode)
#else
int
MAKE_MODE (mode)
int		mode;
#endif
{
	int		newmode = 0;

	/*
	 * These are the flags documented by the Coherent driver kit. In
	 * actual fact, there are more (corresponding to the DDI/DKI flags)
	 * that are passed down from the system file table's flag entry. The
	 * fact that the others are not documented probably reflects the fact
	 * that calls to dread () either pass only IPR or IPW directly, while
	 * the existence of the other flags can only be discovered by tracing
	 * many layers of calls.
	 */

	if ((mode & IPR) != 0)
		newmode |= FREAD;
	if ((mode & IPW) != 0)
		newmode |= FWRITE;

	/*
	 * And the other flags.
	 */

	if ((mode & IPEXCL) != 0)
		newmode |= FEXCL;
	if ((mode & IPNDLY) != 0)
		newmode |= FNDELAY;
	if ((mode & IPNONBLOCK) != 0)
		newmode |= FNONBLOCK;

	return newmode;
}


/*
 * This local function is called to build a "uio_t" structure from Coherent's
 * UIO structure. This function would be local, but it is called by the
 * STREAMS equivalent of the mapping routines.
 */

#if	__USE_PROTO__
uio_t * (MAKE_UIO) (uio_t * uiop, iovec_t * iovp, int mode, IO * iop)
#else
uio_t *
MAKE_UIO __ARGS ((uiop, iovp, mode, iop))
uio_t	      *	uiop;
iovec_t	      *	iovp;
int		mode;
IO	      *	iop;
#endif
{
	uiop->uio_iov = iovp;
	uiop->uio_iovcnt = 1;
	uiop->uio_offset = iop->io_seek;
	uiop->uio_segflg = iop->io_seg == IOSYS ? UIO_SYSSPACE : UIO_USERSPACE;
	if ((iop->io_flag & IONDLY) != 0)
		mode |= FNDELAY;
	if ((iop->io_flag & IONONBLOCK) != 0)
		mode |= FNONBLOCK;
	uiop->uio_fmode = mode;
	uiop->uio_resid = iop->io_ioc;

#ifdef	_I386
	iovp->iov_base = iop->io.vbase;
#else
	iovp->iov_base = iop->io_base;
#endif
	iovp->iov_len = iop->io_ioc;

	return uiop;
}


/*
 * This function is used to copy back the information from a "uio_t" structure
 * into a Coherent IO structure.
 */

#if	__USE_PROTO__
void (DESTROY_UIO) (uio_t * uiop, IO * iop)
#else
void
DESTROY_UIO __ARGS ((uiop, iop))
uio_t	      *	uiop;
IO	      *	iop;
#endif
{
	ASSERT (uiop->uio_iov != NULL);
	ASSERT (uiop->uio_iov->iov_len == uiop->uio_resid);

	iop->io_ioc = uiop->uio_resid;
	iop->io_seek = uiop->uio_offset;
#ifdef	_I386
	iop->io.vbase = uiop->uio_iov->iov_base;
#else
	iop->io_base = uiop->uio_iov->iov_base;
#endif
}


/*
 * This function is called upon by the machine-generated code in "conf.c" to
 * forward a Coherent device open request to a System V device.
 */

#if	__USE_PROTO__
void (_forward_open) (o_dev_t dev, int mode, int flags, cred_t * credp,
		      struct inode ** inodepp, ddi_open_t funcp,
		      ddi_close_t closep)
#else
void
_forward_open __ARGS ((dev, mode, flags, credp, inodepp, funcp, closep))
o_dev_t		dev;
int		mode;
int		flags;
cred_t	      *	credp;
struct inode **	inodepp;
ddi_open_t	funcp;
ddi_close_t	closep;
#endif
{
	n_dev_t		newdev = makedevice (major (dev), minor (dev));
	o_dev_t		clonedev;
	struct inode  *	temp;

	/*
	 * Character devices do not specifically support clone semantics.
	 */

	if ((mode & IPCLONE) != 0) {
		set_user_error (ENXIO);
		return;
	}

	flags = (flags & DFBLK) != 0 ? OTYP_BLK : OTYP_CHR;

	set_user_error ((* funcp) (& newdev, MAKE_MODE (mode), flags, credp));

	clonedev = makedev (getemajor (newdev), geteminor (newdev));
	if (clonedev != dev)
		return;

	if ((temp = inode_clone (* inodepp, clonedev)) != NULL) {
		* inodepp = temp;
		return;
	}

	/*
	 * We are out of in-core inode space.
	 */

	if (closep != NULL)
		(* closep) (newdev, MAKE_MODE (mode), flags, credp);
}


/*
 * This function is called upon by the machine-generated code in "conf.c" to
 * forward a Coherent device close request to a System V device.
 */

#if	__USE_PROTO__
void (_forward_close) (o_dev_t dev, int mode, int flags, cred_t * credp,
		       ddi_close_t funcp)
#else
void
_forward_close __ARGS ((dev, mode, flags, credp, funcp))
o_dev_t		dev;
int		mode;
int		flags;
cred_t	      *	credp;
ddi_close_t	funcp;
#endif
{
	flags = (flags & DFBLK) != 0 ? OTYP_BLK : OTYP_CHR;

	set_user_error ((* funcp) (makedevice (major (dev), minor (dev)),
				   MAKE_MODE (mode), flags, credp));
}


/*
 * This function is called upon by the machine-generated code in "conf.c" to
 * forward a Coherent device read request to a System V device.
 */

#if	__USE_PROTO__
void (_forward_read) (o_dev_t dev, IO * iop, cred_t * credp,
		      ddi_read_t funcp)
#else
void
_forward_read __ARGS ((dev, iop, credp, funcp))
o_dev_t		dev;
IO	      *	iop;
cred_t	      *	credp;
ddi_read_t	funcp;
#endif
{
	iovec_t		iov;
	uio_t		uio;

	set_user_error ((* funcp) (makedevice (major (dev), minor (dev)),
				   MAKE_UIO (& uio, & iov, FREAD, iop),
				   credp));
	DESTROY_UIO (& uio, iop);
}


/*
 * This function is called upon by the machine-generated code in "conf.c" to
 * forward a Coherent device write request to a System V device.
 */

#if	__USE_PROTO__
void (_forward_write) (o_dev_t dev, IO * iop, cred_t * credp,
		       ddi_write_t funcp)
#else
void
_forward_write __ARGS ((dev, iop, credp, funcp))
o_dev_t		dev;
IO	      *	iop;
cred_t	      *	credp;
ddi_write_t	funcp;
#endif
{
	iovec_t		iov;
	uio_t		uio;

	set_user_error ((* funcp) (makedevice (major (dev), minor (dev)),
				   MAKE_UIO (& uio, & iov, FWRITE, iop),
				   credp));
	DESTROY_UIO (& uio, iop);
}


/*
 * This function is called upon by the machine-generated code in "conf.c" to
 * forward a Coherent device ioctl request to a System V device.
 */

#if	__USE_PROTO__
void (_forward_ioctl) (o_dev_t dev, int cmd, _VOID * arg, int mode,
		       cred_t * credp, int * rvalp, ddi_ioctl_t funcp)
#else
void
_forward_ioctl __ARGS ((dev, cmd, arg, mode, credp, rvalp, funcp))
o_dev_t		dev;
int		cmd;
_VOID	      *	arg;
int		mode;
cred_t	      *	credp;
int	      *	rvalp;
ddi_ioctl_t	funcp;
#endif
{
	set_user_error ((* funcp) (makedevice (major (dev), minor (dev)),
				   cmd, arg, mode, credp, rvalp));
}



#if 0
/*
 * This function is called upon by the machine-generated code in "conf.c" to
 * forward a Coherent device block request to a System V device.
 */

#if	__USE_PROTO__
int (_forward_strategy) (BUF * buf, ddi_strategy_t funcp)
#else
int
_forward_strategy __ARGS ((buf, funcp))
BUF	      *	buf;
ddi_strategy_t	funcp;
#endif
{
	cmn_err (CE_PANIC, "DDI/DKI block drivers not yet supported");
}
#endif


/*
 * This function is called upon by the machine-generated code in "conf.c" to
 * forward a Coherent device poll request to a System V device.
 */

#if	__USE_PROTO__
int (_forward_poll) (o_dev_t dev, int events, int msec, ddi_chpoll_t funcp)
#else
int
_forward_poll __ARGS ((dev, events, msec, funcp))
o_dev_t		dev;
int		events;
int		msec;
ddi_chpoll_t	funcp;
#endif
{
	short		revents;

	if (msec == 0) {
		/*
		 * Simply check to see what events are outstanding.
		 */

		set_user_error ((* funcp) (makedevice (major (dev),
						       minor (dev)),
					   events, 1, & revents, NULL));
		return revents;
	}

	set_user_error ((* funcp) (makedevice (major (dev), minor (dev)),
				   events, 0, & revents,
				   get_next_phpp (events)));
	install_phpp ();
	return revents;
}