File:  [DragonFly] / src / sys / net / i4b / driver / i4b_trace.c
Revision 1.9: download - view: text, annotated - select for diffs
Thu May 13 23:49:24 2004 UTC (10 years, 7 months ago) by dillon
Branches: MAIN
CVS tags: HEAD
device switch 1/many: Remove d_autoq, add d_clone (where d_autoq was).

d_autoq was used to allow the device port dispatch to mix old-style synchronous
calls with new style messaging calls within a particular device.  It was never
used for that purpose.

d_clone will be more fully implemented as work continues.  We are going to
install d_port in the dev_t (struct specinfo) structure itself and d_clone
will be needed to allow devices to 'revector' the port on a minor-number
by minor-number basis, in particular allowing minor numbers to be directly
dispatched to distinct threads.  This is something we will be needing later
on.

    1: /*
    2:  * Copyright (c) 1997, 2001 Hellmuth Michaelis. All rights reserved.
    3:  *
    4:  * Redistribution and use in source and binary forms, with or without
    5:  * modification, are permitted provided that the following conditions
    6:  * are met:
    7:  * 1. Redistributions of source code must retain the above copyright
    8:  *    notice, this list of conditions and the following disclaimer.
    9:  * 2. Redistributions in binary form must reproduce the above copyright
   10:  *    notice, this list of conditions and the following disclaimer in the
   11:  *    documentation and/or other materials provided with the distribution.
   12:  *
   13:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   14:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   15:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   16:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   17:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   18:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   19:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   20:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   21:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   22:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   23:  * SUCH DAMAGE.
   24:  *
   25:  *---------------------------------------------------------------------------
   26:  *
   27:  *	i4btrc - device driver for trace data read device
   28:  *	---------------------------------------------------
   29:  *
   30:  *	last edit-date: [Sat Aug 11 18:07:15 2001]
   31:  *
   32:  * $FreeBSD: src/sys/i4b/driver/i4b_trace.c,v 1.9.2.3 2001/08/12 16:22:48 hm Exp $
   33:  * $DragonFly: src/sys/net/i4b/driver/i4b_trace.c,v 1.9 2004/05/13 23:49:24 dillon Exp $
   34:  *
   35:  *	NOTE: the code assumes that SPLI4B >= splimp !
   36:  *
   37:  *---------------------------------------------------------------------------*/
   38: 
   39: #include "use_i4btrc.h"
   40: 
   41: #if NI4BTRC > 0
   42: 
   43: #include <sys/param.h>
   44: #include <sys/systm.h>
   45: 
   46: #if defined(__DragonFly__) || (defined(__FreeBSD__) && __FreeBSD__ >= 3)
   47: #include <sys/ioccom.h>
   48: #else
   49: #include <sys/ioctl.h>
   50: #endif
   51: 
   52: #include <sys/conf.h>
   53: #include <sys/uio.h>
   54: #include <sys/kernel.h>
   55: #include <sys/mbuf.h>
   56: #include <sys/socket.h>
   57: #include <net/if.h>
   58: #include <sys/tty.h>
   59: 
   60: #if defined(__DragonFly__) || defined(__FreeBSD__)
   61: 
   62: #ifdef DEVFS
   63: #include <sys/devfsext.h>
   64: #endif
   65: 
   66: #include <net/i4b/include/machine/i4b_trace.h>
   67: #include <net/i4b/include/machine/i4b_ioctl.h>
   68: 
   69: #else
   70: 
   71: #include <i4b/i4b_trace.h>
   72: #include <i4b/i4b_ioctl.h>
   73: 
   74: #endif
   75: 
   76: #include "../include/i4b_mbuf.h"
   77: #include "../include/i4b_global.h"
   78: #include "../include/i4b_l3l4.h"
   79: 
   80: #if !defined(__DragonFly__) && !defined(__FreeBSD__)
   81: #define	memcpy(d,s,l)	bcopy(s,d,l)
   82: #endif
   83: 
   84: static struct ifqueue trace_queue[NI4BTRC];
   85: static int device_state[NI4BTRC];
   86: #define ST_IDLE		0x00
   87: #define ST_ISOPEN	0x01
   88: #define ST_WAITDATA	0x02
   89: 
   90: #if defined(__FreeBSD__) && __FreeBSD__ == 3
   91: #ifdef DEVFS
   92: static void *devfs_token[NI4BTRC];
   93: #endif
   94: #endif
   95: 
   96: static int analyzemode = 0;
   97: static int rxunit = -1;
   98: static int txunit = -1;
   99: static int outunit = -1;
  100: 
  101: #if !defined(__DragonFly__) && !defined(__FreeBSD__)
  102: 
  103: #define	PDEVSTATIC	/* - not static - */
  104: void i4btrcattach (void);
  105: int i4btrcopen (dev_t dev, int flag, int fmt, struct proc *p);
  106: int i4btrcclose (dev_t dev, int flag, int fmt, struct proc *p);
  107: int i4btrcread (dev_t dev, struct uio * uio, int ioflag);
  108: 
  109: #ifdef __bsdi__
  110: int i4btrcioctl (dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p);
  111: #else
  112: int i4btrcioctl (dev_t dev, int cmd, caddr_t data, int flag, struct proc *p);
  113: #endif
  114: 
  115: #endif
  116: 
  117: #if defined(__DragonFly__) || (BSD > 199306 && defined(__FreeBSD__))
  118: #define	PDEVSTATIC static
  119: static d_open_t	i4btrcopen;
  120: static d_close_t i4btrcclose;
  121: static d_read_t i4btrcread;
  122: static d_ioctl_t i4btrcioctl;
  123: 
  124: #ifdef OS_USES_POLL
  125: static d_poll_t i4btrcpoll;
  126: #define POLLFIELD i4btrcpoll
  127: #else
  128: #define POLLFIELD noselect
  129: #endif
  130: 
  131: #define CDEV_MAJOR 59
  132: 
  133: static struct cdevsw i4btrc_cdevsw = {
  134:         /* name */      "i4btrc",
  135:         /* maj */       CDEV_MAJOR,
  136:         /* flags */     0,
  137: 	/* port */	NULL,
  138: 	/* clone */	NULL,
  139: 
  140: 	/* open */      i4btrcopen,
  141:         /* close */     i4btrcclose,
  142:         /* read */      i4btrcread,
  143:         /* write */     nowrite,
  144:         /* ioctl */     i4btrcioctl,
  145:         /* poll */      POLLFIELD,
  146:         /* mmap */      nommap,
  147:         /* strategy */  nostrategy,
  148:         /* dump */      nodump,
  149:         /* psize */     nopsize
  150: };
  151: 
  152: /*---------------------------------------------------------------------------*
  153:  *	interface init routine
  154:  *---------------------------------------------------------------------------*/
  155: static
  156: void i4btrcinit(void *unused)
  157: {
  158: 	cdevsw_add(&i4btrc_cdevsw);
  159: }
  160: 
  161: SYSINIT(i4btrcdev, SI_SUB_DRIVERS,
  162: 	SI_ORDER_MIDDLE+CDEV_MAJOR, &i4btrcinit, NULL);
  163: 
  164: static void i4btrcattach(void *);
  165: PSEUDO_SET(i4btrcattach, i4b_trace);
  166: 
  167: #endif /* BSD > 199306 && defined(__FreeBSD__) */
  168: 
  169: #ifdef __bsdi__
  170: #include <sys/device.h>
  171: int i4btrcmatch(struct device *parent, struct cfdata *cf, void *aux);
  172: void dummy_i4btrcattach(struct device*, struct device *, void *);
  173: 
  174: #define CDEV_MAJOR 60
  175: 
  176: static struct cfdriver i4btrccd =
  177: 	{ NULL, "i4btrc", i4btrcmatch, dummy_i4btrcattach, DV_DULL,
  178: 	  sizeof(struct cfdriver) };
  179: struct devsw i4btrcsw = 
  180: 	{ &i4btrccd,
  181: 	  i4btrcopen,	i4btrcclose,	i4btrcread,	nowrite,
  182: 	  i4btrcioctl,	seltrue,	nommap,		nostrat,
  183: 	  nodump,	nopsize,	0,		nostop
  184: };
  185: 
  186: int
  187: i4btrcmatch(struct device *parent, struct cfdata *cf, void *aux)
  188: {
  189: 	printf("i4btrcmatch: aux=0x%x\n", aux);
  190: 	return 1;
  191: }
  192: void
  193: dummy_i4btrcattach(struct device *parent, struct device *self, void *aux)
  194: {
  195: 	printf("dummy_i4btrcattach: aux=0x%x\n", aux);
  196: }
  197: #endif /* __bsdi__ */
  198: 
  199: int get_trace_data_from_l1(i4b_trace_hdr_t *hdr, int len, char *buf);
  200: 
  201: /*---------------------------------------------------------------------------*
  202:  *	interface attach routine
  203:  *---------------------------------------------------------------------------*/
  204: PDEVSTATIC void
  205: #if defined(__DragonFly__) || defined(__FreeBSD__)
  206: i4btrcattach(void *dummy)
  207: #else
  208: i4btrcattach()
  209: #endif
  210: {
  211: 	int i;
  212: 
  213: 	printf("i4btrc: %d ISDN trace device(s) attached\n", NI4BTRC);
  214: 	
  215: 	for(i=0; i < NI4BTRC; i++)
  216: 	{
  217: 
  218: #if defined(__DragonFly__) || defined(__FreeBSD__)
  219: 		make_dev(&i4btrc_cdevsw, i,
  220: 				     UID_ROOT, GID_WHEEL, 0600, "i4btrc%d", i);
  221: #endif
  222: 		trace_queue[i].ifq_maxlen = IFQ_MAXLEN;
  223: 
  224: #if defined(__FreeBSD__) && __FreeBSD__ > 4
  225: 		mtx_init(&trace_queue[i].ifq_mtx, "i4b_trace", MTX_DEF);
  226: #endif
  227: 		device_state[i] = ST_IDLE;
  228: 	}
  229: }
  230: 
  231: /*---------------------------------------------------------------------------*
  232:  *	get_trace_data_from_l1()
  233:  *	------------------------
  234:  *	is called from layer 1, adds timestamp to trace data and puts
  235:  *	it into a queue, from which it can be read from the i4btrc
  236:  *	device. The unit number in the trace header selects the minor
  237:  *	device's queue the data is put into.
  238:  *---------------------------------------------------------------------------*/
  239: int
  240: get_trace_data_from_l1(i4b_trace_hdr_t *hdr, int len, char *buf)
  241: {
  242: 	struct mbuf *m;
  243: 	int x;
  244: 	int unit;
  245: 	int trunc = 0;
  246: 	int totlen = len + sizeof(i4b_trace_hdr_t);
  247: 
  248: 	/*
  249: 	 * for telephony (or better non-HDLC HSCX mode) we get 
  250: 	 * (MCLBYTE + sizeof(i4b_trace_hdr_t)) length packets
  251: 	 * to put into the queue to userland. because of this
  252: 	 * we detect this situation, strip the length to MCLBYTES
  253: 	 * max size, and infor the userland program of this fact
  254: 	 * by putting the no of truncated bytes into hdr->trunc.
  255: 	 */
  256: 	 
  257: 	if(totlen > MCLBYTES)
  258: 	{
  259: 		trunc = 1;
  260: 		hdr->trunc = totlen - MCLBYTES;
  261: 		totlen = MCLBYTES;
  262: 	}
  263: 	else
  264: 	{
  265: 		hdr->trunc = 0;
  266: 	}
  267: 
  268: 	/* set length of trace record */
  269: 	
  270: 	hdr->length = totlen;
  271: 	
  272: 	/* check valid unit no */
  273: 	
  274: 	if((unit = hdr->unit) > NI4BTRC)
  275: 	{
  276: 		printf("i4b_trace: get_trace_data_from_l1 - unit > NI4BTRC!\n"); 
  277: 		return(0);
  278: 	}
  279: 
  280: 	/* get mbuf */
  281: 	
  282: 	if(!(m = i4b_Bgetmbuf(totlen)))
  283: 	{
  284: 		printf("i4b_trace: get_trace_data_from_l1 - i4b_getmbuf() failed!\n");
  285: 		return(0);
  286: 	}
  287: 
  288: 	/* check if we are in analyzemode */
  289: 	
  290: 	if(analyzemode && (unit == rxunit || unit == txunit))
  291: 	{
  292: 		if(unit == rxunit)
  293: 			hdr->dir = FROM_NT;
  294: 		else
  295: 			hdr->dir = FROM_TE;
  296: 		unit = outunit;			
  297: 	}
  298: 
  299: 	IF_LOCK(&trace_queue[unit]);
  300: 	if(_IF_QFULL(&trace_queue[unit]))
  301: 	{
  302: 		struct mbuf *m1;
  303: 
  304: 		x = SPLI4B();
  305: 		_IF_DEQUEUE(&trace_queue[unit], m1);
  306: 		splx(x);		
  307: 
  308: 		i4b_Bfreembuf(m1);
  309: 	}
  310: 	
  311: 	/* copy trace header */
  312: 	memcpy(m->m_data, hdr, sizeof(i4b_trace_hdr_t));
  313: 
  314: 	/* copy trace data */
  315: 	if(trunc)
  316: 		memcpy(&m->m_data[sizeof(i4b_trace_hdr_t)], buf, totlen-sizeof(i4b_trace_hdr_t));
  317: 	else
  318: 		memcpy(&m->m_data[sizeof(i4b_trace_hdr_t)], buf, len);
  319: 
  320: 	x = SPLI4B();
  321: 	
  322: 	_IF_ENQUEUE(&trace_queue[unit], m);
  323: 	IF_UNLOCK(&trace_queue[unit]);
  324: 	
  325: 	if(device_state[unit] & ST_WAITDATA)
  326: 	{
  327: 		device_state[unit] &= ~ST_WAITDATA;
  328: 		wakeup((caddr_t) &trace_queue[unit]);
  329: 	}
  330: 
  331: 	splx(x);
  332: 	
  333: 	return(1);
  334: }
  335: 
  336: /*---------------------------------------------------------------------------*
  337:  *	open trace device
  338:  *---------------------------------------------------------------------------*/
  339: PDEVSTATIC int
  340: i4btrcopen(dev_t dev, int flag, int fmt, struct thread *td)
  341: {
  342: 	int x;
  343: 	int unit = minor(dev);
  344: 
  345: 	if(unit >= NI4BTRC)
  346: 		return(ENXIO);
  347: 
  348: 	if(device_state[unit] & ST_ISOPEN)
  349: 		return(EBUSY);
  350: 
  351: 	if(analyzemode && (unit == outunit || unit == rxunit || unit == txunit))
  352: 		return(EBUSY);
  353: 
  354: 	x = SPLI4B();
  355: 	
  356: 	device_state[unit] = ST_ISOPEN;		
  357: 
  358: 	splx(x);
  359: 	
  360: 	return(0);
  361: }
  362: 
  363: /*---------------------------------------------------------------------------*
  364:  *	close trace device
  365:  *---------------------------------------------------------------------------*/
  366: PDEVSTATIC int
  367: i4btrcclose(dev_t dev, int flag, int fmt, struct thread *td)
  368: {
  369: 	int unit = minor(dev);
  370: 	int i, x;
  371: 	int cno = -1;
  372: 
  373: 	for(i=0; i < nctrl; i++)
  374: 	{
  375: 		if((ctrl_desc[i].ctrl_type == CTRL_PASSIVE) &&
  376: 			(ctrl_desc[i].unit == unit))
  377: 		{
  378: 			cno = i;
  379: 			break;
  380: 		}
  381: 	}
  382: 
  383: 	if(analyzemode && (unit == outunit))
  384: 	{
  385: 		analyzemode = 0;		
  386: 		outunit = -1;
  387: 		
  388: 		if(cno >= 0)
  389: 		{
  390: 			(*ctrl_desc[cno].N_MGMT_COMMAND)(rxunit, CMR_SETTRACE, TRACE_OFF);
  391: 			(*ctrl_desc[cno].N_MGMT_COMMAND)(txunit, CMR_SETTRACE, TRACE_OFF);
  392: 		}
  393: 		rxunit = -1;
  394: 		txunit = -1;
  395: 	}
  396: 	
  397: 	if(cno >= 0)
  398: 	{
  399: 			(*ctrl_desc[cno].N_MGMT_COMMAND)(ctrl_desc[cno].unit, CMR_SETTRACE, TRACE_OFF);
  400: 	}
  401: 
  402: 	x = SPLI4B();
  403: 	device_state[unit] = ST_IDLE;
  404: 	splx(x);
  405: 	
  406: 	return(0);
  407: }
  408: 
  409: /*---------------------------------------------------------------------------*
  410:  *	read from trace device
  411:  *---------------------------------------------------------------------------*/
  412: PDEVSTATIC int
  413: i4btrcread(dev_t dev, struct uio * uio, int ioflag)
  414: {
  415: 	struct mbuf *m;
  416: 	int x;
  417: 	int error = 0;
  418: 	int unit = minor(dev);
  419: 	
  420: 	if(!(device_state[unit] & ST_ISOPEN))
  421: 		return(EIO);
  422: 
  423: 	x = SPLI4B();
  424: 	
  425: 	IF_LOCK(&trace_queue[unit]);
  426: 	while(IF_QEMPTY(&trace_queue[unit]) && (device_state[unit] & ST_ISOPEN))
  427: 	{
  428: 		device_state[unit] |= ST_WAITDATA;
  429: 		
  430: #if defined (__FreeBSD__) && __FreeBSD__ > 4
  431: 		if((error = msleep((caddr_t) &trace_queue[unit],
  432: 					&trace_queue[unit].ifq_mtx,
  433: 					TTIPRI | PCATCH,
  434: 					"bitrc", 0 )) != 0)
  435: #else
  436: 		if((error = tsleep((caddr_t) &trace_queue[unit],
  437: 					PCATCH, "bitrc", 0 )) != 0)
  438: #endif                                                                                               
  439: 		{
  440: 			device_state[unit] &= ~ST_WAITDATA;
  441: 			IF_UNLOCK(&trace_queue[unit]);
  442: 			splx(x);
  443: 			return(error);
  444: 		}
  445: 	}
  446: 
  447: 	_IF_DEQUEUE(&trace_queue[unit], m);
  448: 	IF_UNLOCK(&trace_queue[unit]);
  449: 
  450: 	if(m && m->m_len)
  451: 		error = uiomove(m->m_data, m->m_len, uio);
  452: 	else
  453: 		error = EIO;
  454: 		
  455: 	if(m)
  456: 		i4b_Bfreembuf(m);
  457: 
  458: 	splx(x);
  459: 	
  460: 	return(error);
  461: }
  462: 
  463: #if (defined(__DragonFly__) || defined(__FreeBSD__)) && defined(OS_USES_POLL)
  464: /*---------------------------------------------------------------------------*
  465:  *	poll device
  466:  *---------------------------------------------------------------------------*/
  467: PDEVSTATIC int
  468: i4btrcpoll(dev_t dev, int events, struct thread *td)
  469: {
  470: 	return(ENODEV);
  471: }
  472: #endif
  473: 
  474: /*---------------------------------------------------------------------------*
  475:  *	device driver ioctl routine
  476:  *---------------------------------------------------------------------------*/
  477: PDEVSTATIC int
  478: #if defined(__DragonFly__) || (defined (__FreeBSD_version) && __FreeBSD_version >= 300003)
  479: i4btrcioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
  480: #elif defined(__bsdi__)
  481: i4btrcioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
  482: #else
  483: i4btrcioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
  484: #endif
  485: {
  486: 	int error = 0;
  487: 	int unit = minor(dev);
  488: 	i4b_trace_setupa_t *tsa;
  489: 	int i;
  490: 	int cno = -1;
  491: 
  492: 	/* find the first passive controller matching our unit no */
  493: 
  494: 	for(i=0; i < nctrl; i++)
  495: 	{
  496: 		if((ctrl_desc[i].ctrl_type == CTRL_PASSIVE) &&
  497: 			(ctrl_desc[i].unit == unit))
  498: 		{
  499: 			cno = i;
  500: 			break;
  501: 		}
  502: 	}
  503: 	
  504: 	switch(cmd)
  505: 	{
  506: 		case I4B_TRC_SET:
  507: 			if(cno < 0)
  508: 				return ENOTTY;
  509: 			(*ctrl_desc[cno].N_MGMT_COMMAND)(ctrl_desc[cno].unit, CMR_SETTRACE, (void *)*(unsigned int *)data);
  510: 			break;
  511: 
  512: 		case I4B_TRC_SETA:
  513: 			tsa = (i4b_trace_setupa_t *)data;
  514: 
  515: 			if(tsa->rxunit >= 0 && tsa->rxunit < NI4BTRC)
  516: 				rxunit = tsa->rxunit;
  517: 			else
  518: 				error = EINVAL;
  519: 
  520: 			if(tsa->txunit >= 0 && tsa->txunit < NI4BTRC)
  521: 				txunit = tsa->txunit;
  522: 			else
  523: 				error = EINVAL;
  524: 
  525: 			if(error)
  526: 			{
  527: 				outunit = -1;
  528: 				rxunit = -1;
  529: 				txunit = -1;
  530: 			}
  531: 			else
  532: 			{
  533: 				if(cno < 0)
  534: 					return ENOTTY;
  535: 					
  536: 				outunit = unit;
  537: 				analyzemode = 1;
  538: 				(*ctrl_desc[cno].N_MGMT_COMMAND)(rxunit, CMR_SETTRACE, (int *)(tsa->rxflags & (TRACE_I | TRACE_D_RX | TRACE_B_RX)));
  539: 				(*ctrl_desc[cno].N_MGMT_COMMAND)(txunit, CMR_SETTRACE, (int *)(tsa->txflags & (TRACE_I | TRACE_D_RX | TRACE_B_RX)));
  540: 			}
  541: 			break;
  542: 
  543: 		case I4B_TRC_RESETA:
  544: 			analyzemode = 0;		
  545: 			outunit = -1;
  546: 			rxunit = -1;
  547: 			txunit = -1;
  548: 			break;
  549: 			
  550: 		default:
  551: 			error = ENOTTY;
  552: 			break;
  553: 	}
  554: 	return(error);
  555: }
  556: 
  557: #endif /* NI4BTRC > 0 */