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