/contrib/ntp/libparse/parsestreams.c
https://bitbucket.org/freebsd/freebsd-head/ · C · 1367 lines · 937 code · 172 blank · 258 comment · 158 complexity · 8a3b36be009b19d929acac0205fa5a1f MD5 · raw file
- /*
- * /src/NTP/ntp4-dev/libparse/parsestreams.c,v 4.11 2005/04/16 17:32:10 kardel RELEASE_20050508_A
- *
- * parsestreams.c,v 4.11 2005/04/16 17:32:10 kardel RELEASE_20050508_A
- *
- * STREAMS module for reference clocks
- * (SunOS4.x)
- *
- * Copyright (c) 1995-2005 by Frank Kardel <kardel <AT> ntp.org>
- * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universität Erlangen-Nürnberg, Germany
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the author nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- */
- #define KERNEL /* MUST */
- #define VDDRV /* SHOULD */
- #ifdef HAVE_CONFIG_H
- # include "config.h"
- #endif
- #ifndef lint
- static char rcsid[] = "parsestreams.c,v 4.11 2005/04/16 17:32:10 kardel RELEASE_20050508_A";
- #endif
- #ifndef KERNEL
- #include "Bletch: MUST COMPILE WITH KERNEL DEFINE"
- #endif
- #include <sys/types.h>
- #include <sys/conf.h>
- #include <sys/buf.h>
- #include <sys/param.h>
- #include <sys/sysmacros.h>
- #include <sys/time.h>
- #include <sundev/mbvar.h>
- #include <sun/autoconf.h>
- #include <sys/stream.h>
- #include <sys/stropts.h>
- #include <sys/dir.h>
- #include <sys/signal.h>
- #include <sys/termios.h>
- #include <sys/termio.h>
- #include <sys/ttold.h>
- #include <sys/user.h>
- #include <sys/tty.h>
- #ifdef VDDRV
- #include <sun/vddrv.h>
- #endif
- #include "ntp_stdlib.h"
- #include "ntp_fp.h"
- /*
- * just make checking compilers more silent
- */
- extern int printf P((const char *, ...));
- extern int putctl1 P((queue_t *, int, int));
- extern int canput P((queue_t *));
- extern void putbq P((queue_t *, mblk_t *));
- extern void freeb P((mblk_t *));
- extern void qreply P((queue_t *, mblk_t *));
- extern void freemsg P((mblk_t *));
- extern void panic P((const char *, ...));
- extern void usec_delay P((int));
- #include "parse.h"
- #include "sys/parsestreams.h"
- /*
- * use microtime instead of uniqtime if advised to
- */
- #ifdef MICROTIME
- #define uniqtime microtime
- #endif
- #ifdef VDDRV
- static unsigned int parsebusy = 0;
- /*--------------- loadable driver section -----------------------------*/
- extern struct streamtab parseinfo;
- #ifdef PPS_SYNC
- static char mnam[] = "PARSEPPS "; /* name this baby - keep room for revision number */
- #else
- static char mnam[] = "PARSE "; /* name this baby - keep room for revision number */
- #endif
- struct vdldrv parsesync_vd =
- {
- VDMAGIC_PSEUDO, /* nothing like a real driver - a STREAMS module */
- mnam,
- };
- /*
- * strings support usually not in kernel
- */
- static int
- Strlen(
- register const char *s
- )
- {
- register int c;
- c = 0;
- if (s)
- {
- while (*s++)
- {
- c++;
- }
- }
- return c;
- }
- static void
- Strncpy(
- register char *t,
- register char *s,
- register int c
- )
- {
- if (s && t)
- {
- while ((c-- > 0) && (*t++ = *s++))
- ;
- }
- }
- static int
- Strcmp(
- register const char *s,
- register const char *t
- )
- {
- register int c = 0;
- if (!s || !t || (s == t))
- {
- return 0;
- }
- while (!(c = *s++ - *t++) && *s && *t)
- /* empty loop */;
-
- return c;
- }
- static int
- Strncmp(
- register char *s,
- register char *t,
- register int n
- )
- {
- register int c = 0;
- if (!s || !t || (s == t))
- {
- return 0;
- }
- while (n-- && !(c = *s++ - *t++) && *s && *t)
- /* empty loop */;
-
- return c;
- }
-
- void
- ntp_memset(
- char *a,
- int x,
- int c
- )
- {
- while (c-- > 0)
- *a++ = x;
- }
- /*
- * driver init routine
- * since no mechanism gets us into and out of the fmodsw, we have to
- * do it ourselves
- */
- /*ARGSUSED*/
- int
- xxxinit(
- unsigned int fc,
- struct vddrv *vdp,
- addr_t vdin,
- struct vdstat *vds
- )
- {
- extern struct fmodsw fmodsw[];
- extern int fmodcnt;
-
- struct fmodsw *fm = fmodsw;
- struct fmodsw *fmend = &fmodsw[fmodcnt];
- struct fmodsw *ifm = (struct fmodsw *)0;
- char *mname = parseinfo.st_rdinit->qi_minfo->mi_idname;
-
- switch (fc)
- {
- case VDLOAD:
- vdp->vdd_vdtab = (struct vdlinkage *)&parsesync_vd;
- /*
- * now, jog along fmodsw scanning for an empty slot
- * and deposit our name there
- */
- while (fm <= fmend)
- {
- if (!Strncmp(fm->f_name, mname, FMNAMESZ))
- {
- printf("vddrinit[%s]: STREAMS module already loaded.\n", mname);
- return(EBUSY);
- }
- else
- if ((ifm == (struct fmodsw *)0) &&
- (fm->f_name[0] == '\0') &&
- (fm->f_str == (struct streamtab *)0))
- {
- /*
- * got one - so move in
- */
- ifm = fm;
- break;
- }
- fm++;
- }
- if (ifm == (struct fmodsw *)0)
- {
- printf("vddrinit[%s]: no slot free for STREAMS module\n", mname);
- return (ENOSPC);
- }
- else
- {
- static char revision[] = "4.7";
- char *s, *S, *t;
-
- s = rcsid; /* NOOP - keep compilers happy */
- Strncpy(ifm->f_name, mname, FMNAMESZ);
- ifm->f_name[FMNAMESZ] = '\0';
- ifm->f_str = &parseinfo;
- /*
- * copy RCS revision into Drv_name
- *
- * are we forcing RCS here to do things it was not built for ?
- */
- s = revision;
- if (*s == '$')
- {
- /*
- * skip "$Revision: "
- * if present. - not necessary on a -kv co (cvs export)
- */
- while (*s && (*s != ' '))
- {
- s++;
- }
- if (*s == ' ') s++;
- }
-
- t = parsesync_vd.Drv_name;
- while (*t && (*t != ' '))
- {
- t++;
- }
- if (*t == ' ') t++;
-
- S = s;
- while (*S && (((*S >= '0') && (*S <= '9')) || (*S == '.')))
- {
- S++;
- }
-
- if (*s && *t && (S > s))
- {
- if (Strlen(t) >= (S - s))
- {
- (void) Strncpy(t, s, S - s);
- }
- }
- return (0);
- }
- break;
-
- case VDUNLOAD:
- if (parsebusy > 0)
- {
- printf("vddrinit[%s]: STREAMS module has still %d instances active.\n", mname, parsebusy);
- return (EBUSY);
- }
- else
- {
- while (fm <= fmend)
- {
- if (!Strncmp(fm->f_name, mname, FMNAMESZ))
- {
- /*
- * got it - kill entry
- */
- fm->f_name[0] = '\0';
- fm->f_str = (struct streamtab *)0;
- fm++;
-
- break;
- }
- fm++;
- }
- if (fm > fmend)
- {
- printf("vddrinit[%s]: cannot find entry for STREAMS module\n", mname);
- return (ENXIO);
- }
- else
- return (0);
- }
-
- case VDSTAT:
- return (0);
- default:
- return (EIO);
-
- }
- return EIO;
- }
- #endif
- /*--------------- stream module definition ----------------------------*/
- static int parseopen P((queue_t *, dev_t, int, int));
- static int parseclose P((queue_t *, int));
- static int parsewput P((queue_t *, mblk_t *));
- static int parserput P((queue_t *, mblk_t *));
- static int parsersvc P((queue_t *));
- static char mn[] = "parse";
- static struct module_info driverinfo =
- {
- 0, /* module ID number */
- mn, /* module name */
- 0, /* minimum accepted packet size */
- INFPSZ, /* maximum accepted packet size */
- 1, /* high water mark - flow control */
- 0 /* low water mark - flow control */
- };
- static struct qinit rinit = /* read queue definition */
- {
- parserput, /* put procedure */
- parsersvc, /* service procedure */
- parseopen, /* open procedure */
- parseclose, /* close procedure */
- NULL, /* admin procedure - NOT USED FOR NOW */
- &driverinfo, /* information structure */
- NULL /* statistics */
- };
- static struct qinit winit = /* write queue definition */
- {
- parsewput, /* put procedure */
- NULL, /* service procedure */
- NULL, /* open procedure */
- NULL, /* close procedure */
- NULL, /* admin procedure - NOT USED FOR NOW */
- &driverinfo, /* information structure */
- NULL /* statistics */
- };
- struct streamtab parseinfo = /* stream info element for dpr driver */
- {
- &rinit, /* read queue */
- &winit, /* write queue */
- NULL, /* read mux */
- NULL, /* write mux */
- NULL /* module auto push */
- };
- /*--------------- driver data structures ----------------------------*/
- /*
- * we usually have an inverted signal - but you
- * can change this to suit your needs
- */
- int cd_invert = 1; /* invert status of CD line - PPS support via CD input */
- int parsedebug = ~0;
- extern void uniqtime P((struct timeval *));
- /*--------------- module implementation -----------------------------*/
- #define TIMEVAL_USADD(_X_, _US_) {\
- (_X_)->tv_usec += (_US_);\
- if ((_X_)->tv_usec >= 1000000)\
- {\
- (_X_)->tv_sec++;\
- (_X_)->tv_usec -= 1000000;\
- }\
- } while (0)
- static int init_linemon P((queue_t *));
- static void close_linemon P((queue_t *, queue_t *));
- #define M_PARSE 0x0001
- #define M_NOPARSE 0x0002
- static int
- setup_stream(
- queue_t *q,
- int mode
- )
- {
- mblk_t *mp;
- mp = allocb(sizeof(struct stroptions), BPRI_MED);
- if (mp)
- {
- struct stroptions *str = (struct stroptions *)(void *)mp->b_rptr;
- str->so_flags = SO_READOPT|SO_HIWAT|SO_LOWAT;
- str->so_readopt = (mode == M_PARSE) ? RMSGD : RNORM;
- str->so_hiwat = (mode == M_PARSE) ? sizeof(parsetime_t) : 256;
- str->so_lowat = 0;
- mp->b_datap->db_type = M_SETOPTS;
- mp->b_wptr += sizeof(struct stroptions);
- putnext(q, mp);
- return putctl1(WR(q)->q_next, M_CTL, (mode == M_PARSE) ? MC_SERVICEIMM :
- MC_SERVICEDEF);
- }
- else
- {
- parseprintf(DD_OPEN,("parse: setup_stream - FAILED - no MEMORY for allocb\n"));
- return 0;
- }
- }
- /*ARGSUSED*/
- static int
- parseopen(
- queue_t *q,
- dev_t dev,
- int flag,
- int sflag
- )
- {
- register parsestream_t *parse;
- static int notice = 0;
-
- parseprintf(DD_OPEN,("parse: OPEN\n"));
-
- if (sflag != MODOPEN)
- { /* open only for modules */
- parseprintf(DD_OPEN,("parse: OPEN - FAILED - not MODOPEN\n"));
- return OPENFAIL;
- }
- if (q->q_ptr != (caddr_t)NULL)
- {
- u.u_error = EBUSY;
- parseprintf(DD_OPEN,("parse: OPEN - FAILED - EXCLUSIVE ONLY\n"));
- return OPENFAIL;
- }
- #ifdef VDDRV
- parsebusy++;
- #endif
-
- q->q_ptr = (caddr_t)kmem_alloc(sizeof(parsestream_t));
- if (q->q_ptr == (caddr_t)0)
- {
- parseprintf(DD_OPEN,("parse: OPEN - FAILED - no memory\n"));
- #ifdef VDDRV
- parsebusy--;
- #endif
- return OPENFAIL;
- }
- WR(q)->q_ptr = q->q_ptr;
-
- parse = (parsestream_t *)(void *)q->q_ptr;
- bzero((caddr_t)parse, sizeof(*parse));
- parse->parse_queue = q;
- parse->parse_status = PARSE_ENABLE;
- parse->parse_ppsclockev.tv.tv_sec = 0;
- parse->parse_ppsclockev.tv.tv_usec = 0;
- parse->parse_ppsclockev.serial = 0;
- if (!parse_ioinit(&parse->parse_io))
- {
- /*
- * ok guys - beat it
- */
- kmem_free((caddr_t)parse, sizeof(parsestream_t));
- #ifdef VDDRV
- parsebusy--;
- #endif
- return OPENFAIL;
- }
- if (setup_stream(q, M_PARSE))
- {
- (void) init_linemon(q); /* hook up PPS ISR routines if possible */
- parseprintf(DD_OPEN,("parse: OPEN - SUCCEEDED\n"));
- /*
- * I know that you know the delete key, but you didn't write this
- * code, did you ? - So, keep the message in here.
- */
- if (!notice)
- {
- #ifdef VDDRV
- printf("%s: Copyright (C) 1991-2005, Frank Kardel\n", parsesync_vd.Drv_name);
- #else
- printf("%s: Copyright (C) 1991-2005, Frank Kardel\n", "parsestreams.c,v 4.11 2005/04/16 17:32:10 kardel RELEASE_20050508_A");
- #endif
- notice = 1;
- }
- return MODOPEN;
- }
- else
- {
- kmem_free((caddr_t)parse, sizeof(parsestream_t));
- #ifdef VDDRV
- parsebusy--;
- #endif
- return OPENFAIL;
- }
- }
- /*ARGSUSED*/
- static int
- parseclose(
- queue_t *q,
- int flags
- )
- {
- register parsestream_t *parse = (parsestream_t *)(void *)q->q_ptr;
- register unsigned long s;
-
- parseprintf(DD_CLOSE,("parse: CLOSE\n"));
-
- s = splhigh();
-
- if (parse->parse_dqueue)
- close_linemon(parse->parse_dqueue, q);
- parse->parse_dqueue = (queue_t *)0;
- (void) splx(s);
-
- parse_ioend(&parse->parse_io);
- kmem_free((caddr_t)parse, sizeof(parsestream_t));
- q->q_ptr = (caddr_t)NULL;
- WR(q)->q_ptr = (caddr_t)NULL;
- #ifdef VDDRV
- parsebusy--;
- #endif
- return 0;
- }
- /*
- * move unrecognized stuff upward
- */
- static int
- parsersvc(
- queue_t *q
- )
- {
- mblk_t *mp;
-
- while ((mp = getq(q)))
- {
- if (canput(q->q_next) || (mp->b_datap->db_type > QPCTL))
- {
- putnext(q, mp);
- parseprintf(DD_RSVC,("parse: RSVC - putnext\n"));
- }
- else
- {
- putbq(q, mp);
- parseprintf(DD_RSVC,("parse: RSVC - flow control wait\n"));
- break;
- }
- }
- return 0;
- }
- /*
- * do ioctls and
- * send stuff down - dont care about
- * flow control
- */
- static int
- parsewput(
- queue_t *q,
- register mblk_t *mp
- )
- {
- register int ok = 1;
- register mblk_t *datap;
- register struct iocblk *iocp;
- parsestream_t *parse = (parsestream_t *)(void *)q->q_ptr;
-
- parseprintf(DD_WPUT,("parse: parsewput\n"));
-
- switch (mp->b_datap->db_type)
- {
- default:
- putnext(q, mp);
- break;
-
- case M_IOCTL:
- iocp = (struct iocblk *)(void *)mp->b_rptr;
- switch (iocp->ioc_cmd)
- {
- default:
- parseprintf(DD_WPUT,("parse: parsewput - forward M_IOCTL\n"));
- putnext(q, mp);
- break;
- case CIOGETEV:
- /*
- * taken from Craig Leres ppsclock module (and modified)
- */
- datap = allocb(sizeof(struct ppsclockev), BPRI_MED);
- if (datap == NULL || mp->b_cont)
- {
- mp->b_datap->db_type = M_IOCNAK;
- iocp->ioc_error = (datap == NULL) ? ENOMEM : EINVAL;
- if (datap != NULL)
- freeb(datap);
- qreply(q, mp);
- break;
- }
- mp->b_cont = datap;
- *(struct ppsclockev *)(void *)datap->b_wptr = parse->parse_ppsclockev;
- datap->b_wptr +=
- sizeof(struct ppsclockev) / sizeof(*datap->b_wptr);
- mp->b_datap->db_type = M_IOCACK;
- iocp->ioc_count = sizeof(struct ppsclockev);
- qreply(q, mp);
- break;
-
- case PARSEIOC_ENABLE:
- case PARSEIOC_DISABLE:
- {
- parse->parse_status = (parse->parse_status & (unsigned)~PARSE_ENABLE) |
- (iocp->ioc_cmd == PARSEIOC_ENABLE) ?
- PARSE_ENABLE : 0;
- if (!setup_stream(RD(q), (parse->parse_status & PARSE_ENABLE) ?
- M_PARSE : M_NOPARSE))
- {
- mp->b_datap->db_type = M_IOCNAK;
- }
- else
- {
- mp->b_datap->db_type = M_IOCACK;
- }
- qreply(q, mp);
- break;
- }
- case PARSEIOC_TIMECODE:
- case PARSEIOC_SETFMT:
- case PARSEIOC_GETFMT:
- case PARSEIOC_SETCS:
- if (iocp->ioc_count == sizeof(parsectl_t))
- {
- parsectl_t *dct = (parsectl_t *)(void *)mp->b_cont->b_rptr;
- switch (iocp->ioc_cmd)
- {
- case PARSEIOC_TIMECODE:
- parseprintf(DD_WPUT,("parse: parsewput - PARSEIOC_TIMECODE\n"));
- ok = parse_timecode(dct, &parse->parse_io);
- break;
-
- case PARSEIOC_SETFMT:
- parseprintf(DD_WPUT,("parse: parsewput - PARSEIOC_SETFMT\n"));
- ok = parse_setfmt(dct, &parse->parse_io);
- break;
- case PARSEIOC_GETFMT:
- parseprintf(DD_WPUT,("parse: parsewput - PARSEIOC_GETFMT\n"));
- ok = parse_getfmt(dct, &parse->parse_io);
- break;
- case PARSEIOC_SETCS:
- parseprintf(DD_WPUT,("parse: parsewput - PARSEIOC_SETCS\n"));
- ok = parse_setcs(dct, &parse->parse_io);
- break;
- }
- mp->b_datap->db_type = ok ? M_IOCACK : M_IOCNAK;
- }
- else
- {
- mp->b_datap->db_type = M_IOCNAK;
- }
- parseprintf(DD_WPUT,("parse: parsewput qreply - %s\n", (mp->b_datap->db_type == M_IOCNAK) ? "M_IOCNAK" : "M_IOCACK"));
- qreply(q, mp);
- break;
- }
- }
- return 0;
- }
- /*
- * read characters from streams buffers
- */
- static unsigned long
- rdchar(
- register mblk_t **mp
- )
- {
- while (*mp != (mblk_t *)NULL)
- {
- if ((*mp)->b_wptr - (*mp)->b_rptr)
- {
- return (unsigned long)(*(unsigned char *)((*mp)->b_rptr++));
- }
- else
- {
- register mblk_t *mmp = *mp;
-
- *mp = (*mp)->b_cont;
- freeb(mmp);
- }
- }
- return (unsigned)~0;
- }
- /*
- * convert incoming data
- */
- static int
- parserput(
- queue_t *q,
- mblk_t *mp
- )
- {
- unsigned char type;
-
- switch (type = mp->b_datap->db_type)
- {
- default:
- /*
- * anything we don't know will be put on queue
- * the service routine will move it to the next one
- */
- parseprintf(DD_RPUT,("parse: parserput - forward type 0x%x\n", type));
- if (canput(q->q_next) || (mp->b_datap->db_type > QPCTL))
- {
- putnext(q, mp);
- }
- else
- putq(q, mp);
- break;
-
- case M_BREAK:
- case M_DATA:
- {
- register parsestream_t * parse = (parsestream_t *)(void *)q->q_ptr;
- register mblk_t *nmp;
- register unsigned long ch;
- timestamp_t ctime;
- /*
- * get time on packet delivery
- */
- uniqtime(&ctime.tv);
- if (!(parse->parse_status & PARSE_ENABLE))
- {
- parseprintf(DD_RPUT,("parse: parserput - parser disabled - forward type 0x%x\n", type));
- if (canput(q->q_next) || (mp->b_datap->db_type > QPCTL))
- {
- putnext(q, mp);
- }
- else
- putq(q, mp);
- }
- else
- {
- parseprintf(DD_RPUT,("parse: parserput - M_%s\n", (type == M_DATA) ? "DATA" : "BREAK"));
- if (type == M_DATA)
- {
- /*
- * parse packet looking for start an end characters
- */
- while (mp != (mblk_t *)NULL)
- {
- ch = rdchar(&mp);
- if (ch != ~0 && parse_ioread(&parse->parse_io, (unsigned int)ch, &ctime))
- {
- /*
- * up up and away (hopefully ...)
- * don't press it if resources are tight or nobody wants it
- */
- nmp = (mblk_t *)NULL;
- if (canput(parse->parse_queue->q_next) && (nmp = allocb(sizeof(parsetime_t), BPRI_MED)))
- {
- bcopy((caddr_t)&parse->parse_io.parse_dtime, (caddr_t)nmp->b_rptr, sizeof(parsetime_t));
- nmp->b_wptr += sizeof(parsetime_t);
- putnext(parse->parse_queue, nmp);
- }
- else
- if (nmp) freemsg(nmp);
- parse_iodone(&parse->parse_io);
- }
- }
- }
- else
- {
- if (parse_ioread(&parse->parse_io, (unsigned int)0, &ctime))
- {
- /*
- * up up and away (hopefully ...)
- * don't press it if resources are tight or nobody wants it
- */
- nmp = (mblk_t *)NULL;
- if (canput(parse->parse_queue->q_next) && (nmp = allocb(sizeof(parsetime_t), BPRI_MED)))
- {
- bcopy((caddr_t)&parse->parse_io.parse_dtime, (caddr_t)nmp->b_rptr, sizeof(parsetime_t));
- nmp->b_wptr += sizeof(parsetime_t);
- putnext(parse->parse_queue, nmp);
- }
- else
- if (nmp) freemsg(nmp);
- parse_iodone(&parse->parse_io);
- }
- freemsg(mp);
- }
- break;
- }
- }
- /*
- * CD PPS support for non direct ISR hack
- */
- case M_HANGUP:
- case M_UNHANGUP:
- {
- register parsestream_t * parse = (parsestream_t *)(void *)q->q_ptr;
- timestamp_t ctime;
- register mblk_t *nmp;
- register int status = cd_invert ^ (type == M_UNHANGUP);
- uniqtime(&ctime.tv);
-
- parseprintf(DD_RPUT,("parse: parserput - M_%sHANGUP\n", (type == M_HANGUP) ? "" : "UN"));
- if ((parse->parse_status & PARSE_ENABLE) &&
- parse_iopps(&parse->parse_io, (int)(status ? SYNC_ONE : SYNC_ZERO), &ctime))
- {
- nmp = (mblk_t *)NULL;
- if (canput(parse->parse_queue->q_next) && (nmp = allocb(sizeof(parsetime_t), BPRI_MED)))
- {
- bcopy((caddr_t)&parse->parse_io.parse_dtime, (caddr_t)nmp->b_rptr, sizeof(parsetime_t));
- nmp->b_wptr += sizeof(parsetime_t);
- putnext(parse->parse_queue, nmp);
- }
- else
- if (nmp) freemsg(nmp);
- parse_iodone(&parse->parse_io);
- freemsg(mp);
- }
- else
- if (canput(q->q_next) || (mp->b_datap->db_type > QPCTL))
- {
- putnext(q, mp);
- }
- else
- putq(q, mp);
-
- if (status)
- {
- parse->parse_ppsclockev.tv = ctime.tv;
- ++(parse->parse_ppsclockev.serial);
- }
- }
- }
- return 0;
- }
- static int init_zs_linemon P((queue_t *, queue_t *)); /* handle line monitor for "zs" driver */
- static void close_zs_linemon P((queue_t *, queue_t *));
- /*-------------------- CD isr status monitor ---------------*/
- static int
- init_linemon(
- register queue_t *q
- )
- {
- register queue_t *dq;
-
- dq = WR(q);
- /*
- * we ARE doing very bad things down here (basically stealing ISR
- * hooks)
- *
- * so we chase down the STREAMS stack searching for the driver
- * and if this is a known driver we insert our ISR routine for
- * status changes in to the ExternalStatus handling hook
- */
- while (dq->q_next)
- {
- dq = dq->q_next; /* skip down to driver */
- }
- /*
- * find appropriate driver dependent routine
- */
- if (dq->q_qinfo && dq->q_qinfo->qi_minfo)
- {
- register char *dname = dq->q_qinfo->qi_minfo->mi_idname;
- parseprintf(DD_INSTALL, ("init_linemon: driver is \"%s\"\n", dname));
- #ifdef sun
- if (dname && !Strcmp(dname, "zs"))
- {
- return init_zs_linemon(dq, q);
- }
- else
- #endif
- {
- parseprintf(DD_INSTALL, ("init_linemon: driver \"%s\" not suitable for CD monitoring\n", dname));
- return 0;
- }
- }
- parseprintf(DD_INSTALL, ("init_linemon: cannot find driver\n"));
- return 0;
- }
- static void
- close_linemon(
- register queue_t *q,
- register queue_t *my_q
- )
- {
- /*
- * find appropriate driver dependent routine
- */
- if (q->q_qinfo && q->q_qinfo->qi_minfo)
- {
- register char *dname = q->q_qinfo->qi_minfo->mi_idname;
- #ifdef sun
- if (dname && !Strcmp(dname, "zs"))
- {
- close_zs_linemon(q, my_q);
- return;
- }
- parseprintf(DD_INSTALL, ("close_linemon: cannot find driver close routine for \"%s\"\n", dname));
- #endif
- }
- parseprintf(DD_INSTALL, ("close_linemon: cannot find driver name\n"));
- }
- #ifdef sun
- #include <sundev/zsreg.h>
- #include <sundev/zscom.h>
- #include <sundev/zsvar.h>
- static unsigned long cdmask = ZSRR0_CD;
- struct savedzsops
- {
- struct zsops zsops;
- struct zsops *oldzsops;
- };
- struct zsops *emergencyzs;
- extern void zsopinit P((struct zscom *, struct zsops *));
- static int zs_xsisr P((struct zscom *)); /* zs external status interupt handler */
- static int
- init_zs_linemon(
- register queue_t *q,
- register queue_t *my_q
- )
- {
- register struct zscom *zs;
- register struct savedzsops *szs;
- register parsestream_t *parsestream = (parsestream_t *)(void *)my_q->q_ptr;
- /*
- * we expect the zsaline pointer in the q_data pointer
- * from there on we insert our on EXTERNAL/STATUS ISR routine
- * into the interrupt path, before the standard handler
- */
- zs = ((struct zsaline *)(void *)q->q_ptr)->za_common;
- if (!zs)
- {
- /*
- * well - not found on startup - just say no (shouldn't happen though)
- */
- return 0;
- }
- else
- {
- unsigned long s;
-
- /*
- * we do a direct replacement, in case others fiddle also
- * if somebody else grabs our hook and we disconnect
- * we are in DEEP trouble - panic is likely to be next, sorry
- */
- szs = (struct savedzsops *)(void *)kmem_alloc(sizeof(struct savedzsops));
- if (szs == (struct savedzsops *)0)
- {
- parseprintf(DD_INSTALL, ("init_zs_linemon: CD monitor NOT installed - no memory\n"));
- return 0;
- }
- else
- {
- parsestream->parse_data = (void *)szs;
- s = splhigh();
- parsestream->parse_dqueue = q; /* remember driver */
- szs->zsops = *zs->zs_ops;
- szs->zsops.zsop_xsint = zs_xsisr; /* place our bastard */
- szs->oldzsops = zs->zs_ops;
- emergencyzs = zs->zs_ops;
-
- zsopinit(zs, &szs->zsops); /* hook it up */
-
- (void) splx(s);
- parseprintf(DD_INSTALL, ("init_zs_linemon: CD monitor installed\n"));
- return 1;
- }
- }
- }
- /*
- * unregister our ISR routine - must call under splhigh()
- */
- static void
- close_zs_linemon(
- register queue_t *q,
- register queue_t *my_q
- )
- {
- register struct zscom *zs;
- register parsestream_t *parsestream = (parsestream_t *)(void *)my_q->q_ptr;
- zs = ((struct zsaline *)(void *)q->q_ptr)->za_common;
- if (!zs)
- {
- /*
- * well - not found on startup - just say no (shouldn't happen though)
- */
- return;
- }
- else
- {
- register struct savedzsops *szs = (struct savedzsops *)parsestream->parse_data;
-
- zsopinit(zs, szs->oldzsops); /* reset to previous handler functions */
- kmem_free((caddr_t)szs, sizeof (struct savedzsops));
-
- parseprintf(DD_INSTALL, ("close_zs_linemon: CD monitor deleted\n"));
- return;
- }
- }
- #define MAXDEPTH 50 /* maximum allowed stream crawl */
- #ifdef PPS_SYNC
- extern void hardpps P((struct timeval *, long));
- #ifdef PPS_NEW
- extern struct timeval timestamp;
- #else
- extern struct timeval pps_time;
- #endif
- #endif
- /*
- * take external status interrupt (only CD interests us)
- */
- static int
- zs_xsisr(
- struct zscom *zs
- )
- {
- register struct zsaline *za = (struct zsaline *)(void *)zs->zs_priv;
- register struct zscc_device *zsaddr = zs->zs_addr;
- register queue_t *q;
- register unsigned char zsstatus;
- register int loopcheck;
- register char *dname;
- #ifdef PPS_SYNC
- register unsigned int s;
- register long usec;
- #endif
- /*
- * pick up current state
- */
- zsstatus = zsaddr->zscc_control;
- if ((za->za_rr0 ^ zsstatus) & (cdmask))
- {
- timestamp_t cdevent;
- register int status;
-
- za->za_rr0 = (za->za_rr0 & ~(cdmask)) | (zsstatus & (cdmask));
- #ifdef PPS_SYNC
- s = splclock();
- #ifdef PPS_NEW
- usec = timestamp.tv_usec;
- #else
- usec = pps_time.tv_usec;
- #endif
- #endif
- /*
- * time stamp
- */
- uniqtime(&cdevent.tv);
-
- #ifdef PPS_SYNC
- (void)splx(s);
- #endif
- /*
- * logical state
- */
- status = cd_invert ? (zsstatus & cdmask) == 0 : (zsstatus & cdmask) != 0;
- #ifdef PPS_SYNC
- if (status)
- {
- usec = cdevent.tv.tv_usec - usec;
- if (usec < 0)
- usec += 1000000;
- hardpps(&cdevent.tv, usec);
- }
- #endif
- q = za->za_ttycommon.t_readq;
- /*
- * ok - now the hard part - find ourself
- */
- loopcheck = MAXDEPTH;
-
- while (q)
- {
- if (q->q_qinfo && q->q_qinfo->qi_minfo)
- {
- dname = q->q_qinfo->qi_minfo->mi_idname;
- if (!Strcmp(dname, parseinfo.st_rdinit->qi_minfo->mi_idname))
- {
- /*
- * back home - phew (hopping along stream queues might
- * prove dangerous to your health)
- */
- if ((((parsestream_t *)(void *)q->q_ptr)->parse_status & PARSE_ENABLE) &&
- parse_iopps(&((parsestream_t *)(void *)q->q_ptr)->parse_io, (int)(status ? SYNC_ONE : SYNC_ZERO), &cdevent))
- {
- /*
- * XXX - currently we do not pass up the message, as
- * we should.
- * for a correct behaviour wee need to block out
- * processing until parse_iodone has been posted via
- * a softcall-ed routine which does the message pass-up
- * right now PPS information relies on input being
- * received
- */
- parse_iodone(&((parsestream_t *)(void *)q->q_ptr)->parse_io);
- }
-
- if (status)
- {
- ((parsestream_t *)(void *)q->q_ptr)->parse_ppsclockev.tv = cdevent.tv;
- ++(((parsestream_t *)(void *)q->q_ptr)->parse_ppsclockev.serial);
- }
- parseprintf(DD_ISR, ("zs_xsisr: CD event %s has been posted for \"%s\"\n", status ? "ONE" : "ZERO", dname));
- break;
- }
- }
- q = q->q_next;
- if (!loopcheck--)
- {
- panic("zs_xsisr: STREAMS Queue corrupted - CD event");
- }
- }
- /*
- * only pretend that CD has been handled
- */
- ZSDELAY(2);
- if (!((za->za_rr0 ^ zsstatus) & ~(cdmask)))
- {
- /*
- * all done - kill status indication and return
- */
- zsaddr->zscc_control = ZSWR0_RESET_STATUS; /* might kill other conditions here */
- return 0;
- }
- }
- if (zsstatus & cdmask) /* fake CARRIER status */
- za->za_flags |= ZAS_CARR_ON;
- else
- za->za_flags &= ~ZAS_CARR_ON;
-
- /*
- * we are now gathered here to process some unusual external status
- * interrupts.
- * any CD events have also been handled and shouldn't be processed
- * by the original routine (unless we have a VERY busy port pin)
- * some initializations are done here, which could have been done before for
- * both code paths but have been avoided for minimum path length to
- * the uniq_time routine
- */
- dname = (char *) 0;
- q = za->za_ttycommon.t_readq;
- loopcheck = MAXDEPTH;
-
- /*
- * the real thing for everything else ...
- */
- while (q)
- {
- if (q->q_qinfo && q->q_qinfo->qi_minfo)
- {
- dname = q->q_qinfo->qi_minfo->mi_idname;
- if (!Strcmp(dname, parseinfo.st_rdinit->qi_minfo->mi_idname))
- {
- register int (*zsisr) P((struct zscom *));
-
- /*
- * back home - phew (hopping along stream queues might
- * prove dangerous to your health)
- */
- if ((zsisr = ((struct savedzsops *)((parsestream_t *)(void *)q->q_ptr)->parse_data)->oldzsops->zsop_xsint))
- return zsisr(zs);
- else
- panic("zs_xsisr: unable to locate original ISR");
-
- parseprintf(DD_ISR, ("zs_xsisr: non CD event was processed for \"%s\"\n", dname));
- /*
- * now back to our program ...
- */
- return 0;
- }
- }
- q = q->q_next;
- if (!loopcheck--)
- {
- panic("zs_xsisr: STREAMS Queue corrupted - non CD event");
- }
- }
- /*
- * last resort - shouldn't even come here as it indicates
- * corrupted TTY structures
- */
- printf("zs_zsisr: looking for \"%s\" - found \"%s\" - taking EMERGENCY path\n", parseinfo.st_rdinit->qi_minfo->mi_idname, dname ? dname : "-NIL-");
-
- if (emergencyzs && emergencyzs->zsop_xsint)
- emergencyzs->zsop_xsint(zs);
- else
- panic("zs_xsisr: no emergency ISR handler");
- return 0;
- }
- #endif /* sun */
- /*
- * History:
- *
- * parsestreams.c,v
- * Revision 4.11 2005/04/16 17:32:10 kardel
- * update copyright
- *
- * Revision 4.10 2004/11/14 16:06:08 kardel
- * update Id tags
- *
- * Revision 4.9 2004/11/14 15:29:41 kardel
- * support PPSAPI, upgrade Copyright to Berkeley style
- *
- * Revision 4.7 1999/11/28 09:13:53 kardel
- * RECON_4_0_98F
- *
- * Revision 4.6 1998/12/20 23:45:31 kardel
- * fix types and warnings
- *
- * Revision 4.5 1998/11/15 21:23:38 kardel
- * ntp_memset() replicated in Sun kernel files
- *
- * Revision 4.4 1998/06/13 12:15:59 kardel
- * superfluous variable removed
- *
- * Revision 4.3 1998/06/12 15:23:08 kardel
- * fix prototypes
- * adjust for ansi2knr
- *
- * Revision 4.2 1998/05/24 18:16:22 kardel
- * moved copy of shadow status to the beginning
- *
- * Revision 4.1 1998/05/24 09:38:47 kardel
- * streams initiated iopps calls (M_xHANGUP) are now consistent with the
- * respective calls from zs_xsisr()
- * simulation of CARRIER status to avoid unecessary M_xHANGUP messages
- *
- * Revision 4.0 1998/04/10 19:45:38 kardel
- * Start 4.0 release version numbering
- *
- * from V3 3.37 log info deleted 1998/04/11 kardel
- */