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