1 /* $NetBSD: parsesolaris.c,v 1.2 2003/12/04 16:23:37 drochner Exp $ */
4 * /src/NTP/ntp4-dev/libparse/parsesolaris.c,v 4.11 2005/04/16 17:32:10 kardel RELEASE_20050508_A
6 * parsesolaris.c,v 4.11 2005/04/16 17:32:10 kardel RELEASE_20050508_A
8 * STREAMS module for reference clocks
10 * Copyright (c) 1995-2005 by Frank Kardel <kardel <AT> ntp.org>
11 * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universität Erlangen-Nürnberg, Germany
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 * 3. Neither the name of the author nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
25 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 #define _KERNEL /* it is a _KERNEL module */
42 static char rcsid
[] = "parsesolaris.c,v 4.11 2005/04/16 17:32:10 kardel RELEASE_20050508_A";
45 #include <sys/types.h>
47 #include <sys/errno.h>
49 #include <sys/termios.h>
50 #include <sys/stream.h>
51 #include <sys/strtty.h>
52 #include <sys/stropts.h>
53 #include <sys/modctl.h>
55 #include <sys/sunddi.h>
56 #ifdef __GNUC__ /* makes it compile on Solaris 2.6 - acc doesn't like it -- GREAT! */
62 #include <sys/parsestreams.h>
64 /*--------------- loadable driver section -----------------------------*/
66 static struct streamtab parseinfo
;
68 static struct fmodsw fmod_templ
=
70 "parse", /* module name */
71 &parseinfo
, /* module information */
72 D_NEW
|D_MP
|D_MTQPAIR
, /* exclusive for q pair */
76 extern struct mod_ops mod_strmodops
;
78 static struct modlstrmod modlstrmod
=
80 &mod_strmodops
, /* a STREAMS module */
81 "PARSE - NTP reference", /* name this baby - keep room for revision number */
85 static struct modlinkage modlinkage
=
95 * module management routines
103 static char revision
[] = "4.6";
112 * copy RCS revision into Drv_name
114 * are we forcing RCS here to do things it was not built for ?
121 * if present. - not necessary on a -kv co (cvs export)
123 while (*s
&& (*s
!= ' '))
130 t
= modlstrmod
.strmod_linkinfo
;
131 while (*t
&& (*t
!= ' '))
138 while (*S
&& (((*S
>= '0') && (*S
<= '9')) || (*S
== '.')))
143 if (*s
&& *t
&& (S
> s
))
145 if (strlen(t
) >= (S
- s
))
147 (void) strncpy(t
, s
, (unsigned)(S
- s
));
150 return (mod_install(&modlinkage
));
156 struct modinfo
*modinfop
159 return (mod_info(&modlinkage
, modinfop
));
168 if (mod_remove(&modlinkage
) != DDI_SUCCESS
)
176 /*--------------- stream module definition ----------------------------*/
178 static int parseopen
P((queue_t
*, dev_t
*, int, int, cred_t
*));
179 static int parseclose
P((queue_t
*, int));
180 static int parsewput
P((queue_t
*, mblk_t
*));
181 static int parserput
P((queue_t
*, mblk_t
*));
182 static int parsersvc
P((queue_t
*));
184 static struct module_info driverinfo
=
186 0, /* module ID number */
187 fmod_templ
.f_name
, /* module name - why repeated here ? compat ?*/
188 0, /* minimum accepted packet size */
189 INFPSZ
, /* maximum accepted packet size */
190 1, /* high water mark - flow control */
191 0 /* low water mark - flow control */
194 static struct qinit rinit
= /* read queue definition */
196 parserput
, /* put procedure */
197 parsersvc
, /* service procedure */
198 parseopen
, /* open procedure */
199 parseclose
, /* close procedure */
200 NULL
, /* admin procedure - NOT USED FOR NOW */
201 &driverinfo
, /* information structure */
202 NULL
/* statistics */
205 static struct qinit winit
= /* write queue definition */
207 parsewput
, /* put procedure */
208 NULL
, /* service procedure */
209 NULL
, /* open procedure */
210 NULL
, /* close procedure */
211 NULL
, /* admin procedure - NOT USED FOR NOW */
212 &driverinfo
, /* information structure */
213 NULL
/* statistics */
216 static struct streamtab parseinfo
= /* stream info element for parse driver */
218 &rinit
, /* read queue */
219 &winit
, /* write queue */
224 /*--------------- driver data structures ----------------------------*/
227 * we usually have an inverted signal - but you
228 * can change this to suit your needs
230 int cd_invert
= 1; /* invert status of CD line - PPS support via CD input */
238 /*--------------- module implementation -----------------------------*/
240 #define TIMEVAL_USADD(_X_, _US_) do {\
241 (_X_)->tv_usec += (_US_);\
242 if ((_X_)->tv_usec >= 1000000)\
245 (_X_)->tv_usec -= 1000000;\
249 static int init_linemon
P((queue_t
*));
250 static void close_linemon
P((queue_t
*, queue_t
*));
252 #define M_PARSE 0x0001
253 #define M_NOPARSE 0x0002
277 if (lev
& parsedebug
)
278 vcmn_err(CE_CONT
, (char *)form
, ap
);
291 pprintf(DD_OPEN
,"parse: SETUP_STREAM - setting up stream for q=%x\n", q
);
293 mp
= allocb(sizeof(struct stroptions
), BPRI_MED
);
296 struct stroptions
*str
= (struct stroptions
*)mp
->b_wptr
;
298 str
->so_flags
= SO_READOPT
|SO_HIWAT
|SO_LOWAT
|SO_ISNTTY
;
299 str
->so_readopt
= (mode
== M_PARSE
) ? RMSGD
: RNORM
;
300 str
->so_hiwat
= (mode
== M_PARSE
) ? sizeof(parsetime_t
) : 256;
302 mp
->b_datap
->db_type
= M_SETOPTS
;
303 mp
->b_wptr
+= sizeof(struct stroptions
);
305 panic("NULL q - strange");
307 return putctl1(WR(q
)->q_next
, M_CTL
, (mode
== M_PARSE
) ? MC_SERVICEIMM
:
312 pprintf(DD_OPEN
, "parse: setup_stream - FAILED - no MEMORY for allocb\n");
327 register parsestream_t
*parse
;
328 static int notice
= 0;
330 pprintf(DD_OPEN
, "parse: OPEN - q=%x\n", q
);
332 if (sflag
!= MODOPEN
)
333 { /* open only for modules */
334 pprintf(DD_OPEN
, "parse: OPEN - FAILED - not MODOPEN\n");
338 if (q
->q_ptr
!= (caddr_t
)NULL
)
340 pprintf(DD_OPEN
, "parse: OPEN - FAILED - EXCLUSIVE ONLY\n");
344 q
->q_ptr
= (caddr_t
)kmem_alloc(sizeof(parsestream_t
), KM_SLEEP
);
345 if (q
->q_ptr
== (caddr_t
)0)
350 pprintf(DD_OPEN
, "parse: OPEN - parse area q=%x, q->q_ptr=%x\n", q
, q
->q_ptr
);
351 WR(q
)->q_ptr
= q
->q_ptr
;
352 pprintf(DD_OPEN
, "parse: OPEN - WQ parse area q=%x, q->q_ptr=%x\n", WR(q
), WR(q
)->q_ptr
);
354 parse
= (parsestream_t
*) q
->q_ptr
;
355 bzero((caddr_t
)parse
, sizeof(*parse
));
356 parse
->parse_queue
= q
;
357 parse
->parse_status
= PARSE_ENABLE
;
358 parse
->parse_ppsclockev
.tv
.tv_sec
= 0;
359 parse
->parse_ppsclockev
.tv
.tv_usec
= 0;
360 parse
->parse_ppsclockev
.serial
= 0;
364 pprintf(DD_OPEN
, "parse: OPEN - initializing io subsystem q=%x\n", q
);
366 if (!parse_ioinit(&parse
->parse_io
))
373 kmem_free((caddr_t
)parse
, sizeof(parsestream_t
));
378 pprintf(DD_OPEN
, "parse: OPEN - initializing stream q=%x\n", q
);
380 if (setup_stream(q
, M_PARSE
))
382 (void) init_linemon(q
); /* hook up PPS ISR routines if possible */
383 pprintf(DD_OPEN
, "parse: OPEN - SUCCEEDED\n");
386 * I know that you know the delete key, but you didn't write this
387 * code, did you ? - So, keep the message in here.
391 cmn_err(CE_CONT
, "?%s: Copyright (c) 1993-2005, Frank Kardel\n", modlstrmod
.strmod_linkinfo
);
401 kmem_free((caddr_t
)parse
, sizeof(parsestream_t
));
414 register parsestream_t
*parse
= (parsestream_t
*)q
->q_ptr
;
415 register unsigned long s
;
417 pprintf(DD_CLOSE
, "parse: CLOSE\n");
423 if (parse
->parse_dqueue
)
424 close_linemon(parse
->parse_dqueue
, q
);
425 parse
->parse_dqueue
= (queue_t
*)0;
429 parse_ioend(&parse
->parse_io
);
431 kmem_free((caddr_t
)parse
, sizeof(parsestream_t
));
433 q
->q_ptr
= (caddr_t
)NULL
;
434 WR(q
)->q_ptr
= (caddr_t
)NULL
;
440 * move unrecognized stuff upward
449 while ((mp
= getq(q
)))
451 if (canputnext(q
) || (mp
->b_datap
->db_type
> QPCTL
))
454 pprintf(DD_RSVC
, "parse: RSVC - putnext\n");
459 pprintf(DD_RSVC
, "parse: RSVC - flow control wait\n");
468 * send stuff down - dont care about
478 register mblk_t
*datap
;
479 register struct iocblk
*iocp
;
480 parsestream_t
*parse
= (parsestream_t
*)q
->q_ptr
;
482 pprintf(DD_WPUT
, "parse: parsewput\n");
484 switch (mp
->b_datap
->db_type
)
491 iocp
= (struct iocblk
*)mp
->b_rptr
;
492 switch (iocp
->ioc_cmd
)
495 pprintf(DD_WPUT
, "parse: parsewput - forward M_IOCTL\n");
501 * taken from Craig Leres ppsclock module (and modified)
503 datap
= allocb(sizeof(struct ppsclockev
), BPRI_MED
);
504 if (datap
== NULL
|| mp
->b_cont
)
506 mp
->b_datap
->db_type
= M_IOCNAK
;
507 iocp
->ioc_error
= (datap
== NULL
) ? ENOMEM
: EINVAL
;
515 *(struct ppsclockev
*)datap
->b_wptr
= parse
->parse_ppsclockev
;
517 sizeof(struct ppsclockev
) / sizeof(*datap
->b_wptr
);
518 mp
->b_datap
->db_type
= M_IOCACK
;
519 iocp
->ioc_count
= sizeof(struct ppsclockev
);
523 case PARSEIOC_ENABLE
:
524 case PARSEIOC_DISABLE
:
526 parse
->parse_status
= (parse
->parse_status
& (unsigned)~PARSE_ENABLE
) |
527 (iocp
->ioc_cmd
== PARSEIOC_ENABLE
) ?
529 if (!setup_stream(RD(q
), (parse
->parse_status
& PARSE_ENABLE
) ?
530 M_PARSE
: M_NOPARSE
))
532 mp
->b_datap
->db_type
= M_IOCNAK
;
536 mp
->b_datap
->db_type
= M_IOCACK
;
542 case PARSEIOC_TIMECODE
:
543 case PARSEIOC_SETFMT
:
544 case PARSEIOC_GETFMT
:
546 if (iocp
->ioc_count
== sizeof(parsectl_t
))
548 parsectl_t
*dct
= (parsectl_t
*)mp
->b_cont
->b_rptr
;
550 switch (iocp
->ioc_cmd
)
552 case PARSEIOC_TIMECODE
:
553 pprintf(DD_WPUT
, "parse: parsewput - PARSEIOC_TIMECODE\n");
554 ok
= parse_timecode(dct
, &parse
->parse_io
);
557 case PARSEIOC_SETFMT
:
558 pprintf(DD_WPUT
, "parse: parsewput - PARSEIOC_SETFMT\n");
559 ok
= parse_setfmt(dct
, &parse
->parse_io
);
562 case PARSEIOC_GETFMT
:
563 pprintf(DD_WPUT
, "parse: parsewput - PARSEIOC_GETFMT\n");
564 ok
= parse_getfmt(dct
, &parse
->parse_io
);
568 pprintf(DD_WPUT
, "parse: parsewput - PARSEIOC_SETCS\n");
569 ok
= parse_setcs(dct
, &parse
->parse_io
);
572 mp
->b_datap
->db_type
= ok
? M_IOCACK
: M_IOCNAK
;
576 mp
->b_datap
->db_type
= M_IOCNAK
;
578 pprintf(DD_WPUT
, "parse: parsewput qreply - %s\n", (mp
->b_datap
->db_type
== M_IOCNAK
) ? "M_IOCNAK" : "M_IOCACK");
587 * read characters from streams buffers
594 while (*mp
!= (mblk_t
*)NULL
)
596 if ((*mp
)->b_wptr
- (*mp
)->b_rptr
)
598 return (unsigned long)(*(unsigned char *)((*mp
)->b_rptr
++));
602 register mblk_t
*mmp
= *mp
;
608 return (unsigned long)~0;
612 * convert incoming data
620 register unsigned char type
;
623 switch (type
= mp
->b_datap
->db_type
)
627 * anything we don't know will be put on queue
628 * the service routine will move it to the next one
630 pprintf(DD_RPUT
, "parse: parserput - forward type 0x%x\n", type
);
632 if (canputnext(q
) || (mp
->b_datap
->db_type
> QPCTL
))
643 register parsestream_t
* parse
= (parsestream_t
*)q
->q_ptr
;
644 register mblk_t
*nmp
;
645 register unsigned long ch
;
647 timespec_t hres_time
;
650 * get time on packet delivery
652 gethrestime(&hres_time
);
653 ctime
.tv
.tv_sec
= hres_time
.tv_sec
;
654 ctime
.tv
.tv_usec
= hres_time
.tv_nsec
/ 1000;
656 if (!(parse
->parse_status
& PARSE_ENABLE
))
658 pprintf(DD_RPUT
, "parse: parserput - parser disabled - forward type 0x%x\n", type
);
659 if (canputnext(q
) || (mp
->b_datap
->db_type
> QPCTL
))
668 pprintf(DD_RPUT
, "parse: parserput - M_%s\n", (type
== M_DATA
) ? "DATA" : "BREAK");
672 * parse packet looking for start an end characters
674 while (mp
!= (mblk_t
*)NULL
)
677 if (ch
!= ~0 && parse_ioread(&parse
->parse_io
, (unsigned int)ch
, &ctime
))
680 * up up and away (hopefully ...)
681 * don't press it if resources are tight or nobody wants it
683 nmp
= (mblk_t
*)NULL
;
684 if (canputnext(parse
->parse_queue
) && (nmp
= allocb(sizeof(parsetime_t
), BPRI_MED
)))
686 bcopy((caddr_t
)&parse
->parse_io
.parse_dtime
, (caddr_t
)nmp
->b_rptr
, sizeof(parsetime_t
));
687 nmp
->b_wptr
+= sizeof(parsetime_t
);
688 putnext(parse
->parse_queue
, nmp
);
691 if (nmp
) freemsg(nmp
);
692 parse_iodone(&parse
->parse_io
);
698 if (parse_ioread(&parse
->parse_io
, (unsigned int)0, &ctime
))
701 * up up and away (hopefully ...)
702 * don't press it if resources are tight or nobody wants it
704 nmp
= (mblk_t
*)NULL
;
705 if (canputnext(parse
->parse_queue
) && (nmp
= allocb(sizeof(parsetime_t
), BPRI_MED
)))
707 bcopy((caddr_t
)&parse
->parse_io
.parse_dtime
, (caddr_t
)nmp
->b_rptr
, sizeof(parsetime_t
));
708 nmp
->b_wptr
+= sizeof(parsetime_t
);
709 putnext(parse
->parse_queue
, nmp
);
712 if (nmp
) freemsg(nmp
);
713 parse_iodone(&parse
->parse_io
);
722 * CD PPS support for non direct ISR hack
727 register parsestream_t
* parse
= (parsestream_t
*)q
->q_ptr
;
729 timespec_t hres_time
;
730 register mblk_t
*nmp
;
731 register int status
= cd_invert
^ (type
== M_UNHANGUP
);
733 gethrestime(&hres_time
);
734 ctime
.tv
.tv_sec
= hres_time
.tv_sec
;
735 ctime
.tv
.tv_usec
= hres_time
.tv_nsec
/ 1000;
737 pprintf(DD_RPUT
, "parse: parserput - M_%sHANGUP\n", (type
== M_HANGUP
) ? "" : "UN");
739 if ((parse
->parse_status
& PARSE_ENABLE
) &&
740 parse_iopps(&parse
->parse_io
, status
? SYNC_ONE
: SYNC_ZERO
, &ctime
))
742 nmp
= (mblk_t
*)NULL
;
743 if (canputnext(parse
->parse_queue
) && (nmp
= allocb(sizeof(parsetime_t
), BPRI_MED
)))
745 bcopy((caddr_t
)&parse
->parse_io
.parse_dtime
, (caddr_t
)nmp
->b_rptr
, sizeof(parsetime_t
));
746 nmp
->b_wptr
+= sizeof(parsetime_t
);
747 putnext(parse
->parse_queue
, nmp
);
750 if (nmp
) freemsg(nmp
);
751 parse_iodone(&parse
->parse_io
);
755 if (canputnext(q
) || (mp
->b_datap
->db_type
> QPCTL
))
764 parse
->parse_ppsclockev
.tv
= ctime
.tv
;
765 ++(parse
->parse_ppsclockev
.serial
);
772 static int init_zs_linemon
P((queue_t
*, queue_t
*)); /* handle line monitor for "zs" driver */
773 static void close_zs_linemon
P((queue_t
*, queue_t
*));
775 /*-------------------- CD isr status monitor ---------------*/
782 register queue_t
*dq
;
786 * we ARE doing very bad things down here (basically stealing ISR
789 * so we chase down the STREAMS stack searching for the driver
790 * and if this is a known driver we insert our ISR routine for
791 * status changes in to the ExternalStatus handling hook
795 dq
= dq
->q_next
; /* skip down to driver */
799 * find appropriate driver dependent routine
801 if (dq
->q_qinfo
&& dq
->q_qinfo
->qi_minfo
)
803 register char *dname
= dq
->q_qinfo
->qi_minfo
->mi_idname
;
805 pprintf(DD_INSTALL
, "init_linemon: driver is \"%s\"\n", dname
);
808 if (dname
&& !strcmp(dname
, "zs"))
810 return init_zs_linemon(dq
, q
);
815 pprintf(DD_INSTALL
, "init_linemon: driver \"%s\" not suitable for CD monitoring\n", dname
);
819 pprintf(DD_INSTALL
, "init_linemon: cannot find driver\n");
830 * find appropriate driver dependent routine
832 if (q
->q_qinfo
&& q
->q_qinfo
->qi_minfo
)
834 register char *dname
= q
->q_qinfo
->qi_minfo
->mi_idname
;
837 if (dname
&& !strcmp(dname
, "zs"))
839 close_zs_linemon(q
, my_q
);
842 pprintf(DD_INSTALL
, "close_linemon: cannot find driver close routine for \"%s\"\n", dname
);
845 pprintf(DD_INSTALL
, "close_linemon: cannot find driver name\n");
850 #include <sys/zsdev.h>
851 #include <sys/ser_async.h>
852 #include <sys/ser_zscc.h>
854 static void zs_xsisr
P((struct zscom
*)); /* zs external status interupt handler */
857 * there should be some docs telling how to get to
858 * sz:zs_usec_delay and zs:initzsops()
860 #define zs_usec_delay 5
865 struct zsops
*oldzsops
;
868 static struct zsops
*emergencyzs
;
876 register struct zscom
*zs
;
877 register struct savedzsops
*szs
;
878 register parsestream_t
*parsestream
= (parsestream_t
*)my_q
->q_ptr
;
880 * we expect the zsaline pointer in the q_data pointer
881 * from there on we insert our on EXTERNAL/STATUS ISR routine
882 * into the interrupt path, before the standard handler
884 zs
= ((struct asyncline
*)q
->q_ptr
)->za_common
;
888 * well - not found on startup - just say no (shouldn't happen though)
895 * we do a direct replacement, in case others fiddle also
896 * if somebody else grabs our hook and we disconnect
897 * we are in DEEP trouble - panic is likely to be next, sorry
899 szs
= (struct savedzsops
*) kmem_alloc(sizeof(struct savedzsops
), KM_SLEEP
);
901 if (szs
== (struct savedzsops
*)0)
903 pprintf(DD_INSTALL
, "init_zs_linemon: CD monitor NOT installed - no memory\n");
909 parsestream
->parse_data
= (void *)szs
;
911 mutex_enter(zs
->zs_excl
);
913 parsestream
->parse_dqueue
= q
; /* remember driver */
915 szs
->zsops
= *zs
->zs_ops
;
916 szs
->zsops
.zsop_xsint
= (void (*) P((struct zscom
*)))zs_xsisr
; /* place our bastard */
917 szs
->oldzsops
= zs
->zs_ops
;
918 emergencyzs
= zs
->zs_ops
;
920 zs
->zs_ops
= &szs
->zsops
; /* hook it up */
922 * XXX: this is usually done via zsopinit()
923 * - have yet to find a way to call that routine
925 zs
->zs_xsint
= (void (*) P((struct zscom
*)))zs_xsisr
;
927 mutex_exit(zs
->zs_excl
);
929 pprintf(DD_INSTALL
, "init_zs_linemon: CD monitor installed\n");
937 * unregister our ISR routine - must call under splhigh() (or
938 * whatever block ZS status interrupts)
946 register struct zscom
*zs
;
947 register parsestream_t
*parsestream
= (parsestream_t
*)my_q
->q_ptr
;
949 zs
= ((struct asyncline
*)q
->q_ptr
)->za_common
;
953 * well - not found on startup - just say no (shouldn't happen though)
959 register struct savedzsops
*szs
= (struct savedzsops
*)parsestream
->parse_data
;
961 mutex_enter(zs
->zs_excl
);
963 zs
->zs_ops
= szs
->oldzsops
; /* reset to previous handler functions */
965 * XXX: revert xsint (usually done via zsopinit() - have still to find
966 * a way to call that bugger
968 zs
->zs_xsint
= zs
->zs_ops
->zsop_xsint
;
970 mutex_exit(zs
->zs_excl
);
972 kmem_free((caddr_t
)szs
, sizeof (struct savedzsops
));
974 pprintf(DD_INSTALL
, "close_zs_linemon: CD monitor deleted\n");
979 #define ZSRR0_IGNORE (ZSRR0_CD|ZSRR0_SYNC|ZSRR0_CTS)
981 #define MAXDEPTH 50 /* maximum allowed stream crawl */
984 * take external status interrupt (only CD interests us)
991 register struct asyncline
*za
= (struct asyncline
*)zs
->zs_priv
;
993 register unsigned char zsstatus
;
994 register int loopcheck
;
995 register unsigned char cdstate
;
996 register const char *dname
= "-UNKNOWN-";
997 timespec_t hres_time
;
1000 * pick up current state
1002 zsstatus
= SCC_READ0();
1004 if (za
->za_rr0
^ (cdstate
= zsstatus
& ZSRR0_CD
))
1006 timestamp_t cdevent
;
1007 register int status
;
1012 gethrestime(&hres_time
);
1013 cdevent
.tv
.tv_sec
= hres_time
.tv_sec
;
1014 cdevent
.tv
.tv_usec
= hres_time
.tv_nsec
/ 1000;
1016 q
= za
->za_ttycommon
.t_readq
;
1021 status
= cd_invert
? cdstate
== 0 : cdstate
!= 0;
1024 * ok - now the hard part - find ourself
1026 loopcheck
= MAXDEPTH
;
1030 if (q
->q_qinfo
&& q
->q_qinfo
->qi_minfo
)
1032 dname
= q
->q_qinfo
->qi_minfo
->mi_idname
;
1034 if (!strcmp(dname
, parseinfo
.st_rdinit
->qi_minfo
->mi_idname
))
1037 * back home - phew (hopping along stream queues might
1038 * prove dangerous to your health)
1041 if ((((parsestream_t
*)q
->q_ptr
)->parse_status
& PARSE_ENABLE
) &&
1042 parse_iopps(&((parsestream_t
*)q
->q_ptr
)->parse_io
, status
? SYNC_ONE
: SYNC_ZERO
, &cdevent
))
1045 * XXX - currently we do not pass up the message, as
1047 * for a correct behaviour wee need to block out
1048 * processing until parse_iodone has been posted via
1049 * a softcall-ed routine which does the message pass-up
1050 * right now PPS information relies on input being
1053 parse_iodone(&((parsestream_t
*)q
->q_ptr
)->parse_io
);
1058 ((parsestream_t
*)q
->q_ptr
)->parse_ppsclockev
.tv
= cdevent
.tv
;
1059 ++(((parsestream_t
*)q
->q_ptr
)->parse_ppsclockev
.serial
);
1062 pprintf(DD_ISR
, "zs_xsisr: CD event %s has been posted for \"%s\"\n", status
? "ONE" : "ZERO", dname
);
1071 panic("zs_xsisr: STREAMS Queue corrupted - CD event");
1075 if (cdstate
) /* fake CARRIER status - XXX currently not coordinated */
1076 za
->za_flags
|= ZAS_CARR_ON
;
1078 za
->za_flags
&= ~ZAS_CARR_ON
;
1081 * only pretend that CD and ignored transistion (SYNC,CTS)
1084 za
->za_rr0
= (za
->za_rr0
& ~ZSRR0_IGNORE
) | (zsstatus
& ZSRR0_IGNORE
);
1086 if (((za
->za_rr0
^ zsstatus
) & ~ZSRR0_IGNORE
) == 0)
1089 * all done - kill status indication and return
1091 SCC_WRITE0(ZSWR0_RESET_STATUS
); /* might kill other conditions here */
1096 pprintf(DD_ISR
, "zs_xsisr: non CD event 0x%x for \"%s\"\n",
1097 (za
->za_rr0
^ zsstatus
) & ~ZSRR0_CD
,dname
);
1099 * we are now gathered here to process some unusual external status
1101 * any CD events have also been handled and shouldn't be processed
1102 * by the original routine (unless we have a VERY busy port pin)
1103 * some initializations are done here, which could have been done before for
1104 * both code paths but have been avioded for minimum path length to
1105 * the uniq_time routine
1108 q
= za
->za_ttycommon
.t_readq
;
1110 loopcheck
= MAXDEPTH
;
1113 * the real thing for everything else ...
1117 if (q
->q_qinfo
&& q
->q_qinfo
->qi_minfo
)
1119 dname
= q
->q_qinfo
->qi_minfo
->mi_idname
;
1120 if (!strcmp(dname
, parseinfo
.st_rdinit
->qi_minfo
->mi_idname
))
1122 register void (*zsisr
) P((struct zscom
*));
1125 * back home - phew (hopping along stream queues might
1126 * prove dangerous to your health)
1128 if ((zsisr
= ((struct savedzsops
*)((parsestream_t
*)q
->q_ptr
)->parse_data
)->oldzsops
->zsop_xsint
))
1131 panic("zs_xsisr: unable to locate original ISR");
1133 pprintf(DD_ISR
, "zs_xsisr: non CD event was processed for \"%s\"\n", dname
);
1135 * now back to our program ...
1145 panic("zs_xsisr: STREAMS Queue corrupted - non CD event");
1150 * last resort - shouldn't even come here as it indicates
1151 * corrupted TTY structures
1153 printf("zs_zsisr: looking for \"%s\" - found \"%s\" - taking EMERGENCY path\n", parseinfo
.st_rdinit
->qi_minfo
->mi_idname
, dname
? dname
: "-NIL-");
1155 if (emergencyzs
&& emergencyzs
->zsop_xsint
)
1156 emergencyzs
->zsop_xsint(zs
);
1158 panic("zs_xsisr: no emergency ISR handler");
1166 * Revision 4.11 2005/04/16 17:32:10 kardel
1169 * Revision 4.10 2004/11/14 16:06:08 kardel
1172 * Revision 4.9 2004/11/14 15:29:41 kardel
1173 * support PPSAPI, upgrade Copyright to Berkeley style
1175 * Revision 4.6 1998/11/15 21:56:08 kardel
1176 * ntp_memset not necessary
1178 * Revision 4.5 1998/11/15 21:23:37 kardel
1179 * ntp_memset() replicated in Sun kernel files
1181 * Revision 4.4 1998/06/14 21:09:40 kardel
1184 * Revision 4.3 1998/06/13 12:14:59 kardel
1187 * allow for ansi2knr
1189 * Revision 4.2 1998/06/12 15:23:08 kardel
1191 * adjust for ansi2knr
1193 * Revision 4.1 1998/05/24 09:38:46 kardel
1194 * streams initiated iopps calls (M_xHANGUP) are now consistent with the
1195 * respective calls from zs_xsisr()
1196 * simulation of CARRIER status to avoid unecessary M_xHANGUP messages
1198 * Revision 4.0 1998/04/10 19:45:38 kardel
1199 * Start 4.0 release version numbering
1201 * from V3 3.28 log info deleted 1998/04/11 kardel