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