1
0
Files
irix-657m-src/irix/kern/io/clone.c
2022-09-29 17:59:04 +03:00

131 lines
3.5 KiB
C

/* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
/* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */
/* All Rights Reserved */
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF */
/* UNIX System Laboratories, Inc. */
/* The copyright notice above does not evidence any */
/* actual or intended publication of such source code. */
/*#ident "@(#)uts-comm:io/clone/clone.c 1.4"*/
#ident "$Revision: 3.21 $"
/*
* Clone Driver.
*/
#include <sys/types.h>
#include <sys/conf.h>
#include <sys/errno.h>
#include <sys/mkdev.h>
#include <sys/param.h>
#include <sys/stream.h>
#include <sys/strsubr.h>
#include <sys/ddi.h>
/*
* The clone driver is intended for drivers which are not hwgraph-aware.
* hwgraph-aware drivers can implement similar functionality in other ways.
*/
int clnopen(queue_t *, dev_t *, int, int, struct cred *);
static struct module_info clnm_info = { 0, "CLONE", 0, 0, 0, 0 };
static struct qinit clnrinit = { NULL, NULL, clnopen, NULL, NULL, &clnm_info, NULL };
static struct qinit clnwinit = { NULL, NULL, NULL, NULL, NULL, &clnm_info, NULL };
int clndevflag = 0;
struct streamtab clninfo = { &clnrinit, &clnwinit };
/*
* clone_get_cdevsw is a support routine for clone devices which converts
* a clone dev_t into the actual cdevsw that it refers to.
*/
struct cdevsw *
clone_get_cdevsw(dev_t dev)
{
major_t maj, emaj;
if (!dev_is_vertex(dev)) {
emaj = getminor(dev);
maj = etoimajor(emaj);
if ((maj < cdevcnt) || ((maj < cdevmax) && cdevsw[maj].d_flags))
return(&cdevsw[maj]);
}
return(NULL);
}
/*
* Clone open. Maj is the major device number of the streams
* device to open. Look up the device in the cdevsw[]. Attach
* its qinit structures to the read and write queues and call its
* open with the sflag set to CLONEOPEN. Swap in a new vnode with
* the real device number constructed from either
* a) for old-style drivers:
* maj and the minor returned by the device open, or
* b) for new-style drivers:
* the whole dev passed back as a reference parameter
* from the device open.
*/
int
clnopen(queue_t *qp, dev_t *devp, int flag, int sflag, struct cred *crp)
{
register struct streamtab *stp;
dev_t newdev;
int error;
minor_t emaj;
struct cdevsw *my_cdevsw;
if (sflag)
return (ENXIO);
/*
* Get the device to open.
*/
my_cdevsw = clone_get_cdevsw(*devp);
/*
* If this is a dynamically loadable clone, call cdhold to increment
* the refcnt. This does the work of the cdhold call in qattach for
* a non-clone driver, so the non-error cdrele call is handled in
* mlqdetach for both clone and non-clone drivers.
*/
if (!cdvalid(my_cdevsw))
return (ENXIO);
if (*my_cdevsw->d_flags & D_OBSOLD)
return ENOTSUP;
if (error = cdhold(my_cdevsw))
return error;
if (!(stp = my_cdevsw->d_str)) {
cdrele (my_cdevsw);
return (ENXIO);
}
emaj = getminor(*devp); /* minor is major for a cloned drivers */
/*
* Substitute the real qinit values for the current ones.
*/
setq(qp, stp->st_rdinit, stp->st_wrinit);
/*
* Call the device open with the stream flag CLONEOPEN. The device
* will either fail this or return the whole device number
*/
newdev = makedevice(emaj, 0); /* create new style device number */
if (error = (*qp->q_qinfo->qi_qopen)(qp, &newdev, flag, CLONEOPEN, crp)) {
/* no cdrele() needed; cleaned up by qdetach/mlqdetach */
return (error);
}
my_cdevsw = get_cdevsw(newdev);
if (!cdvalid(my_cdevsw) || !(stp = my_cdevsw->d_str)) {
(*qp->q_qinfo->qi_qclose)(qp, flag, crp);
return (ENXIO);
}
*devp = newdev;
return (0);
}