Coherent4.2.10/coh.386/lib/ddi_drv.c
/* $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;
}