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