File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / ntp / libparse / parsesolaris.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue May 29 12:08:38 2012 UTC (12 years ago) by misho
Branches: ntp, MAIN
CVS tags: v4_2_6p5p0, v4_2_6p5, HEAD
ntp 4.2.6p5

    1: /*
    2:  * /src/NTP/ntp4-dev/libparse/parsesolaris.c,v 4.11 2005/04/16 17:32:10 kardel RELEASE_20050508_A
    3:  *  
    4:  * parsesolaris.c,v 4.11 2005/04/16 17:32:10 kardel RELEASE_20050508_A
    5:  *
    6:  * STREAMS module for reference clocks
    7:  *
    8:  * Copyright (c) 1995-2005 by Frank Kardel <kardel <AT> ntp.org>
    9:  * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universität Erlangen-Nürnberg, Germany
   10:  *
   11:  * Redistribution and use in source and binary forms, with or without
   12:  * modification, are permitted provided that the following conditions
   13:  * are met:
   14:  * 1. Redistributions of source code must retain the above copyright
   15:  *    notice, this list of conditions and the following disclaimer.
   16:  * 2. Redistributions in binary form must reproduce the above copyright
   17:  *    notice, this list of conditions and the following disclaimer in the
   18:  *    documentation and/or other materials provided with the distribution.
   19:  * 3. Neither the name of the author nor the names of its contributors
   20:  *    may be used to endorse or promote products derived from this software
   21:  *    without specific prior written permission.
   22:  *
   23:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   24:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   25:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   26:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   27:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   28:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   29:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   31:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   32:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   33:  * SUCH DAMAGE.
   34:  *
   35:  */
   36: 
   37: #define _KERNEL			/* it is a _KERNEL module */
   38: 
   39: #ifndef lint
   40: static char rcsid[] = "parsesolaris.c,v 4.11 2005/04/16 17:32:10 kardel RELEASE_20050508_A";
   41: #endif
   42: 
   43: #include <sys/types.h>
   44: #include <sys/conf.h>
   45: #include <sys/errno.h>
   46: #include <sys/time.h>
   47: #include <sys/termios.h>
   48: #include <sys/stream.h>
   49: #include <sys/strtty.h>
   50: #include <sys/stropts.h>
   51: #include <sys/modctl.h>
   52: #include <sys/ddi.h>
   53: #include <sys/sunddi.h>
   54: #ifdef __GNUC__ /* makes it compile on Solaris 2.6 - acc doesn't like it -- GREAT! */
   55: #include <stdarg.h>
   56: #endif
   57: 
   58: #include "ntp_fp.h"
   59: #include "parse.h"
   60: #include <sys/parsestreams.h>
   61: 
   62: /*--------------- loadable driver section -----------------------------*/
   63: 
   64: static struct streamtab parseinfo;
   65: 
   66: static struct fmodsw fmod_templ =
   67: {
   68: 	"parse",			/* module name */
   69: 	&parseinfo,			/* module information */
   70: 	D_NEW|D_MP|D_MTQPAIR,		/* exclusive for q pair */
   71: 	/* lock ptr */
   72: };
   73: 
   74: extern struct mod_ops mod_strmodops;
   75: 
   76: static struct modlstrmod modlstrmod = 
   77: {
   78: 	&mod_strmodops,		/* a STREAMS module */
   79: 	"PARSE      - NTP reference",	/* name this baby - keep room for revision number */
   80: 	&fmod_templ
   81: };
   82: 
   83: static struct modlinkage modlinkage =
   84: {
   85: 	MODREV_1,
   86: 	{
   87: 		&modlstrmod,
   88: 		NULL
   89: 	}
   90: };
   91: 
   92: /*
   93:  * module management routines
   94:  */
   95: /*ARGSUSED*/
   96: int
   97: _init(
   98:      void
   99:      )
  100: {
  101: 	static char revision[] = "4.6";
  102: 	char *s, *S; 
  103: 	char *t;
  104:   
  105: #ifndef lint
  106: 	t = rcsid;
  107: #endif
  108: 	
  109: 	/*
  110: 	 * copy RCS revision into Drv_name
  111: 	 *
  112: 	 * are we forcing RCS here to do things it was not built for ?
  113: 	 */
  114: 	s = revision;
  115: 	if (*s == '$')
  116: 	{
  117: 		/*
  118: 		 * skip "$Revision: "
  119: 		 * if present. - not necessary on a -kv co (cvs export)
  120: 		 */
  121: 		while (*s && (*s != ' '))
  122: 		{
  123: 			s++;
  124: 		}
  125: 		if (*s == ' ') s++;
  126: 	}
  127: 	  
  128: 	t = modlstrmod.strmod_linkinfo; 
  129: 	while (*t && (*t != ' '))
  130: 	{
  131: 		t++;
  132: 	}
  133: 	if (*t == ' ') t++;
  134: 	  
  135: 	S = s;
  136: 	while (*S && (((*S >= '0') && (*S <= '9')) || (*S == '.')))
  137: 	{
  138: 		S++;
  139: 	}
  140: 	  
  141: 	if (*s && *t && (S > s))
  142: 	{
  143: 		if (strlen(t) >= (S - s))
  144: 		{
  145: 			(void) strncpy(t, s, (unsigned)(S - s));
  146: 		}
  147: 	}
  148: 	return (mod_install(&modlinkage));
  149: }
  150: 
  151: /*ARGSUSED*/
  152: int
  153: _info(
  154:       struct modinfo *modinfop
  155:       )
  156: {
  157: 	return (mod_info(&modlinkage, modinfop));
  158: }
  159: 
  160: /*ARGSUSED*/
  161: int
  162: _fini(
  163:       void
  164:       )
  165: {
  166: 	if (mod_remove(&modlinkage) != DDI_SUCCESS)
  167: 	{
  168: 		return EBUSY;
  169: 	}
  170: 	else
  171: 	    return DDI_SUCCESS;
  172: }
  173: 
  174: /*--------------- stream module definition ----------------------------*/
  175: 
  176: static int parseopen  (queue_t *, dev_t *, int, int, cred_t *);
  177: static int parseclose (queue_t *, int);
  178: static int parsewput  (queue_t *, mblk_t *);
  179: static int parserput  (queue_t *, mblk_t *);
  180: static int parsersvc  (queue_t *);
  181: 
  182: static struct module_info driverinfo =
  183: {
  184: 	0,				/* module ID number */
  185: 	fmod_templ.f_name,		/* module name - why repeated here ? compat ?*/
  186: 	0,				/* minimum accepted packet size */
  187: 	INFPSZ,				/* maximum accepted packet size */
  188: 	1,				/* high water mark - flow control */
  189: 	0				/* low water mark - flow control */
  190: };
  191: 
  192: static struct qinit rinit =	/* read queue definition */
  193: {
  194: 	parserput,			/* put procedure */
  195: 	parsersvc,			/* service procedure */
  196: 	parseopen,			/* open procedure */
  197: 	parseclose,			/* close procedure */
  198: 	NULL,				/* admin procedure - NOT USED FOR NOW */
  199: 	&driverinfo,			/* information structure */
  200: 	NULL				/* statistics */
  201: };
  202: 
  203: static struct qinit winit =	/* write queue definition */
  204: {
  205: 	parsewput,			/* put procedure */
  206: 	NULL,				/* service procedure */
  207: 	NULL,				/* open procedure */
  208: 	NULL,				/* close procedure */
  209: 	NULL,				/* admin procedure - NOT USED FOR NOW */
  210: 	&driverinfo,			/* information structure */
  211: 	NULL				/* statistics */
  212: };
  213: 
  214: static struct streamtab parseinfo =	/* stream info element for parse driver */
  215: {
  216: 	&rinit,			/* read queue */
  217: 	&winit,			/* write queue */
  218: 	NULL,				/* read mux */
  219: 	NULL				/* write mux */
  220: };
  221: 
  222: /*--------------- driver data structures ----------------------------*/
  223: 
  224: /*
  225:  * we usually have an inverted signal - but you
  226:  * can change this to suit your needs
  227:  */
  228: int cd_invert = 1;		/* invert status of CD line - PPS support via CD input */
  229: 
  230: #ifdef PARSEDEBUG
  231: int parsedebug = ~0;
  232: #else
  233: int parsedebug = 0;
  234: #endif
  235: 
  236: /*--------------- module implementation -----------------------------*/
  237: 
  238: #define TIMEVAL_USADD(_X_, _US_) do {\
  239: 	(_X_)->tv_usec += (_US_);\
  240: 	if ((_X_)->tv_usec >= 1000000)\
  241: 	{\
  242: 	    (_X_)->tv_sec++;\
  243: 	    (_X_)->tv_usec -= 1000000;\
  244: 	}\
  245:      } while (0)
  246: 
  247: static int init_linemon (queue_t *);
  248: static void close_linemon (queue_t *, queue_t *);
  249: 
  250: #define M_PARSE		0x0001
  251: #define M_NOPARSE	0x0002
  252: 
  253: void
  254: ntp_memset(
  255: 	char *a,
  256: 	int x,
  257: 	int c
  258: 	)
  259: {
  260: 	while (c-- > 0)
  261: 	    *a++ = x;
  262: }
  263: 
  264: static void
  265: pprintf(
  266: 	int lev,
  267: 	char *form,
  268: 	...
  269: 	)
  270: {
  271: 	va_list ap;
  272: 
  273: 	va_start(ap, form);
  274: 
  275: 	if (lev & parsedebug)
  276: 		vcmn_err(CE_CONT, form, ap);
  277: 
  278: 	va_end(ap);
  279: }
  280: 
  281: static int
  282: setup_stream(
  283: 	     queue_t *q,
  284: 	     int mode
  285: 	     )
  286: {
  287: 	register mblk_t *mp;
  288: 
  289: 	pprintf(DD_OPEN,"parse: SETUP_STREAM - setting up stream for q=%x\n", q);
  290: 
  291: 	mp = allocb(sizeof(struct stroptions), BPRI_MED);
  292: 	if (mp)
  293: 	{
  294: 		struct stroptions *str = (struct stroptions *)mp->b_wptr;
  295: 
  296: 		str->so_flags   = SO_READOPT|SO_HIWAT|SO_LOWAT|SO_ISNTTY;
  297: 		str->so_readopt = (mode == M_PARSE) ? RMSGD : RNORM;
  298: 		str->so_hiwat   = (mode == M_PARSE) ? sizeof(parsetime_t) : 256;
  299: 		str->so_lowat   = 0;
  300: 		mp->b_datap->db_type = M_SETOPTS;
  301: 		mp->b_wptr     += sizeof(struct stroptions);
  302: 		if (!q)
  303: 		    panic("NULL q - strange");
  304: 		putnext(q, mp);
  305: 		return putctl1(WR(q)->q_next, M_CTL, (mode == M_PARSE) ? MC_SERVICEIMM :
  306: 			       MC_SERVICEDEF);
  307: 	}
  308: 	else
  309: 	{
  310: 		pprintf(DD_OPEN, "parse: setup_stream - FAILED - no MEMORY for allocb\n"); 
  311: 		return 0;
  312: 	}
  313: }
  314: 
  315: /*ARGSUSED*/
  316: static int
  317: parseopen(
  318: 	  queue_t *q,
  319: 	  dev_t *dev,
  320: 	  int flag,
  321: 	  int sflag,
  322: 	  cred_t *credp
  323: 	  )
  324: {
  325: 	register parsestream_t *parse;
  326: 	static int notice = 0;
  327:   
  328: 	pprintf(DD_OPEN, "parse: OPEN - q=%x\n", q); 
  329:   
  330: 	if (sflag != MODOPEN)
  331: 	{			/* open only for modules */
  332: 		pprintf(DD_OPEN, "parse: OPEN - FAILED - not MODOPEN\n"); 
  333: 		return EIO;
  334: 	}
  335: 
  336: 	if (q->q_ptr != (caddr_t)NULL)
  337: 	{
  338: 		pprintf(DD_OPEN, "parse: OPEN - FAILED - EXCLUSIVE ONLY\n"); 
  339: 		return EBUSY;
  340: 	}
  341: 
  342: 	q->q_ptr = (caddr_t)kmem_alloc(sizeof(parsestream_t), KM_SLEEP);
  343: 	if (q->q_ptr == (caddr_t)0)
  344: 	{
  345: 		return ENOMEM;
  346: 	}
  347: 
  348: 	pprintf(DD_OPEN, "parse: OPEN - parse area q=%x, q->q_ptr=%x\n", q, q->q_ptr); 
  349: 	WR(q)->q_ptr = q->q_ptr;
  350: 	pprintf(DD_OPEN, "parse: OPEN - WQ parse area q=%x, q->q_ptr=%x\n", WR(q), WR(q)->q_ptr); 
  351:   
  352: 	parse = (parsestream_t *) q->q_ptr;
  353: 	bzero((caddr_t)parse, sizeof(*parse));
  354: 	parse->parse_queue     = q;
  355: 	parse->parse_status    = PARSE_ENABLE;
  356: 	parse->parse_ppsclockev.tv.tv_sec  = 0;
  357: 	parse->parse_ppsclockev.tv.tv_usec = 0;
  358: 	parse->parse_ppsclockev.serial     = 0;
  359: 
  360: 	qprocson(q);
  361: 
  362: 	pprintf(DD_OPEN, "parse: OPEN - initializing io subsystem q=%x\n", q); 
  363: 
  364: 	if (!parse_ioinit(&parse->parse_io))
  365: 	{
  366: 		/*
  367: 		 * ok guys - beat it
  368: 		 */
  369: 		qprocsoff(q);
  370: 
  371: 		kmem_free((caddr_t)parse, sizeof(parsestream_t));
  372: 
  373: 		return EIO;
  374: 	}
  375: 
  376: 	pprintf(DD_OPEN, "parse: OPEN - initializing stream q=%x\n", q); 
  377: 
  378: 	if (setup_stream(q, M_PARSE))
  379: 	{
  380: 		(void) init_linemon(q);	/* hook up PPS ISR routines if possible */
  381: 		pprintf(DD_OPEN, "parse: OPEN - SUCCEEDED\n"); 
  382: 
  383: 		/*
  384: 		 * I know that you know the delete key, but you didn't write this
  385: 		 * code, did you ? - So, keep the message in here.
  386: 		 */
  387: 		if (!notice)
  388: 		{
  389: 		  cmn_err(CE_CONT, "?%s: Copyright (c) 1993-2005, Frank Kardel\n", modlstrmod.strmod_linkinfo);
  390: 			notice = 1;
  391: 		}
  392: 
  393: 		return 0;
  394: 	}
  395: 	else
  396: 	{
  397: 		qprocsoff(q);
  398: 
  399: 		kmem_free((caddr_t)parse, sizeof(parsestream_t));
  400: 
  401: 		return EIO;
  402: 	}
  403: }
  404: 
  405: /*ARGSUSED*/
  406: static int
  407: parseclose(
  408: 	   queue_t *q,
  409: 	   int flags
  410: 	   )
  411: {
  412: 	register parsestream_t *parse = (parsestream_t *)q->q_ptr;
  413: 	register unsigned long s;
  414:   
  415: 	pprintf(DD_CLOSE, "parse: CLOSE\n");
  416:   
  417: 	qprocsoff(q);
  418: 
  419: 	s = splhigh();
  420:   
  421: 	if (parse->parse_dqueue)
  422: 	    close_linemon(parse->parse_dqueue, q);
  423: 	parse->parse_dqueue = (queue_t *)0;
  424: 
  425: 	(void) splx(s);
  426:       
  427: 	parse_ioend(&parse->parse_io);
  428: 
  429: 	kmem_free((caddr_t)parse, sizeof(parsestream_t));
  430: 
  431: 	q->q_ptr = (caddr_t)NULL;
  432: 	WR(q)->q_ptr = (caddr_t)NULL;
  433: 
  434: 	return 0;
  435: }
  436: 
  437: /*
  438:  * move unrecognized stuff upward
  439:  */
  440: static int
  441: parsersvc(
  442: 	  queue_t *q
  443: 	  )
  444: {
  445: 	mblk_t *mp;
  446:   
  447: 	while ((mp = getq(q)))
  448: 	{
  449: 		if (canputnext(q) || (mp->b_datap->db_type > QPCTL))
  450: 		{
  451: 			putnext(q, mp);
  452: 			pprintf(DD_RSVC, "parse: RSVC - putnext\n");
  453: 		}
  454: 		else
  455: 		{
  456: 			putbq(q, mp);
  457: 			pprintf(DD_RSVC, "parse: RSVC - flow control wait\n");
  458: 			break;
  459: 		}
  460: 	}
  461: 	return 0;
  462: }
  463: 
  464: /*
  465:  * do ioctls and
  466:  * send stuff down - dont care about
  467:  * flow control
  468:  */
  469: static int
  470: parsewput(
  471: 	  queue_t *q,
  472: 	  mblk_t *mp
  473: 	  )
  474: {
  475: 	register int ok = 1;
  476: 	register mblk_t *datap;
  477: 	register struct iocblk *iocp;
  478: 	parsestream_t         *parse = (parsestream_t *)q->q_ptr;
  479:   
  480: 	pprintf(DD_WPUT, "parse: parsewput\n");
  481:   
  482: 	switch (mp->b_datap->db_type)
  483: 	{
  484: 	    default:
  485: 		putnext(q, mp);
  486: 		break;
  487:       
  488: 	    case M_IOCTL:
  489: 		iocp = (struct iocblk *)mp->b_rptr;
  490: 		switch (iocp->ioc_cmd)
  491: 		{
  492: 		    default:
  493: 			pprintf(DD_WPUT, "parse: parsewput - forward M_IOCTL\n");
  494: 			putnext(q, mp);
  495: 			break;
  496: 
  497: 		    case CIOGETEV:
  498: 			/*
  499: 			 * taken from Craig Leres ppsclock module (and modified)
  500: 			 */
  501: 			datap = allocb(sizeof(struct ppsclockev), BPRI_MED);
  502: 			if (datap == NULL || mp->b_cont)
  503: 			{
  504: 				mp->b_datap->db_type = M_IOCNAK;
  505: 				iocp->ioc_error = (datap == NULL) ? ENOMEM : EINVAL;
  506: 				if (datap != NULL)
  507: 				    freeb(datap);
  508: 				qreply(q, mp);
  509: 				break;
  510: 			}
  511: 
  512: 			mp->b_cont = datap;
  513: 			*(struct ppsclockev *)datap->b_wptr = parse->parse_ppsclockev;
  514: 			datap->b_wptr +=
  515: 				sizeof(struct ppsclockev) / sizeof(*datap->b_wptr);
  516: 			mp->b_datap->db_type = M_IOCACK;
  517: 			iocp->ioc_count = sizeof(struct ppsclockev);
  518: 			qreply(q, mp);
  519: 			break;
  520: 	  
  521: 		    case PARSEIOC_ENABLE:
  522: 		    case PARSEIOC_DISABLE:
  523: 			    {
  524: 				    parse->parse_status = (parse->parse_status & (unsigned)~PARSE_ENABLE) |
  525: 					    (iocp->ioc_cmd == PARSEIOC_ENABLE) ?
  526: 					    PARSE_ENABLE : 0;
  527: 				    if (!setup_stream(RD(q), (parse->parse_status & PARSE_ENABLE) ?
  528: 						      M_PARSE : M_NOPARSE))
  529: 				    {
  530: 					    mp->b_datap->db_type = M_IOCNAK;
  531: 				    }
  532: 				    else
  533: 				    {
  534: 					    mp->b_datap->db_type = M_IOCACK;
  535: 				    }
  536: 				    qreply(q, mp);
  537: 				    break;
  538: 			    }	    
  539: 
  540: 		    case PARSEIOC_TIMECODE:
  541: 		    case PARSEIOC_SETFMT:
  542: 		    case PARSEIOC_GETFMT:
  543: 		    case PARSEIOC_SETCS:
  544: 			if (iocp->ioc_count == sizeof(parsectl_t))
  545: 			{
  546: 				parsectl_t *dct = (parsectl_t *)mp->b_cont->b_rptr;
  547: 
  548: 				switch (iocp->ioc_cmd)
  549: 				{
  550: 				    case PARSEIOC_TIMECODE:
  551: 					pprintf(DD_WPUT, "parse: parsewput - PARSEIOC_TIMECODE\n");
  552: 					ok = parse_timecode(dct, &parse->parse_io);
  553: 					break;
  554: 		  
  555: 				    case PARSEIOC_SETFMT:
  556: 					pprintf(DD_WPUT, "parse: parsewput - PARSEIOC_SETFMT\n");
  557: 					ok = parse_setfmt(dct, &parse->parse_io);
  558: 					break;
  559: 
  560: 				    case PARSEIOC_GETFMT:
  561: 					pprintf(DD_WPUT, "parse: parsewput - PARSEIOC_GETFMT\n");
  562: 					ok = parse_getfmt(dct, &parse->parse_io);
  563: 					break;
  564: 
  565: 				    case PARSEIOC_SETCS:
  566: 					pprintf(DD_WPUT, "parse: parsewput - PARSEIOC_SETCS\n");
  567: 					ok = parse_setcs(dct, &parse->parse_io);
  568: 					break;
  569: 				}
  570: 				mp->b_datap->db_type = ok ? M_IOCACK : M_IOCNAK;
  571: 			}
  572: 			else
  573: 			{
  574: 				mp->b_datap->db_type = M_IOCNAK;
  575: 			}
  576: 			pprintf(DD_WPUT, "parse: parsewput qreply - %s\n", (mp->b_datap->db_type == M_IOCNAK) ? "M_IOCNAK" : "M_IOCACK");
  577: 			qreply(q, mp);
  578: 			break;
  579: 		}
  580: 	}
  581: 	return 0;
  582: }
  583: 
  584: /*
  585:  * read characters from streams buffers
  586:  */
  587: static unsigned long
  588: rdchar(
  589:        mblk_t **mp
  590:        )
  591: {
  592: 	while (*mp != (mblk_t *)NULL)
  593: 	{
  594: 		if ((*mp)->b_wptr - (*mp)->b_rptr)
  595: 		{
  596: 			return (unsigned long)(*(unsigned char *)((*mp)->b_rptr++));
  597: 		}
  598: 		else
  599: 		{
  600: 			register mblk_t *mmp = *mp;
  601: 	  
  602: 			*mp = (*mp)->b_cont;
  603: 			freeb(mmp);
  604: 		}
  605: 	}
  606: 	return (unsigned long)~0;
  607: }
  608: 
  609: /*
  610:  * convert incoming data
  611:  */
  612: static int
  613: parserput(
  614: 	  queue_t *q,
  615: 	  mblk_t *imp
  616: 	  )
  617: {
  618: 	register unsigned char type;
  619: 	mblk_t *mp = imp;
  620:   
  621: 	switch (type = mp->b_datap->db_type)
  622: 	{
  623: 	    default:
  624: 		/*
  625: 		 * anything we don't know will be put on queue
  626: 		 * the service routine will move it to the next one
  627: 		 */
  628: 		pprintf(DD_RPUT, "parse: parserput - forward type 0x%x\n", type);
  629: 
  630: 		if (canputnext(q) || (mp->b_datap->db_type > QPCTL))
  631: 		{
  632: 			putnext(q, mp);
  633: 		}
  634: 		else
  635: 		    putq(q, mp);
  636: 		break;
  637:       
  638: 	    case M_BREAK:
  639: 	    case M_DATA:
  640: 		    {
  641: 			    register parsestream_t * parse = (parsestream_t *)q->q_ptr;
  642: 			    register mblk_t *nmp;
  643: 			    register unsigned long ch;
  644: 			    timestamp_t c_time;
  645: 			    timespec_t hres_time;
  646: 
  647: 			    /*
  648: 			     * get time on packet delivery
  649: 			     */
  650: 			    gethrestime(&hres_time);
  651: 			    c_time.tv.tv_sec  = hres_time.tv_sec;
  652: 			    c_time.tv.tv_usec = hres_time.tv_nsec / 1000;
  653: 
  654: 			    if (!(parse->parse_status & PARSE_ENABLE))
  655: 			    {
  656: 				    pprintf(DD_RPUT, "parse: parserput - parser disabled - forward type 0x%x\n", type);
  657: 				    if (canputnext(q) || (mp->b_datap->db_type > QPCTL))
  658: 				    {
  659: 					    putnext(q, mp);
  660: 				    }
  661: 				    else
  662: 					putq(q, mp);
  663: 			    }
  664: 			    else
  665: 			    {
  666: 				    pprintf(DD_RPUT, "parse: parserput - M_%s\n", (type == M_DATA) ? "DATA" : "BREAK");
  667: 				    if (type == M_DATA)
  668: 				    {
  669: 					    /*
  670: 					     * parse packet looking for start an end characters
  671: 					     */
  672: 					    while (mp != (mblk_t *)NULL)
  673: 					    {
  674: 						    ch = rdchar(&mp);
  675: 						    if (ch != ~0 && parse_ioread(&parse->parse_io, (unsigned int)ch, &c_time))
  676: 						    {
  677: 							    /*
  678: 							     * up up and away (hopefully ...)
  679: 							     * don't press it if resources are tight or nobody wants it
  680: 							     */
  681: 							    nmp = (mblk_t *)NULL;
  682: 							    if (canputnext(parse->parse_queue) && (nmp = allocb(sizeof(parsetime_t), BPRI_MED)))
  683: 							    {
  684: 								    bcopy((caddr_t)&parse->parse_io.parse_dtime, (caddr_t)nmp->b_rptr, sizeof(parsetime_t));
  685: 								    nmp->b_wptr += sizeof(parsetime_t);
  686: 								    putnext(parse->parse_queue, nmp);
  687: 							    }
  688: 							    else
  689: 								if (nmp) freemsg(nmp);
  690: 							    parse_iodone(&parse->parse_io);
  691: 						    }
  692: 					    }	
  693: 				    }
  694: 				    else
  695: 				    {
  696: 					    if (parse_ioread(&parse->parse_io, (unsigned int)0, &c_time))
  697: 					    {
  698: 						    /*
  699: 						     * up up and away (hopefully ...)
  700: 						     * don't press it if resources are tight or nobody wants it
  701: 						     */
  702: 						    nmp = (mblk_t *)NULL;
  703: 						    if (canputnext(parse->parse_queue) && (nmp = allocb(sizeof(parsetime_t), BPRI_MED)))
  704: 						    {
  705: 							    bcopy((caddr_t)&parse->parse_io.parse_dtime, (caddr_t)nmp->b_rptr, sizeof(parsetime_t));
  706: 							    nmp->b_wptr += sizeof(parsetime_t);
  707: 							    putnext(parse->parse_queue, nmp);
  708: 						    }
  709: 						    else
  710: 							if (nmp) freemsg(nmp);
  711: 						    parse_iodone(&parse->parse_io);
  712: 					    }
  713: 					    freemsg(mp);
  714: 				    }
  715: 				    break;
  716: 			    }
  717: 		    }
  718: 
  719: 		    /*
  720: 		     * CD PPS support for non direct ISR hack
  721: 		     */
  722: 	    case M_HANGUP:
  723: 	    case M_UNHANGUP:
  724: 		    {
  725: 			    register parsestream_t * parse = (parsestream_t *)q->q_ptr;
  726: 			    timestamp_t c_time;
  727: 			    timespec_t hres_time;
  728: 			    register mblk_t *nmp;
  729: 			    register int status = cd_invert ^ (type == M_UNHANGUP);
  730: 
  731: 			    gethrestime(&hres_time);
  732: 			    c_time.tv.tv_sec  = hres_time.tv_sec;
  733: 			    c_time.tv.tv_usec = hres_time.tv_nsec / 1000;
  734: 	
  735: 			    pprintf(DD_RPUT, "parse: parserput - M_%sHANGUP\n", (type == M_HANGUP) ? "" : "UN");
  736: 
  737: 			    if ((parse->parse_status & PARSE_ENABLE) &&
  738: 				parse_iopps(&parse->parse_io, status ? SYNC_ONE : SYNC_ZERO, &c_time))
  739: 			    {
  740: 				    nmp = (mblk_t *)NULL;
  741: 				    if (canputnext(parse->parse_queue) && (nmp = allocb(sizeof(parsetime_t), BPRI_MED)))
  742: 				    {
  743: 					    bcopy((caddr_t)&parse->parse_io.parse_dtime, (caddr_t)nmp->b_rptr, sizeof(parsetime_t));
  744: 					    nmp->b_wptr += sizeof(parsetime_t);
  745: 					    putnext(parse->parse_queue, nmp);
  746: 				    }
  747: 				    else
  748: 					if (nmp) freemsg(nmp);
  749: 				    parse_iodone(&parse->parse_io);
  750: 				    freemsg(mp);
  751: 			    }
  752: 			    else
  753: 				if (canputnext(q) || (mp->b_datap->db_type > QPCTL))
  754: 				{
  755: 					putnext(q, mp);
  756: 				}
  757: 				else
  758: 				    putq(q, mp);
  759: 	
  760: 			    if (status)
  761: 			    {
  762: 				    parse->parse_ppsclockev.tv = c_time.tv;
  763: 				    ++(parse->parse_ppsclockev.serial);
  764: 			    }
  765: 		    }
  766: 	}
  767: 	return 0;
  768: }
  769: 
  770: static int  init_zs_linemon  (queue_t *, queue_t *);	/* handle line monitor for "zs" driver */
  771: static void close_zs_linemon (queue_t *, queue_t *);
  772: 
  773: /*-------------------- CD isr status monitor ---------------*/
  774: 
  775: static int
  776: init_linemon(
  777: 	     queue_t *q
  778: 	     )
  779: {
  780: 	register queue_t *dq;
  781:   
  782: 	dq = WR(q);
  783: 	/*
  784: 	 * we ARE doing very bad things down here (basically stealing ISR
  785: 	 * hooks)
  786: 	 *
  787: 	 * so we chase down the STREAMS stack searching for the driver
  788: 	 * and if this is a known driver we insert our ISR routine for
  789: 	 * status changes in to the ExternalStatus handling hook
  790: 	 */
  791: 	while (dq->q_next)
  792: 	{
  793: 		dq = dq->q_next;		/* skip down to driver */
  794: 	}
  795: 
  796: 	/*
  797: 	 * find appropriate driver dependent routine
  798: 	 */
  799: 	if (dq->q_qinfo && dq->q_qinfo->qi_minfo)
  800: 	{
  801: 		register char *dname = dq->q_qinfo->qi_minfo->mi_idname;
  802: 
  803: 		pprintf(DD_INSTALL, "init_linemon: driver is \"%s\"\n", dname);
  804: 
  805: #ifdef sun
  806: 		if (dname && !strcmp(dname, "zs"))
  807: 		{
  808: 			return init_zs_linemon(dq, q);
  809: 		}
  810: 		else
  811: #endif
  812: 		{
  813: 			pprintf(DD_INSTALL, "init_linemon: driver \"%s\" not suitable for CD monitoring\n", dname);
  814: 			return 0;
  815: 		}
  816: 	}
  817: 	pprintf(DD_INSTALL, "init_linemon: cannot find driver\n");
  818: 	return 0;
  819: }
  820: 
  821: static void
  822: close_linemon(
  823: 	      queue_t *q,
  824: 	      queue_t *my_q
  825: 	      )
  826: {
  827: 	/*
  828: 	 * find appropriate driver dependent routine
  829: 	 */
  830: 	if (q->q_qinfo && q->q_qinfo->qi_minfo)
  831: 	{
  832: 		register char *dname = q->q_qinfo->qi_minfo->mi_idname;
  833: 
  834: #ifdef sun
  835: 		if (dname && !strcmp(dname, "zs"))
  836: 		{
  837: 			close_zs_linemon(q, my_q);
  838: 			return;
  839: 		}
  840: 		pprintf(DD_INSTALL, "close_linemon: cannot find driver close routine for \"%s\"\n", dname);
  841: #endif
  842: 	}
  843: 	pprintf(DD_INSTALL, "close_linemon: cannot find driver name\n");
  844: }
  845: 
  846: #ifdef sun
  847: #include <sys/tty.h>
  848: #include <sys/zsdev.h>
  849: #include <sys/ser_async.h>
  850: #include <sys/ser_zscc.h>
  851: 
  852: static void zs_xsisr         (struct zscom *);	/* zs external status interupt handler */
  853: 
  854: /*
  855:  * there should be some docs telling how to get to
  856:  * sz:zs_usec_delay and zs:initzsops()
  857:  */
  858: #define zs_usec_delay 5
  859: 
  860: struct savedzsops
  861: {
  862: 	struct zsops  zsops;
  863: 	struct zsops *oldzsops;
  864: };
  865: 
  866: static struct zsops   *emergencyzs;
  867: 
  868: static int
  869: init_zs_linemon(
  870: 		queue_t *q,
  871: 		queue_t *my_q
  872: 		)
  873: {
  874: 	register struct zscom *zs;
  875: 	register struct savedzsops *szs;
  876: 	register parsestream_t  *parsestream = (parsestream_t *)my_q->q_ptr;
  877: 	/*
  878: 	 * we expect the zsaline pointer in the q_data pointer
  879: 	 * from there on we insert our on EXTERNAL/STATUS ISR routine
  880: 	 * into the interrupt path, before the standard handler
  881: 	 */
  882: 	zs = ((struct asyncline *)q->q_ptr)->za_common;
  883: 	if (!zs)
  884: 	{
  885: 		/*
  886: 		 * well - not found on startup - just say no (shouldn't happen though)
  887: 		 */
  888: 		return 0;
  889: 	}
  890: 	else
  891: 	{
  892: 		/*
  893: 		 * we do a direct replacement, in case others fiddle also
  894: 		 * if somebody else grabs our hook and we disconnect
  895: 		 * we are in DEEP trouble - panic is likely to be next, sorry
  896: 		 */
  897: 		szs = (struct savedzsops *) kmem_alloc(sizeof(struct savedzsops), KM_SLEEP);
  898: 
  899: 		if (szs == (struct savedzsops *)0)
  900: 		{
  901: 			pprintf(DD_INSTALL, "init_zs_linemon: CD monitor NOT installed - no memory\n");
  902: 
  903: 			return 0;
  904: 		}
  905: 		else
  906: 		{
  907: 			parsestream->parse_data   = (void *)szs;
  908: 
  909: 			mutex_enter(zs->zs_excl);
  910: 
  911: 			parsestream->parse_dqueue = q; /* remember driver */
  912: 
  913: 			szs->zsops            = *zs->zs_ops;
  914: 			szs->zsops.zsop_xsint = (void (*) (struct zscom *))zs_xsisr; /* place our bastard */
  915: 			szs->oldzsops         = zs->zs_ops;
  916: 			emergencyzs           = zs->zs_ops;
  917: 	  
  918: 			zs->zs_ops = &szs->zsops; /* hook it up */
  919: 			/*
  920: 			 * XXX: this is usually done via zsopinit() 
  921: 			 * - have yet to find a way to call that routine
  922: 			 */
  923: 			zs->zs_xsint          = (void (*) (struct zscom *))zs_xsisr;
  924: 	  
  925: 			mutex_exit(zs->zs_excl);
  926: 
  927: 			pprintf(DD_INSTALL, "init_zs_linemon: CD monitor installed\n");
  928: 
  929: 			return 1;
  930: 		}
  931: 	}
  932: }
  933: 
  934: /*
  935:  * unregister our ISR routine - must call under splhigh() (or 
  936:  * whatever block ZS status interrupts)
  937:  */
  938: static void
  939: close_zs_linemon(
  940: 		 queue_t *q,
  941: 		 queue_t *my_q
  942: 		 )
  943: {
  944: 	register struct zscom *zs;
  945: 	register parsestream_t  *parsestream = (parsestream_t *)my_q->q_ptr;
  946: 
  947: 	zs = ((struct asyncline *)q->q_ptr)->za_common;
  948: 	if (!zs)
  949: 	{
  950: 		/*
  951: 		 * well - not found on startup - just say no (shouldn't happen though)
  952: 		 */
  953: 		return;
  954: 	}
  955: 	else
  956: 	{
  957: 		register struct savedzsops *szs = (struct savedzsops *)parsestream->parse_data;
  958: 
  959: 		mutex_enter(zs->zs_excl);
  960: 
  961: 		zs->zs_ops = szs->oldzsops; /* reset to previous handler functions */
  962: 		/*
  963: 		 * XXX: revert xsint (usually done via zsopinit() - have still to find
  964: 		 * a way to call that bugger
  965: 		 */
  966: 		zs->zs_xsint = zs->zs_ops->zsop_xsint;
  967: 
  968: 		mutex_exit(zs->zs_excl);
  969: 
  970: 		kmem_free((caddr_t)szs, sizeof (struct savedzsops));
  971:       
  972: 		pprintf(DD_INSTALL, "close_zs_linemon: CD monitor deleted\n");
  973: 		return;
  974: 	}
  975: }
  976: 
  977: #define ZSRR0_IGNORE	(ZSRR0_CD|ZSRR0_SYNC|ZSRR0_CTS)
  978: 
  979: #define MAXDEPTH 50		/* maximum allowed stream crawl */
  980: 
  981: /*
  982:  * take external status interrupt (only CD interests us)
  983:  */
  984: static void
  985: zs_xsisr(
  986: 	 struct zscom *zs
  987: 	 )
  988: {
  989: 	register struct asyncline *za = (struct asyncline *)zs->zs_priv;
  990: 	register queue_t *q;
  991: 	register unsigned char zsstatus;
  992: 	register int loopcheck;
  993: 	register unsigned char cdstate;
  994: 	register const char *dname = "-UNKNOWN-";
  995: 	timespec_t hres_time;
  996: 
  997: 	/*
  998: 	 * pick up current state
  999: 	 */
 1000: 	zsstatus = SCC_READ0();
 1001: 
 1002: 	if (za->za_rr0 ^ (cdstate = zsstatus & ZSRR0_CD))
 1003: 	{
 1004: 		timestamp_t cdevent;
 1005: 		register int status;
 1006:       
 1007: 		/*
 1008: 		 * time stamp
 1009: 		 */
 1010: 		gethrestime(&hres_time);
 1011: 		cdevent.tv.tv_sec  = hres_time.tv_sec;
 1012: 		cdevent.tv.tv_usec = hres_time.tv_nsec / 1000;
 1013: 
 1014: 		q = za->za_ttycommon.t_readq;
 1015: 
 1016: 		/*
 1017: 		 * logical state
 1018: 		 */
 1019: 		status = cd_invert ? cdstate == 0 : cdstate != 0;
 1020: 
 1021: 		/*
 1022: 		 * ok - now the hard part - find ourself
 1023: 		 */
 1024: 		loopcheck = MAXDEPTH;
 1025:       
 1026: 		while (q)
 1027: 		{
 1028: 			if (q->q_qinfo && q->q_qinfo->qi_minfo)
 1029: 			{
 1030: 				dname = q->q_qinfo->qi_minfo->mi_idname;
 1031: 
 1032: 				if (!strcmp(dname, parseinfo.st_rdinit->qi_minfo->mi_idname))
 1033: 				{
 1034: 					/*
 1035: 					 * back home - phew (hopping along stream queues might
 1036: 					 * prove dangerous to your health)
 1037: 					 */
 1038: 
 1039: 					if ((((parsestream_t *)q->q_ptr)->parse_status & PARSE_ENABLE) &&
 1040: 					    parse_iopps(&((parsestream_t *)q->q_ptr)->parse_io, status ? SYNC_ONE : SYNC_ZERO, &cdevent))
 1041: 					{
 1042: 						/*
 1043: 						 * XXX - currently we do not pass up the message, as
 1044: 						 * we should.
 1045: 						 * for a correct behaviour wee need to block out
 1046: 						 * processing until parse_iodone has been posted via
 1047: 						 * a softcall-ed routine which does the message pass-up
 1048: 						 * right now PPS information relies on input being
 1049: 						 * received
 1050: 						 */
 1051: 						parse_iodone(&((parsestream_t *)q->q_ptr)->parse_io);
 1052: 					}
 1053: 		  
 1054: 					if (status)
 1055: 					{
 1056: 						((parsestream_t *)q->q_ptr)->parse_ppsclockev.tv = cdevent.tv;
 1057: 						++(((parsestream_t *)q->q_ptr)->parse_ppsclockev.serial);
 1058: 					}
 1059: 
 1060: 					pprintf(DD_ISR, "zs_xsisr: CD event %s has been posted for \"%s\"\n", status ? "ONE" : "ZERO", dname);
 1061: 					break;
 1062: 				}
 1063: 			}
 1064: 
 1065: 			q = q->q_next;
 1066: 
 1067: 			if (!loopcheck--)
 1068: 			{
 1069: 				panic("zs_xsisr: STREAMS Queue corrupted - CD event");
 1070: 			}
 1071: 		}
 1072: 
 1073: 		if (cdstate)	/* fake CARRIER status - XXX currently not coordinated */
 1074: 		  za->za_flags |= ZAS_CARR_ON;
 1075: 		else
 1076: 		  za->za_flags &= ~ZAS_CARR_ON;
 1077: 
 1078: 		/*
 1079: 		 * only pretend that CD and ignored transistion (SYNC,CTS)
 1080: 		 * have been handled
 1081: 		 */
 1082: 		za->za_rr0 = (za->za_rr0 & ~ZSRR0_IGNORE) | (zsstatus & ZSRR0_IGNORE);
 1083: 
 1084: 		if (((za->za_rr0 ^ zsstatus) & ~ZSRR0_IGNORE) == 0)
 1085: 		{
 1086: 			/*
 1087: 			 * all done - kill status indication and return
 1088: 			 */
 1089: 			SCC_WRITE0(ZSWR0_RESET_STATUS); /* might kill other conditions here */
 1090: 			return;
 1091: 		}
 1092: 	}      
 1093: 
 1094: 	pprintf(DD_ISR, "zs_xsisr: non CD event 0x%x for \"%s\"\n", 
 1095: 		(za->za_rr0 ^ zsstatus) & ~ZSRR0_CD,dname);
 1096: 	/*
 1097: 	 * we are now gathered here to process some unusual external status
 1098: 	 * interrupts.
 1099: 	 * any CD events have also been handled and shouldn't be processed
 1100: 	 * by the original routine (unless we have a VERY busy port pin)
 1101: 	 * some initializations are done here, which could have been done before for
 1102: 	 * both code paths but have been avioded for minimum path length to
 1103: 	 * the uniq_time routine
 1104: 	 */
 1105: 	dname = (char *) 0;
 1106: 	q = za->za_ttycommon.t_readq;
 1107: 
 1108: 	loopcheck = MAXDEPTH;
 1109:       
 1110: 	/*
 1111: 	 * the real thing for everything else ...
 1112: 	 */
 1113: 	while (q)
 1114: 	{
 1115: 		if (q->q_qinfo && q->q_qinfo->qi_minfo)
 1116: 		{
 1117: 			dname = q->q_qinfo->qi_minfo->mi_idname;
 1118: 			if (!strcmp(dname, parseinfo.st_rdinit->qi_minfo->mi_idname))
 1119: 			{
 1120: 				register void (*zsisr) (struct zscom *);
 1121: 		  
 1122: 				/*
 1123: 				 * back home - phew (hopping along stream queues might
 1124: 				 * prove dangerous to your health)
 1125: 				 */
 1126: 				if ((zsisr = ((struct savedzsops *)((parsestream_t *)q->q_ptr)->parse_data)->oldzsops->zsop_xsint))
 1127: 				    zsisr(zs);
 1128: 				else
 1129: 				    panic("zs_xsisr: unable to locate original ISR");
 1130: 		  
 1131: 				pprintf(DD_ISR, "zs_xsisr: non CD event was processed for \"%s\"\n", dname);
 1132: 				/*
 1133: 				 * now back to our program ...
 1134: 				 */
 1135: 				return;
 1136: 			}
 1137: 		}
 1138: 
 1139: 		q = q->q_next;
 1140: 
 1141: 		if (!loopcheck--)
 1142: 		{
 1143: 			panic("zs_xsisr: STREAMS Queue corrupted - non CD event");
 1144: 		}
 1145: 	}
 1146: 
 1147: 	/*
 1148: 	 * last resort - shouldn't even come here as it indicates
 1149: 	 * corrupted TTY structures
 1150: 	 */
 1151: 	printf("zs_zsisr: looking for \"%s\" - found \"%s\" - taking EMERGENCY path\n", parseinfo.st_rdinit->qi_minfo->mi_idname, dname ? dname : "-NIL-");
 1152:       
 1153: 	if (emergencyzs && emergencyzs->zsop_xsint)
 1154: 	    emergencyzs->zsop_xsint(zs);
 1155: 	else
 1156: 	    panic("zs_xsisr: no emergency ISR handler");
 1157: }
 1158: #endif				/* sun */
 1159: 
 1160: /*
 1161:  * History:
 1162:  *
 1163:  * parsesolaris.c,v
 1164:  * Revision 4.11  2005/04/16 17:32:10  kardel
 1165:  * update copyright
 1166:  *
 1167:  * Revision 4.10  2004/11/14 16:06:08  kardel
 1168:  * update Id tags
 1169:  *
 1170:  * Revision 4.9  2004/11/14 15:29:41  kardel
 1171:  * support PPSAPI, upgrade Copyright to Berkeley style
 1172:  *
 1173:  * Revision 4.6  1998/11/15 21:56:08  kardel
 1174:  * ntp_memset not necessary
 1175:  *
 1176:  * Revision 4.5  1998/11/15 21:23:37  kardel
 1177:  * ntp_memset() replicated in Sun kernel files
 1178:  *
 1179:  * Revision 4.4  1998/06/14 21:09:40  kardel
 1180:  * Sun acc cleanup
 1181:  *
 1182:  * Revision 4.3  1998/06/13 12:14:59  kardel
 1183:  * more prototypes
 1184:  * fix name clashes
 1185:  * allow for ansi2knr
 1186:  *
 1187:  * Revision 4.2  1998/06/12 15:23:08  kardel
 1188:  * fix prototypes
 1189:  * adjust for ansi2knr
 1190:  *
 1191:  * Revision 4.1  1998/05/24 09:38:46  kardel
 1192:  * streams initiated iopps calls (M_xHANGUP) are now consistent with the
 1193:  * respective calls from zs_xsisr()
 1194:  * simulation of CARRIER status to avoid unecessary M_xHANGUP messages
 1195:  *
 1196:  * Revision 4.0  1998/04/10 19:45:38  kardel
 1197:  * Start 4.0 release version numbering
 1198:  *
 1199:  * from V3 3.28 log info deleted 1998/04/11 kardel
 1200:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>