📄 mtdrv.c
字号:
/************************************************************************* Multi-Threaded Test Driver *************************************************************************** ** Used to test the multi-threaded aspects of driver opens. This is ** a separately loadable driver which is only loaded when strtst is run. ** *************************************************************************//* * * 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. * */#ident "@(#) LiS mtdrv.c 1.2 05/14/03"/* ------------------------------------------------------------------- */#include <linux/config.h>#include <linux/version.h>#ifdef CONFIG_MODVERSIONS#include <linux/modversions.h>#endif#include <linux/module.h>#include <sys/stream.h>#include <sys/stropts.h>#include <linux/stat.h> /* for S_IFCHR */#include <sys/osif.h>#include <sys/LiS/mtdrv.h>/************************************************************************* Module Definition Structs *************************************************************************/static struct module_info mtdrv_minfo = { 0, /* id */ "mtdrv", /* 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 mtdrv_open(queue_t *, dev_t *, int, int, cred_t *);static int mtdrv_close(queue_t *, int, cred_t *);static int mtdrv_wput(queue_t *, mblk_t *);static int mtdrv_wsrv(queue_t *);static int mtdrv_rsrv(queue_t *);/* qinit structures (rd and wr side) */static struct qinit mtdrv_rinit = { NULL, /* put */ mtdrv_rsrv, /* service */ mtdrv_open, /* open */ mtdrv_close, /* close */ NULL, /* admin */ &mtdrv_minfo, /* info */ NULL /* stat */};static struct qinit mtdrv_winit = { mtdrv_wput, /* put */ mtdrv_wsrv, /* service */ NULL, /* open */ NULL, /* close */ NULL, /* admin */ &mtdrv_minfo, /* info */ NULL /* stat */};/* streamtab for the driver. */struct streamtab mtdrv_info = { &mtdrv_rinit, /* read queue */ &mtdrv_winit, /* write queue */ NULL, /* mux read queue */ NULL /* mux write queue */};/************************************************************************* Global Storage *************************************************************************/static int next_clone_dev ;static int open_sleep_time ;static lis_semaphore_t *open_sleep_sem ;static int mtdrv_major ; /* from registration */static lis_semaphore_t *open_sem ;#define N_DEVS 20static char devs[N_DEVS] ;/************************************************************************* Prototypes *************************************************************************/static void mtdrv_timeout(caddr_t arg) ;/************************************************************************* Functions *************************************************************************/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 mtdrv_init(int maj){ make_node("/dev/mtdrv_clone", CLONE__CMAJOR_0, maj); make_node("/dev/mtdrv.1", maj, 1); make_node("/dev/mtdrv.2", maj, 2); make_node("/dev/mtdrv.3", maj, 3); make_node("/dev/mtdrv.4", maj, 4); open_sleep_sem = lis_sem_alloc(0) ; open_sem = lis_sem_alloc(1) ;} /* mtdrv_init */void mtdrv_term(void){ open_sleep_sem = lis_sem_destroy(open_sleep_sem) ; open_sem = lis_sem_destroy(open_sem) ; make_node("/dev/mtdrv_clone", 0,0); make_node("/dev/mtdrv.1", 0,0); make_node("/dev/mtdrv.2", 0,0); make_node("/dev/mtdrv.3", 0,0); make_node("/dev/mtdrv.4", 0,0);} /* mtdrv_term *//* ------------------------------------------------------------------- */static intmtdrv_open(queue_t * q, dev_t * devp, int flag, int sflag, cred_t * credp){ int dev; printk("mtdrv_open: flag=0x%x sflag=0x%x\n", flag, sflag) ; lis_down(open_sem) ; if (sflag == CLONEOPEN) { if (next_clone_dev) { dev = next_clone_dev ; next_clone_dev = 0 ; if (dev >= sizeof(devs)) { lis_up(open_sem) ; return(-EINVAL) ; } } else { for (dev = 1; dev < sizeof(devs); dev++) if (devs[dev] == 0) break ; if (dev >= sizeof(devs)) { lis_up(open_sem) ; return(-EBUSY) ; } } } else dev = MINOR(*devp); MOD_INC_USE_COUNT; devs[dev]++ ; /* must be protected by semaphore */ lis_up(open_sem) ; q->q_ptr = (void *) &devs[dev] ; *devp = MKDEV(MAJOR(*devp), dev); printk("mtdrv_open: dev=%d\n", dev) ; if (open_sleep_time > 0) { timeout(mtdrv_timeout, (caddr_t) 0, open_sleep_time); open_sleep_time = 0 ; lis_down(open_sleep_sem) ; } return 0; /* success */}/* ------------------------------------------------------------------- */static void mtdrv_timeout(caddr_t arg){ lis_up(open_sleep_sem) ;} /* mtdrv_timeout *//* ------------------------------------------------------------------- */static void mtdrv_ioctl(queue_t * q, mblk_t * mp){ struct iocblk *iocb; int error; int rtn_count = 0 ; iocb = (struct iocblk *) mp->b_rptr; /* * Syntax switch */ switch (iocb->ioc_cmd) { case MTDRV_SET_CLONE_DEV: case MTDRV_SET_OPEN_SLEEP: if (mp->b_cont == NULL) { printk("mtdrv_ioctl: integer argument expected\n") ; error = EINVAL ; goto iocnak; } if (iocb->ioc_count != sizeof(int)) { printk("mtdrv_ioctl: expected ioctl len %d, got %d\n", sizeof(int), iocb->ioc_count); error = EINVAL; goto iocnak; } break ; default: printk("mtdrv_ioctl: Invalid ioctl: %x\n", iocb->ioc_cmd); error = EINVAL; goto iocnak ; iocnak: { mp->b_datap->db_type = M_IOCNAK; iocb->ioc_error = error; qreply(q, mp); } return ; } /* end of switch on ioc_cmd */ /* * Semantics switch */ switch (iocb->ioc_cmd) { case MTDRV_SET_CLONE_DEV: next_clone_dev = *(int *) mp->b_cont->b_rptr; break ; case MTDRV_SET_OPEN_SLEEP: open_sleep_time = *(int *) mp->b_cont->b_rptr; break ; } /* end of switch on ioc_cmd */ mp->b_datap->db_type = M_IOCACK; iocb->ioc_count = rtn_count; iocb->ioc_error = 0; qreply(q, mp);}/* ------------------------------------------------------------------- */static int mtdrv_wput(queue_t * q, mblk_t * mp){ switch (mp->b_datap->db_type) { case M_IOCTL: mtdrv_ioctl(q, mp) ; return(0) ; case M_FLUSH: if (*mp->b_rptr & FLUSHW) flushq(q, FLUSHDATA); if (*mp->b_rptr & FLUSHR) { flushq(RD(q), FLUSHDATA); *mp->b_rptr &= ~FLUSHW; qreply(q, mp); } else freemsg(mp); return(0) ; default: break; } freemsg(mp) ; return (0);}/* ------------------------------------------------------------------- */static int mtdrv_wsrv(queue_t * q){ return (0);}/* ------------------------------------------------------------------- */static int mtdrv_rsrv(queue_t * q){ return (0);}/* ------------------------------------------------------------------- */static int mtdrv_close(queue_t * q, int dummy, cred_t * credp){ char *devp = (char *) q->q_ptr ; while (devp != NULL && *devp) { MOD_DEC_USE_COUNT; (*devp)-- ; } return (0);}#ifdef MODULEint init_module(void){ int ret = lis_register_strdev(0, &mtdrv_info, 10, "mtdrv"); if (ret < 0) { printk("mtdrv.init_module: Unable to register driver.\n"); return ret; } mtdrv_major = ret ; mtdrv_init(mtdrv_major) ; return 0;}void cleanup_module(void){ mtdrv_term() ; if (lis_unregister_strdev(mtdrv_major) < 0) printk("mtdrv.cleanup_module: Unable to unregister driver.\n"); else printk("mtdrv.cleanup_module: Unregistered, ready to be unloaded.\n"); return;}#if defined(MODULE_LICENSE)MODULE_LICENSE("GPL and additional rights");#endif#if defined(MODULE_AUTHOR)MODULE_AUTHOR("David Grothe");#endif#if defined(MODULE_DESCRIPTION)MODULE_DESCRIPTION("multi-threaded open test helper driver");#endif#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -