⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 loop.c

📁 7号信令功能代码,为开源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*                               -*- Mode: C -*-  * loop.c --- Streams loopback driver, as of Sun manual  * Author          : Graham Wheeler * Created On      : Sat Oct  7 05:01:31 1995 * Last Modified By: David Grothe * RCS Id          : loop.c,v 1.1.1.2.8.1 2004/01/12 23:32:39 brian Exp * Purpose         : provide loopback streams driver * ----------------______________________________________________ * *    Copyright (C) 1995  Graham Wheeler, Francisco J. Ballesteros, *    Copyright (C) 1997  David Grothe, Gcom, Inc <dave@gcom.com> * * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. *  * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Library General Public License for more details. *  * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Cambridge, * MA 02139, USA. *  * *    You can reach us by email to any of *    gram@aztec.co.za, nemo@ordago.uc3m.es */#ident "@(#) LiS loop.c 2.23 10/23/03 21:23:58 "/*  -------------------------------------------------------------------  */#include <sys/stream.h>#include <sys/stropts.h>#include <linux/stat.h>		/* for S_IFCHR */#include <sys/osif.h>/*  -------------------------------------------------------------------  *//*			  Module definition structs                      *//* Module info for the loopback driver */static struct module_info loop_minfo = {    0,				/* id */    "loop",			/* name */    0,				/* min packet size accepted */    INFPSZ,			/* max packet size accepted */    10240L,			/* high water mark */    512L			/* low water mark */};/* These are the entry points to the driver: open, close, write side put and * service procedures and read side service procedure. */static int loop_open(queue_t *, dev_t *, int, int, cred_t *);static int loop_close(queue_t *, int, cred_t *);static int loop_wput(queue_t *, mblk_t *);static int loop_wsrv(queue_t *);static int loop_rsrv(queue_t *);/* qinit structures (rd and wr side)  */static struct qinit loop_rinit = {    NULL,			/* put */    loop_rsrv,			/* service  */    loop_open,			/* open */    loop_close,			/* close */    NULL,			/* admin */    &loop_minfo,		/* info */    NULL			/* stat */};static struct qinit loop_winit = {    loop_wput,			/* put */    loop_wsrv,			/* service  */    NULL,			/* open */    NULL,			/* close */    NULL,			/* admin */    &loop_minfo,		/* info */    NULL			/* stat */};/* streamtab for the loopback driver. */struct streamtab sloop_info = {    &loop_rinit,		/* read queue */    &loop_winit,		/* write queue */    NULL,			/* mux read queue  */    NULL			/* mux write queue */};/*  -------------------------------------------------------------------  *//*			    Module implementation                        */#include <sys/LiS/loop.h>/*  -------------------------------------------------------------------  */#define NLOOP 21		/* number of clone devs supported */struct loop			/* info for each loopback device */{    queue_t *qptr;    queue_t *oqptr;    int use_putnext;		/* instead of service queue */    int use_bufcall;		/* instead of putnext */    int msglvl;			/* # msgs to queue before sending upstream */    int msgcnt;			/* # msgs in the queue */    int timr;			/* time out amount while msgs queued */    toid_t timr_hndl;		/* for running timer */    int mark;			/* "mark" the next message(s) from above */    int minor_nr;		/* minor number of this instance */    int catlvl;			/* # msgs to concat before sending upstream */    int copy_bfr;		/* copy the message before looping */    mblk_t *saved_msg;		/* msg saved for contatenation */    char *copy_buf;		/* for copyin/out */    int copy_buf_size;		/* length of copy_buf data */    loop_xparent_t xp;		/* copied in from user space */    int deny_2nd_open;		/* deny a subsequent open of this minor */    int burst;			/* send a burst of messages upstream */};/* Arry.  w/ opened devices info & number of openened devices */static struct loop loop_loop[NLOOP];static int loop_cnt = NLOOP;/*  -------------------------------------------------------------------  */static void make_node(char *name, int maj, int mnr){    int rtn;    rtn = lis_unlink(name);    if (rtn < 0 && rtn != -ENOENT)    {	printk("unlink %s: error %d\n", name, rtn);	return ;    }    if (maj == 0)			/* don't make the node */    {	printk("unlink %s: OK\n", name);	return ;    }    rtn = lis_mknod(name, 0666 | S_IFCHR, MKDEV(maj, mnr));    if (rtn == 0)	printk("mknod %s: OK\n", name);    else	printk("mknod %s: error %d\n", name, rtn);}void sloop_init(void){    make_node("/dev/loop_clone", CLONE__CMAJOR_0, SLOOP__CMAJOR_0);    make_node("/dev/loop.1", SLOOP__CMAJOR_0, 1);    make_node("/dev/loop.2", SLOOP__CMAJOR_0, 2);    make_node("/dev/loop.9", SLOOP__CMAJOR_0, 9);    make_node("/dev/loop.255", SLOOP__CMAJOR_0, 255);}				/* loop_init */void sloop_term(void){    make_node("/dev/loop_clone", 0,0);    make_node("/dev/loop.1", 0,0);    make_node("/dev/loop.2", 0,0);    make_node("/dev/loop.9", 0,0);    make_node("/dev/loop.255", 0,0);}				/* loop_term *//*  -------------------------------------------------------------------  */static intloop_open(queue_t * q, dev_t * devp, int flag, int sflag, cred_t * credp){    struct loop *loop;    int          dev;    if (sflag == CLONEOPEN)    {	for (dev = 1; dev < loop_cnt; dev++)	{	    if (loop_loop[dev].qptr == NULL)		break;	}    }    else	dev = MINOR(*devp);    if (dev >= loop_cnt)	return -ENODEV;    loop = &loop_loop[dev];    *devp = MKDEV(MAJOR(*devp), dev);    if (q->q_ptr)		/* already open */    {	if (loop->deny_2nd_open)	    return -EBUSY;	return 0;		/* success */    }    WR(q)->q_ptr = (char *) loop;    q->q_ptr = (char *) loop;    loop->qptr = WR(q);    loop->minor_nr = dev;    MOD_INC_USE_COUNT;    return 0;			/* success */}/*  -------------------------------------------------------------------  */static void loop_timeout(caddr_t arg){    struct loop *loop = (struct loop *) arg;    if (loop->qptr != NULL)    {	enableok(WR(loop->qptr));	/* allow qenable to work */	qenable(WR(loop->qptr));    }}				/* loop_timeout *//*  -------------------------------------------------------------------  *//* * loop_bufcall * * Called from the STREAMS bufcall mechanism. * * The argument is a pointer to a queue to enable. */static void loop_bufcall(long q_ptr){    enableok((queue_t *) q_ptr);	/* allow qenable to work */    qenable((queue_t *) q_ptr);}				/* loop_bufcall *//*  -------------------------------------------------------------------  *//* * Concatenate the given message with the "saved" message in the * loop structure.  This allows the user to build multi-segment * messages that later get sent upstream. */static mblk_t *loop_concat(struct loop *loop, mblk_t * mp){    mblk_t *lastmp;    if (loop->saved_msg == NULL)    {	loop->saved_msg = mp;	return (mp);    }    for (lastmp = loop->saved_msg;	 lastmp->b_cont != NULL; lastmp = lastmp->b_cont)	;    lastmp->b_cont = mp;	/* hook new onto saved msg */    mp = loop->saved_msg;	/* mp becomes new concatenated msg */    loop->saved_msg = NULL;	/* no longer saved */    return (mp);		/* return entire message */}				/* loop_concat *//*  -------------------------------------------------------------------  */int loop_request_copyio(queue_t * wq, struct loop *loop, mblk_t * mp,			int msg_type, void *uptr, int nbytes){    struct copyreq *rq = (struct copyreq *) mp->b_rptr;    mblk_t *dp = mp->b_cont;    mp->b_wptr = mp->b_rptr + sizeof(*rq);    rq->cq_addr = uptr;    rq->cq_size = nbytes;    rq->cq_flag = 0;    rq->cq_private = (mblk_t *) loop;    if (dp != NULL && msg_type == M_COPYIN)    {	mp->b_cont = NULL;	/* discard data */	freemsg(dp);    }    mp->b_datap->db_type = msg_type;	/* M_COPYIN or M_COPYOUT */    qreply(wq, mp);    return (0);}				/* loop_request_copyio *//*  -------------------------------------------------------------------  */int loop_iocdata(queue_t * wq, mblk_t * mp){    struct copyresp *rsp = (struct copyresp *) mp->b_rptr;    struct loop *loop = (struct loop *) rsp->cp_private;    struct iocblk *iocb;    iocb = (struct iocblk *) rsp;    switch (rsp->cp_cmd)    {    case LOOP_XPARENT_COPYIN:    case LOOP_XPARENT_COPYOUT:	{	    mblk_t *dp;	    dp = mp->b_cont;	    if (rsp->cp_rval != 0)	    {		printk("loop_iocdata: copyin request failed\n");		return (-EINVAL);	    }	    if (dp == NULL || dp->b_datap->db_type != M_DATA)	    {		printk("loop_iocdata: attached bfr NULL or not M_DATA\n");		return (-EINVAL);	    }	    if (msgdsize(dp) != sizeof(loop_xparent_t))	    {		printk("loop_iocdata: expected %d bytes, got %d\n",		       sizeof(loop_xparent_t), msgdsize(dp));		return (-EINVAL);	    }	    loop->xp = *((loop_xparent_t *) dp->b_rptr);	    mp->b_cont = NULL;	    freemsg(dp);	    /*	     * If we fetched the xparent struct for a copy in then issue	     * another copy in for the actual data from user space.	     * If it was for a copy out then return the requested data	     * in an M_DATA and request it to be copied out to the user's	     * space.	     *	     * Alter the command by oring in an 0xf00 so that when the	     * iocdata for these requests comes down we can tell that	     * they are for the final copy functions.  Handled in separate	     * cases below.	     */	    switch (rsp->cp_cmd)	    {	    case LOOP_XPARENT_COPYIN:		rsp->cp_cmd |= 0xf00;	/* alter the command */		if (loop_request_copyio(wq, loop, mp, M_COPYIN,					loop->xp.p_arg, loop->xp.i_arg) < 0)		{		    printk("loop_iocdata: loop_request_copyio failed\n");		    return (-EINVAL);		}		return (1);	/* keep exchanging msgs w/strm hd */	    case LOOP_XPARENT_COPYOUT:		if (loop->copy_buf == NULL)		    return (-EINVAL);		if (loop->copy_buf_size < loop->xp.i_arg)		    loop->xp.i_arg = loop->copy_buf_size;		dp = allocb(loop->xp.i_arg, BPRI_LO);		if (dp == NULL)		    return (-ENOMEM);		memcpy(dp->b_wptr, loop->copy_buf, loop->xp.i_arg);		dp->b_wptr += loop->xp.i_arg;		linkb(mp, dp);		rsp->cp_cmd |= 0xf00;	/* alter the command */		if (loop_request_copyio(wq, loop, mp, M_COPYOUT,					loop->xp.p_arg, loop->xp.i_arg) < 0)		{		    printk("loop_iocdata: loop_request_copyio failed\n");		    return (-EINVAL);		}		return (1);	/* keep exchanging msgs w/strm hd */	    }	    break;	}	/*	 * This is the actual data that the user wanted us to copy in.	 */    case LOOP_XPARENT_COPYIN | 0xf00:	{	    mblk_t *dp;	    dp = mp->b_cont;	    if (rsp->cp_rval != 0)	    {		printk("loop_iocdata: copyin request failed\n");		return (-EINVAL);	    }	    if (dp == NULL || dp->b_datap->db_type != M_DATA)	    {		printk("loop_iocdata: attached bfr NULL or not M_DATA\n");		return (-EINVAL);	    }	    if (msgdsize(dp) != loop->xp.i_arg)	    {		printk("loop_iocdata: expected %d bytes, got %d\n",		       loop->xp.i_arg, msgdsize(dp));		return (-1);	    }	    if (loop->copy_buf != NULL)		FREE(loop->copy_buf);	    loop->copy_buf = MALLOC(loop->xp.i_arg);	    if (loop->copy_buf == NULL)		return (-ENOMEM);	    memcpy(loop->copy_buf, dp->b_rptr, loop->xp.i_arg);	    loop->copy_buf_size = loop->xp.i_arg;	    return (0);		/* send iocack now */	}	/*	 * This is the result of copying out data to the user.	 */    case LOOP_XPARENT_COPYOUT | 0xf00:	{	    if (rsp->cp_rval != 0)	    {		printk("loop_iocdata: copyin request failed\n");		return (-EINVAL);	    }	    return (0);		/* send iocack now */	}    default:	printk("loop_iocdata: cmd=0x%x unknown\n", rsp->cp_cmd);	return (-EINVAL);    }    return (0);}				/* loop_iocdata *//*  -------------------------------------------------------------------  */static int loop_wput(queue_t * q, mblk_t * mp){    struct loop *loop;    int rtn_count = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -