1 /* $NetBSD: parsestreams.c,v 1.2 2003/12/04 16:23:37 drochner Exp $ */
4 * /src/NTP/ntp4-dev/libparse/parsestreams.c,v 4.11 2005/04/16 17:32:10 kardel RELEASE_20050508_A
6 * parsestreams.c,v 4.11 2005/04/16 17:32:10 kardel RELEASE_20050508_A
8 * STREAMS module for reference clocks
11 * Copyright (c) 1995-2005 by Frank Kardel <kardel <AT> ntp.org>
12 * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universität Erlangen-Nürnberg, Germany
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 * 3. Neither the name of the author nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40 #define KERNEL /* MUST */
41 #define VDDRV /* SHOULD */
48 static char rcsid
[] = "parsestreams.c,v 4.11 2005/04/16 17:32:10 kardel RELEASE_20050508_A";
52 #include "Bletch: MUST COMPILE WITH KERNEL DEFINE"
55 #include <sys/types.h>
58 #include <sys/param.h>
59 #include <sys/sysmacros.h>
61 #include <sundev/mbvar.h>
62 #include <sun/autoconf.h>
63 #include <sys/stream.h>
64 #include <sys/stropts.h>
66 #include <sys/signal.h>
67 #include <sys/termios.h>
68 #include <sys/termio.h>
69 #include <sys/ttold.h>
74 #include <sun/vddrv.h>
77 #include "ntp_stdlib.h"
80 * just make checking compilers more silent
82 extern int printf
P((const char *, ...));
83 extern int putctl1
P((queue_t
*, int, int));
84 extern int canput
P((queue_t
*));
85 extern void putbq
P((queue_t
*, mblk_t
*));
86 extern void freeb
P((mblk_t
*));
87 extern void qreply
P((queue_t
*, mblk_t
*));
88 extern void freemsg
P((mblk_t
*));
89 extern void panic
P((const char *, ...));
90 extern void usec_delay
P((int));
93 #include "sys/parsestreams.h"
96 * use microtime instead of uniqtime if advised to
99 #define uniqtime microtime
103 static unsigned int parsebusy
= 0;
105 /*--------------- loadable driver section -----------------------------*/
107 extern struct streamtab parseinfo
;
111 static char mnam
[] = "PARSEPPS "; /* name this baby - keep room for revision number */
113 static char mnam
[] = "PARSE "; /* name this baby - keep room for revision number */
115 struct vdldrv parsesync_vd
=
117 VDMAGIC_PSEUDO
, /* nothing like a real driver - a STREAMS module */
122 * strings support usually not in kernel
126 register const char *s
151 while ((c
-- > 0) && (*t
++ = *s
++))
158 register const char *s
,
159 register const char *t
164 if (!s
|| !t
|| (s
== t
))
169 while (!(c
= *s
++ - *t
++) && *s
&& *t
)
184 if (!s
|| !t
|| (s
== t
))
189 while (n
-- && !(c
= *s
++ - *t
++) && *s
&& *t
)
207 * driver init routine
208 * since no mechanism gets us into and out of the fmodsw, we have to
220 extern struct fmodsw fmodsw
[];
223 struct fmodsw
*fm
= fmodsw
;
224 struct fmodsw
*fmend
= &fmodsw
[fmodcnt
];
225 struct fmodsw
*ifm
= (struct fmodsw
*)0;
226 char *mname
= parseinfo
.st_rdinit
->qi_minfo
->mi_idname
;
231 vdp
->vdd_vdtab
= (struct vdlinkage
*)&parsesync_vd
;
233 * now, jog along fmodsw scanning for an empty slot
234 * and deposit our name there
238 if (!Strncmp(fm
->f_name
, mname
, FMNAMESZ
))
240 printf("vddrinit[%s]: STREAMS module already loaded.\n", mname
);
244 if ((ifm
== (struct fmodsw
*)0) &&
245 (fm
->f_name
[0] == '\0') &&
246 (fm
->f_str
== (struct streamtab
*)0))
249 * got one - so move in
257 if (ifm
== (struct fmodsw
*)0)
259 printf("vddrinit[%s]: no slot free for STREAMS module\n", mname
);
264 static char revision
[] = "4.7";
267 s
= rcsid
; /* NOOP - keep compilers happy */
269 Strncpy(ifm
->f_name
, mname
, FMNAMESZ
);
270 ifm
->f_name
[FMNAMESZ
] = '\0';
271 ifm
->f_str
= &parseinfo
;
273 * copy RCS revision into Drv_name
275 * are we forcing RCS here to do things it was not built for ?
282 * if present. - not necessary on a -kv co (cvs export)
284 while (*s
&& (*s
!= ' '))
291 t
= parsesync_vd
.Drv_name
;
292 while (*t
&& (*t
!= ' '))
299 while (*S
&& (((*S
>= '0') && (*S
<= '9')) || (*S
== '.')))
304 if (*s
&& *t
&& (S
> s
))
306 if (Strlen(t
) >= (S
- s
))
308 (void) Strncpy(t
, s
, S
- s
);
318 printf("vddrinit[%s]: STREAMS module has still %d instances active.\n", mname
, parsebusy
);
325 if (!Strncmp(fm
->f_name
, mname
, FMNAMESZ
))
328 * got it - kill entry
330 fm
->f_name
[0] = '\0';
331 fm
->f_str
= (struct streamtab
*)0;
340 printf("vddrinit[%s]: cannot find entry for STREAMS module\n", mname
);
360 /*--------------- stream module definition ----------------------------*/
362 static int parseopen
P((queue_t
*, dev_t
, int, int));
363 static int parseclose
P((queue_t
*, int));
364 static int parsewput
P((queue_t
*, mblk_t
*));
365 static int parserput
P((queue_t
*, mblk_t
*));
366 static int parsersvc
P((queue_t
*));
368 static char mn
[] = "parse";
370 static struct module_info driverinfo
=
372 0, /* module ID number */
373 mn
, /* module name */
374 0, /* minimum accepted packet size */
375 INFPSZ
, /* maximum accepted packet size */
376 1, /* high water mark - flow control */
377 0 /* low water mark - flow control */
380 static struct qinit rinit
= /* read queue definition */
382 parserput
, /* put procedure */
383 parsersvc
, /* service procedure */
384 parseopen
, /* open procedure */
385 parseclose
, /* close procedure */
386 NULL
, /* admin procedure - NOT USED FOR NOW */
387 &driverinfo
, /* information structure */
388 NULL
/* statistics */
391 static struct qinit winit
= /* write queue definition */
393 parsewput
, /* put procedure */
394 NULL
, /* service procedure */
395 NULL
, /* open procedure */
396 NULL
, /* close procedure */
397 NULL
, /* admin procedure - NOT USED FOR NOW */
398 &driverinfo
, /* information structure */
399 NULL
/* statistics */
402 struct streamtab parseinfo
= /* stream info element for dpr driver */
404 &rinit
, /* read queue */
405 &winit
, /* write queue */
407 NULL
, /* write mux */
408 NULL
/* module auto push */
411 /*--------------- driver data structures ----------------------------*/
414 * we usually have an inverted signal - but you
415 * can change this to suit your needs
417 int cd_invert
= 1; /* invert status of CD line - PPS support via CD input */
421 extern void uniqtime
P((struct timeval
*));
423 /*--------------- module implementation -----------------------------*/
425 #define TIMEVAL_USADD(_X_, _US_) {\
426 (_X_)->tv_usec += (_US_);\
427 if ((_X_)->tv_usec >= 1000000)\
430 (_X_)->tv_usec -= 1000000;\
434 static int init_linemon
P((queue_t
*));
435 static void close_linemon
P((queue_t
*, queue_t
*));
437 #define M_PARSE 0x0001
438 #define M_NOPARSE 0x0002
448 mp
= allocb(sizeof(struct stroptions
), BPRI_MED
);
451 struct stroptions
*str
= (struct stroptions
*)(void *)mp
->b_rptr
;
453 str
->so_flags
= SO_READOPT
|SO_HIWAT
|SO_LOWAT
;
454 str
->so_readopt
= (mode
== M_PARSE
) ? RMSGD
: RNORM
;
455 str
->so_hiwat
= (mode
== M_PARSE
) ? sizeof(parsetime_t
) : 256;
457 mp
->b_datap
->db_type
= M_SETOPTS
;
458 mp
->b_wptr
+= sizeof(struct stroptions
);
460 return putctl1(WR(q
)->q_next
, M_CTL
, (mode
== M_PARSE
) ? MC_SERVICEIMM
:
465 parseprintf(DD_OPEN
,("parse: setup_stream - FAILED - no MEMORY for allocb\n"));
479 register parsestream_t
*parse
;
480 static int notice
= 0;
482 parseprintf(DD_OPEN
,("parse: OPEN\n"));
484 if (sflag
!= MODOPEN
)
485 { /* open only for modules */
486 parseprintf(DD_OPEN
,("parse: OPEN - FAILED - not MODOPEN\n"));
490 if (q
->q_ptr
!= (caddr_t
)NULL
)
493 parseprintf(DD_OPEN
,("parse: OPEN - FAILED - EXCLUSIVE ONLY\n"));
501 q
->q_ptr
= (caddr_t
)kmem_alloc(sizeof(parsestream_t
));
502 if (q
->q_ptr
== (caddr_t
)0)
504 parseprintf(DD_OPEN
,("parse: OPEN - FAILED - no memory\n"));
510 WR(q
)->q_ptr
= q
->q_ptr
;
512 parse
= (parsestream_t
*)(void *)q
->q_ptr
;
513 bzero((caddr_t
)parse
, sizeof(*parse
));
514 parse
->parse_queue
= q
;
515 parse
->parse_status
= PARSE_ENABLE
;
516 parse
->parse_ppsclockev
.tv
.tv_sec
= 0;
517 parse
->parse_ppsclockev
.tv
.tv_usec
= 0;
518 parse
->parse_ppsclockev
.serial
= 0;
520 if (!parse_ioinit(&parse
->parse_io
))
525 kmem_free((caddr_t
)parse
, sizeof(parsestream_t
));
532 if (setup_stream(q
, M_PARSE
))
534 (void) init_linemon(q
); /* hook up PPS ISR routines if possible */
536 parseprintf(DD_OPEN
,("parse: OPEN - SUCCEEDED\n"));
539 * I know that you know the delete key, but you didn't write this
540 * code, did you ? - So, keep the message in here.
545 printf("%s: Copyright (C) 1991-2005, Frank Kardel\n", parsesync_vd
.Drv_name
);
547 printf("%s: Copyright (C) 1991-2005, Frank Kardel\n", "parsestreams.c,v 4.11 2005/04/16 17:32:10 kardel RELEASE_20050508_A");
556 kmem_free((caddr_t
)parse
, sizeof(parsestream_t
));
572 register parsestream_t
*parse
= (parsestream_t
*)(void *)q
->q_ptr
;
573 register unsigned long s
;
575 parseprintf(DD_CLOSE
,("parse: CLOSE\n"));
579 if (parse
->parse_dqueue
)
580 close_linemon(parse
->parse_dqueue
, q
);
581 parse
->parse_dqueue
= (queue_t
*)0;
585 parse_ioend(&parse
->parse_io
);
587 kmem_free((caddr_t
)parse
, sizeof(parsestream_t
));
589 q
->q_ptr
= (caddr_t
)NULL
;
590 WR(q
)->q_ptr
= (caddr_t
)NULL
;
599 * move unrecognized stuff upward
608 while ((mp
= getq(q
)))
610 if (canput(q
->q_next
) || (mp
->b_datap
->db_type
> QPCTL
))
613 parseprintf(DD_RSVC
,("parse: RSVC - putnext\n"));
618 parseprintf(DD_RSVC
,("parse: RSVC - flow control wait\n"));
627 * send stuff down - dont care about
637 register mblk_t
*datap
;
638 register struct iocblk
*iocp
;
639 parsestream_t
*parse
= (parsestream_t
*)(void *)q
->q_ptr
;
641 parseprintf(DD_WPUT
,("parse: parsewput\n"));
643 switch (mp
->b_datap
->db_type
)
650 iocp
= (struct iocblk
*)(void *)mp
->b_rptr
;
651 switch (iocp
->ioc_cmd
)
654 parseprintf(DD_WPUT
,("parse: parsewput - forward M_IOCTL\n"));
660 * taken from Craig Leres ppsclock module (and modified)
662 datap
= allocb(sizeof(struct ppsclockev
), BPRI_MED
);
663 if (datap
== NULL
|| mp
->b_cont
)
665 mp
->b_datap
->db_type
= M_IOCNAK
;
666 iocp
->ioc_error
= (datap
== NULL
) ? ENOMEM
: EINVAL
;
674 *(struct ppsclockev
*)(void *)datap
->b_wptr
= parse
->parse_ppsclockev
;
676 sizeof(struct ppsclockev
) / sizeof(*datap
->b_wptr
);
677 mp
->b_datap
->db_type
= M_IOCACK
;
678 iocp
->ioc_count
= sizeof(struct ppsclockev
);
682 case PARSEIOC_ENABLE
:
683 case PARSEIOC_DISABLE
:
685 parse
->parse_status
= (parse
->parse_status
& (unsigned)~PARSE_ENABLE
) |
686 (iocp
->ioc_cmd
== PARSEIOC_ENABLE
) ?
688 if (!setup_stream(RD(q
), (parse
->parse_status
& PARSE_ENABLE
) ?
689 M_PARSE
: M_NOPARSE
))
691 mp
->b_datap
->db_type
= M_IOCNAK
;
695 mp
->b_datap
->db_type
= M_IOCACK
;
701 case PARSEIOC_TIMECODE
:
702 case PARSEIOC_SETFMT
:
703 case PARSEIOC_GETFMT
:
705 if (iocp
->ioc_count
== sizeof(parsectl_t
))
707 parsectl_t
*dct
= (parsectl_t
*)(void *)mp
->b_cont
->b_rptr
;
709 switch (iocp
->ioc_cmd
)
711 case PARSEIOC_TIMECODE
:
712 parseprintf(DD_WPUT
,("parse: parsewput - PARSEIOC_TIMECODE\n"));
713 ok
= parse_timecode(dct
, &parse
->parse_io
);
716 case PARSEIOC_SETFMT
:
717 parseprintf(DD_WPUT
,("parse: parsewput - PARSEIOC_SETFMT\n"));
718 ok
= parse_setfmt(dct
, &parse
->parse_io
);
721 case PARSEIOC_GETFMT
:
722 parseprintf(DD_WPUT
,("parse: parsewput - PARSEIOC_GETFMT\n"));
723 ok
= parse_getfmt(dct
, &parse
->parse_io
);
727 parseprintf(DD_WPUT
,("parse: parsewput - PARSEIOC_SETCS\n"));
728 ok
= parse_setcs(dct
, &parse
->parse_io
);
731 mp
->b_datap
->db_type
= ok
? M_IOCACK
: M_IOCNAK
;
735 mp
->b_datap
->db_type
= M_IOCNAK
;
737 parseprintf(DD_WPUT
,("parse: parsewput qreply - %s\n", (mp
->b_datap
->db_type
== M_IOCNAK
) ? "M_IOCNAK" : "M_IOCACK"));
746 * read characters from streams buffers
753 while (*mp
!= (mblk_t
*)NULL
)
755 if ((*mp
)->b_wptr
- (*mp
)->b_rptr
)
757 return (unsigned long)(*(unsigned char *)((*mp
)->b_rptr
++));
761 register mblk_t
*mmp
= *mp
;
771 * convert incoming data
781 switch (type
= mp
->b_datap
->db_type
)
785 * anything we don't know will be put on queue
786 * the service routine will move it to the next one
788 parseprintf(DD_RPUT
,("parse: parserput - forward type 0x%x\n", type
));
789 if (canput(q
->q_next
) || (mp
->b_datap
->db_type
> QPCTL
))
800 register parsestream_t
* parse
= (parsestream_t
*)(void *)q
->q_ptr
;
801 register mblk_t
*nmp
;
802 register unsigned long ch
;
806 * get time on packet delivery
810 if (!(parse
->parse_status
& PARSE_ENABLE
))
812 parseprintf(DD_RPUT
,("parse: parserput - parser disabled - forward type 0x%x\n", type
));
813 if (canput(q
->q_next
) || (mp
->b_datap
->db_type
> QPCTL
))
822 parseprintf(DD_RPUT
,("parse: parserput - M_%s\n", (type
== M_DATA
) ? "DATA" : "BREAK"));
827 * parse packet looking for start an end characters
829 while (mp
!= (mblk_t
*)NULL
)
832 if (ch
!= ~0 && parse_ioread(&parse
->parse_io
, (unsigned int)ch
, &ctime
))
835 * up up and away (hopefully ...)
836 * don't press it if resources are tight or nobody wants it
838 nmp
= (mblk_t
*)NULL
;
839 if (canput(parse
->parse_queue
->q_next
) && (nmp
= allocb(sizeof(parsetime_t
), BPRI_MED
)))
841 bcopy((caddr_t
)&parse
->parse_io
.parse_dtime
, (caddr_t
)nmp
->b_rptr
, sizeof(parsetime_t
));
842 nmp
->b_wptr
+= sizeof(parsetime_t
);
843 putnext(parse
->parse_queue
, nmp
);
846 if (nmp
) freemsg(nmp
);
847 parse_iodone(&parse
->parse_io
);
853 if (parse_ioread(&parse
->parse_io
, (unsigned int)0, &ctime
))
856 * up up and away (hopefully ...)
857 * don't press it if resources are tight or nobody wants it
859 nmp
= (mblk_t
*)NULL
;
860 if (canput(parse
->parse_queue
->q_next
) && (nmp
= allocb(sizeof(parsetime_t
), BPRI_MED
)))
862 bcopy((caddr_t
)&parse
->parse_io
.parse_dtime
, (caddr_t
)nmp
->b_rptr
, sizeof(parsetime_t
));
863 nmp
->b_wptr
+= sizeof(parsetime_t
);
864 putnext(parse
->parse_queue
, nmp
);
867 if (nmp
) freemsg(nmp
);
868 parse_iodone(&parse
->parse_io
);
877 * CD PPS support for non direct ISR hack
882 register parsestream_t
* parse
= (parsestream_t
*)(void *)q
->q_ptr
;
884 register mblk_t
*nmp
;
885 register int status
= cd_invert
^ (type
== M_UNHANGUP
);
889 parseprintf(DD_RPUT
,("parse: parserput - M_%sHANGUP\n", (type
== M_HANGUP
) ? "" : "UN"));
891 if ((parse
->parse_status
& PARSE_ENABLE
) &&
892 parse_iopps(&parse
->parse_io
, (int)(status
? SYNC_ONE
: SYNC_ZERO
), &ctime
))
894 nmp
= (mblk_t
*)NULL
;
895 if (canput(parse
->parse_queue
->q_next
) && (nmp
= allocb(sizeof(parsetime_t
), BPRI_MED
)))
897 bcopy((caddr_t
)&parse
->parse_io
.parse_dtime
, (caddr_t
)nmp
->b_rptr
, sizeof(parsetime_t
));
898 nmp
->b_wptr
+= sizeof(parsetime_t
);
899 putnext(parse
->parse_queue
, nmp
);
902 if (nmp
) freemsg(nmp
);
903 parse_iodone(&parse
->parse_io
);
907 if (canput(q
->q_next
) || (mp
->b_datap
->db_type
> QPCTL
))
916 parse
->parse_ppsclockev
.tv
= ctime
.tv
;
917 ++(parse
->parse_ppsclockev
.serial
);
924 static int init_zs_linemon
P((queue_t
*, queue_t
*)); /* handle line monitor for "zs" driver */
925 static void close_zs_linemon
P((queue_t
*, queue_t
*));
927 /*-------------------- CD isr status monitor ---------------*/
934 register queue_t
*dq
;
938 * we ARE doing very bad things down here (basically stealing ISR
941 * so we chase down the STREAMS stack searching for the driver
942 * and if this is a known driver we insert our ISR routine for
943 * status changes in to the ExternalStatus handling hook
947 dq
= dq
->q_next
; /* skip down to driver */
951 * find appropriate driver dependent routine
953 if (dq
->q_qinfo
&& dq
->q_qinfo
->qi_minfo
)
955 register char *dname
= dq
->q_qinfo
->qi_minfo
->mi_idname
;
957 parseprintf(DD_INSTALL
, ("init_linemon: driver is \"%s\"\n", dname
));
960 if (dname
&& !Strcmp(dname
, "zs"))
962 return init_zs_linemon(dq
, q
);
967 parseprintf(DD_INSTALL
, ("init_linemon: driver \"%s\" not suitable for CD monitoring\n", dname
));
971 parseprintf(DD_INSTALL
, ("init_linemon: cannot find driver\n"));
978 register queue_t
*my_q
982 * find appropriate driver dependent routine
984 if (q
->q_qinfo
&& q
->q_qinfo
->qi_minfo
)
986 register char *dname
= q
->q_qinfo
->qi_minfo
->mi_idname
;
989 if (dname
&& !Strcmp(dname
, "zs"))
991 close_zs_linemon(q
, my_q
);
994 parseprintf(DD_INSTALL
, ("close_linemon: cannot find driver close routine for \"%s\"\n", dname
));
997 parseprintf(DD_INSTALL
, ("close_linemon: cannot find driver name\n"));
1002 #include <sundev/zsreg.h>
1003 #include <sundev/zscom.h>
1004 #include <sundev/zsvar.h>
1006 static unsigned long cdmask
= ZSRR0_CD
;
1011 struct zsops
*oldzsops
;
1014 struct zsops
*emergencyzs
;
1015 extern void zsopinit
P((struct zscom
*, struct zsops
*));
1016 static int zs_xsisr
P((struct zscom
*)); /* zs external status interupt handler */
1020 register queue_t
*q
,
1021 register queue_t
*my_q
1024 register struct zscom
*zs
;
1025 register struct savedzsops
*szs
;
1026 register parsestream_t
*parsestream
= (parsestream_t
*)(void *)my_q
->q_ptr
;
1028 * we expect the zsaline pointer in the q_data pointer
1029 * from there on we insert our on EXTERNAL/STATUS ISR routine
1030 * into the interrupt path, before the standard handler
1032 zs
= ((struct zsaline
*)(void *)q
->q_ptr
)->za_common
;
1036 * well - not found on startup - just say no (shouldn't happen though)
1045 * we do a direct replacement, in case others fiddle also
1046 * if somebody else grabs our hook and we disconnect
1047 * we are in DEEP trouble - panic is likely to be next, sorry
1049 szs
= (struct savedzsops
*)(void *)kmem_alloc(sizeof(struct savedzsops
));
1051 if (szs
== (struct savedzsops
*)0)
1053 parseprintf(DD_INSTALL
, ("init_zs_linemon: CD monitor NOT installed - no memory\n"));
1059 parsestream
->parse_data
= (void *)szs
;
1063 parsestream
->parse_dqueue
= q
; /* remember driver */
1065 szs
->zsops
= *zs
->zs_ops
;
1066 szs
->zsops
.zsop_xsint
= zs_xsisr
; /* place our bastard */
1067 szs
->oldzsops
= zs
->zs_ops
;
1068 emergencyzs
= zs
->zs_ops
;
1070 zsopinit(zs
, &szs
->zsops
); /* hook it up */
1074 parseprintf(DD_INSTALL
, ("init_zs_linemon: CD monitor installed\n"));
1082 * unregister our ISR routine - must call under splhigh()
1086 register queue_t
*q
,
1087 register queue_t
*my_q
1090 register struct zscom
*zs
;
1091 register parsestream_t
*parsestream
= (parsestream_t
*)(void *)my_q
->q_ptr
;
1093 zs
= ((struct zsaline
*)(void *)q
->q_ptr
)->za_common
;
1097 * well - not found on startup - just say no (shouldn't happen though)
1103 register struct savedzsops
*szs
= (struct savedzsops
*)parsestream
->parse_data
;
1105 zsopinit(zs
, szs
->oldzsops
); /* reset to previous handler functions */
1107 kmem_free((caddr_t
)szs
, sizeof (struct savedzsops
));
1109 parseprintf(DD_INSTALL
, ("close_zs_linemon: CD monitor deleted\n"));
1114 #define MAXDEPTH 50 /* maximum allowed stream crawl */
1117 extern void hardpps
P((struct timeval
*, long));
1119 extern struct timeval timestamp
;
1121 extern struct timeval pps_time
;
1126 * take external status interrupt (only CD interests us)
1133 register struct zsaline
*za
= (struct zsaline
*)(void *)zs
->zs_priv
;
1134 register struct zscc_device
*zsaddr
= zs
->zs_addr
;
1135 register queue_t
*q
;
1136 register unsigned char zsstatus
;
1137 register int loopcheck
;
1138 register char *dname
;
1140 register unsigned int s
;
1145 * pick up current state
1147 zsstatus
= zsaddr
->zscc_control
;
1149 if ((za
->za_rr0
^ zsstatus
) & (cdmask
))
1151 timestamp_t cdevent
;
1152 register int status
;
1154 za
->za_rr0
= (za
->za_rr0
& ~(cdmask
)) | (zsstatus
& (cdmask
));
1159 usec
= timestamp
.tv_usec
;
1161 usec
= pps_time
.tv_usec
;
1167 uniqtime(&cdevent
.tv
);
1176 status
= cd_invert
? (zsstatus
& cdmask
) == 0 : (zsstatus
& cdmask
) != 0;
1181 usec
= cdevent
.tv
.tv_usec
- usec
;
1185 hardpps(&cdevent
.tv
, usec
);
1189 q
= za
->za_ttycommon
.t_readq
;
1192 * ok - now the hard part - find ourself
1194 loopcheck
= MAXDEPTH
;
1198 if (q
->q_qinfo
&& q
->q_qinfo
->qi_minfo
)
1200 dname
= q
->q_qinfo
->qi_minfo
->mi_idname
;
1202 if (!Strcmp(dname
, parseinfo
.st_rdinit
->qi_minfo
->mi_idname
))
1205 * back home - phew (hopping along stream queues might
1206 * prove dangerous to your health)
1209 if ((((parsestream_t
*)(void *)q
->q_ptr
)->parse_status
& PARSE_ENABLE
) &&
1210 parse_iopps(&((parsestream_t
*)(void *)q
->q_ptr
)->parse_io
, (int)(status
? SYNC_ONE
: SYNC_ZERO
), &cdevent
))
1213 * XXX - currently we do not pass up the message, as
1215 * for a correct behaviour wee need to block out
1216 * processing until parse_iodone has been posted via
1217 * a softcall-ed routine which does the message pass-up
1218 * right now PPS information relies on input being
1221 parse_iodone(&((parsestream_t
*)(void *)q
->q_ptr
)->parse_io
);
1226 ((parsestream_t
*)(void *)q
->q_ptr
)->parse_ppsclockev
.tv
= cdevent
.tv
;
1227 ++(((parsestream_t
*)(void *)q
->q_ptr
)->parse_ppsclockev
.serial
);
1230 parseprintf(DD_ISR
, ("zs_xsisr: CD event %s has been posted for \"%s\"\n", status
? "ONE" : "ZERO", dname
));
1239 panic("zs_xsisr: STREAMS Queue corrupted - CD event");
1244 * only pretend that CD has been handled
1248 if (!((za
->za_rr0
^ zsstatus
) & ~(cdmask
)))
1251 * all done - kill status indication and return
1253 zsaddr
->zscc_control
= ZSWR0_RESET_STATUS
; /* might kill other conditions here */
1258 if (zsstatus
& cdmask
) /* fake CARRIER status */
1259 za
->za_flags
|= ZAS_CARR_ON
;
1261 za
->za_flags
&= ~ZAS_CARR_ON
;
1264 * we are now gathered here to process some unusual external status
1266 * any CD events have also been handled and shouldn't be processed
1267 * by the original routine (unless we have a VERY busy port pin)
1268 * some initializations are done here, which could have been done before for
1269 * both code paths but have been avoided for minimum path length to
1270 * the uniq_time routine
1273 q
= za
->za_ttycommon
.t_readq
;
1275 loopcheck
= MAXDEPTH
;
1278 * the real thing for everything else ...
1282 if (q
->q_qinfo
&& q
->q_qinfo
->qi_minfo
)
1284 dname
= q
->q_qinfo
->qi_minfo
->mi_idname
;
1285 if (!Strcmp(dname
, parseinfo
.st_rdinit
->qi_minfo
->mi_idname
))
1287 register int (*zsisr
) P((struct zscom
*));
1290 * back home - phew (hopping along stream queues might
1291 * prove dangerous to your health)
1293 if ((zsisr
= ((struct savedzsops
*)((parsestream_t
*)(void *)q
->q_ptr
)->parse_data
)->oldzsops
->zsop_xsint
))
1296 panic("zs_xsisr: unable to locate original ISR");
1298 parseprintf(DD_ISR
, ("zs_xsisr: non CD event was processed for \"%s\"\n", dname
));
1300 * now back to our program ...
1310 panic("zs_xsisr: STREAMS Queue corrupted - non CD event");
1315 * last resort - shouldn't even come here as it indicates
1316 * corrupted TTY structures
1318 printf("zs_zsisr: looking for \"%s\" - found \"%s\" - taking EMERGENCY path\n", parseinfo
.st_rdinit
->qi_minfo
->mi_idname
, dname
? dname
: "-NIL-");
1320 if (emergencyzs
&& emergencyzs
->zsop_xsint
)
1321 emergencyzs
->zsop_xsint(zs
);
1323 panic("zs_xsisr: no emergency ISR handler");
1332 * Revision 4.11 2005/04/16 17:32:10 kardel
1335 * Revision 4.10 2004/11/14 16:06:08 kardel
1338 * Revision 4.9 2004/11/14 15:29:41 kardel
1339 * support PPSAPI, upgrade Copyright to Berkeley style
1341 * Revision 4.7 1999/11/28 09:13:53 kardel
1344 * Revision 4.6 1998/12/20 23:45:31 kardel
1345 * fix types and warnings
1347 * Revision 4.5 1998/11/15 21:23:38 kardel
1348 * ntp_memset() replicated in Sun kernel files
1350 * Revision 4.4 1998/06/13 12:15:59 kardel
1351 * superfluous variable removed
1353 * Revision 4.3 1998/06/12 15:23:08 kardel
1355 * adjust for ansi2knr
1357 * Revision 4.2 1998/05/24 18:16:22 kardel
1358 * moved copy of shadow status to the beginning
1360 * Revision 4.1 1998/05/24 09:38:47 kardel
1361 * streams initiated iopps calls (M_xHANGUP) are now consistent with the
1362 * respective calls from zs_xsisr()
1363 * simulation of CARRIER status to avoid unecessary M_xHANGUP messages
1365 * Revision 4.0 1998/04/10 19:45:38 kardel
1366 * Start 4.0 release version numbering
1368 * from V3 3.37 log info deleted 1998/04/11 kardel