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