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