154359Sroberto/* 2182007Sroberto * /src/NTP/ntp4-dev/libparse/parsestreams.c,v 4.11 2005/04/16 17:32:10 kardel RELEASE_20050508_A 354359Sroberto * 4182007Sroberto * parsestreams.c,v 4.11 2005/04/16 17:32:10 kardel RELEASE_20050508_A 554359Sroberto * 654359Sroberto * STREAMS module for reference clocks 754359Sroberto * (SunOS4.x) 854359Sroberto * 9182007Sroberto * Copyright (c) 1995-2005 by Frank Kardel <kardel <AT> ntp.org> 10182007Sroberto * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universit�t Erlangen-N�rnberg, Germany 1154359Sroberto * 12182007Sroberto * Redistribution and use in source and binary forms, with or without 13182007Sroberto * modification, are permitted provided that the following conditions 14182007Sroberto * are met: 15182007Sroberto * 1. Redistributions of source code must retain the above copyright 16182007Sroberto * notice, this list of conditions and the following disclaimer. 17182007Sroberto * 2. Redistributions in binary form must reproduce the above copyright 18182007Sroberto * notice, this list of conditions and the following disclaimer in the 19182007Sroberto * documentation and/or other materials provided with the distribution. 20182007Sroberto * 3. Neither the name of the author nor the names of its contributors 21182007Sroberto * may be used to endorse or promote products derived from this software 22182007Sroberto * without specific prior written permission. 23182007Sroberto * 24182007Sroberto * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 25182007Sroberto * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26182007Sroberto * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27182007Sroberto * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 28182007Sroberto * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29182007Sroberto * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30182007Sroberto * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31182007Sroberto * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32182007Sroberto * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33182007Sroberto * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34182007Sroberto * SUCH DAMAGE. 35182007Sroberto * 3654359Sroberto */ 3754359Sroberto 3854359Sroberto#define KERNEL /* MUST */ 3954359Sroberto#define VDDRV /* SHOULD */ 4054359Sroberto 4154359Sroberto#ifdef HAVE_CONFIG_H 4254359Sroberto# include "config.h" 4354359Sroberto#endif 4454359Sroberto 4554359Sroberto#ifndef lint 46182007Srobertostatic char rcsid[] = "parsestreams.c,v 4.11 2005/04/16 17:32:10 kardel RELEASE_20050508_A"; 4754359Sroberto#endif 4854359Sroberto 4954359Sroberto#ifndef KERNEL 5054359Sroberto#include "Bletch: MUST COMPILE WITH KERNEL DEFINE" 5154359Sroberto#endif 5254359Sroberto 5354359Sroberto#include <sys/types.h> 5454359Sroberto#include <sys/conf.h> 5554359Sroberto#include <sys/buf.h> 5654359Sroberto#include <sys/param.h> 5754359Sroberto#include <sys/sysmacros.h> 5854359Sroberto#include <sys/time.h> 5954359Sroberto#include <sundev/mbvar.h> 6054359Sroberto#include <sun/autoconf.h> 6154359Sroberto#include <sys/stream.h> 6254359Sroberto#include <sys/stropts.h> 6354359Sroberto#include <sys/dir.h> 6454359Sroberto#include <sys/signal.h> 6554359Sroberto#include <sys/termios.h> 6654359Sroberto#include <sys/termio.h> 6754359Sroberto#include <sys/ttold.h> 6854359Sroberto#include <sys/user.h> 6954359Sroberto#include <sys/tty.h> 7054359Sroberto 7154359Sroberto#ifdef VDDRV 7254359Sroberto#include <sun/vddrv.h> 7354359Sroberto#endif 7454359Sroberto 7554359Sroberto#include "ntp_stdlib.h" 7654359Sroberto#include "ntp_fp.h" 7754359Sroberto/* 7854359Sroberto * just make checking compilers more silent 7954359Sroberto */ 8054359Srobertoextern int printf P((const char *, ...)); 8154359Srobertoextern int putctl1 P((queue_t *, int, int)); 8254359Srobertoextern int canput P((queue_t *)); 8354359Srobertoextern void putbq P((queue_t *, mblk_t *)); 8454359Srobertoextern void freeb P((mblk_t *)); 8554359Srobertoextern void qreply P((queue_t *, mblk_t *)); 8654359Srobertoextern void freemsg P((mblk_t *)); 8754359Srobertoextern void panic P((const char *, ...)); 8854359Srobertoextern void usec_delay P((int)); 8954359Sroberto 9054359Sroberto#include "parse.h" 9154359Sroberto#include "sys/parsestreams.h" 9254359Sroberto 9354359Sroberto/* 9454359Sroberto * use microtime instead of uniqtime if advised to 9554359Sroberto */ 9654359Sroberto#ifdef MICROTIME 9754359Sroberto#define uniqtime microtime 9854359Sroberto#endif 9954359Sroberto 10054359Sroberto#ifdef VDDRV 10154359Srobertostatic unsigned int parsebusy = 0; 10254359Sroberto 10354359Sroberto/*--------------- loadable driver section -----------------------------*/ 10454359Sroberto 10554359Srobertoextern struct streamtab parseinfo; 10654359Sroberto 10754359Sroberto 10854359Sroberto#ifdef PPS_SYNC 10954359Srobertostatic char mnam[] = "PARSEPPS "; /* name this baby - keep room for revision number */ 11054359Sroberto#else 11154359Srobertostatic char mnam[] = "PARSE "; /* name this baby - keep room for revision number */ 11254359Sroberto#endif 11354359Srobertostruct vdldrv parsesync_vd = 11454359Sroberto{ 11554359Sroberto VDMAGIC_PSEUDO, /* nothing like a real driver - a STREAMS module */ 11654359Sroberto mnam, 11754359Sroberto}; 11854359Sroberto 11954359Sroberto/* 12054359Sroberto * strings support usually not in kernel 12154359Sroberto */ 12254359Srobertostatic int 12354359SrobertoStrlen( 12454359Sroberto register const char *s 12554359Sroberto ) 12654359Sroberto{ 12754359Sroberto register int c; 12854359Sroberto 12954359Sroberto c = 0; 13054359Sroberto if (s) 13154359Sroberto { 13254359Sroberto while (*s++) 13354359Sroberto { 13454359Sroberto c++; 13554359Sroberto } 13654359Sroberto } 13754359Sroberto return c; 13854359Sroberto} 13954359Sroberto 14054359Srobertostatic void 14154359SrobertoStrncpy( 14254359Sroberto register char *t, 14354359Sroberto register char *s, 14454359Sroberto register int c 14554359Sroberto ) 14654359Sroberto{ 14754359Sroberto if (s && t) 14854359Sroberto { 14954359Sroberto while ((c-- > 0) && (*t++ = *s++)) 15054359Sroberto ; 15154359Sroberto } 15254359Sroberto} 15354359Sroberto 15454359Srobertostatic int 15554359SrobertoStrcmp( 15654359Sroberto register const char *s, 15754359Sroberto register const char *t 15854359Sroberto ) 15954359Sroberto{ 16054359Sroberto register int c = 0; 16154359Sroberto 16254359Sroberto if (!s || !t || (s == t)) 16354359Sroberto { 16454359Sroberto return 0; 16554359Sroberto } 16654359Sroberto 16754359Sroberto while (!(c = *s++ - *t++) && *s && *t) 16854359Sroberto /* empty loop */; 16954359Sroberto 17054359Sroberto return c; 17154359Sroberto} 17254359Sroberto 17354359Srobertostatic int 17454359SrobertoStrncmp( 17554359Sroberto register char *s, 17654359Sroberto register char *t, 17754359Sroberto register int n 17854359Sroberto ) 17954359Sroberto{ 18054359Sroberto register int c = 0; 18154359Sroberto 18254359Sroberto if (!s || !t || (s == t)) 18354359Sroberto { 18454359Sroberto return 0; 18554359Sroberto } 18654359Sroberto 18754359Sroberto while (n-- && !(c = *s++ - *t++) && *s && *t) 18854359Sroberto /* empty loop */; 18954359Sroberto 19054359Sroberto return c; 19154359Sroberto} 19254359Sroberto 19354359Srobertovoid 19454359Srobertontp_memset( 19554359Sroberto char *a, 19654359Sroberto int x, 19754359Sroberto int c 19854359Sroberto ) 19954359Sroberto{ 20054359Sroberto while (c-- > 0) 20154359Sroberto *a++ = x; 20254359Sroberto} 20354359Sroberto 20454359Sroberto/* 20554359Sroberto * driver init routine 20654359Sroberto * since no mechanism gets us into and out of the fmodsw, we have to 20754359Sroberto * do it ourselves 20854359Sroberto */ 20954359Sroberto/*ARGSUSED*/ 21054359Srobertoint 21154359Srobertoxxxinit( 21254359Sroberto unsigned int fc, 21354359Sroberto struct vddrv *vdp, 21454359Sroberto addr_t vdin, 21554359Sroberto struct vdstat *vds 21654359Sroberto ) 21754359Sroberto{ 21854359Sroberto extern struct fmodsw fmodsw[]; 21954359Sroberto extern int fmodcnt; 22054359Sroberto 22154359Sroberto struct fmodsw *fm = fmodsw; 22254359Sroberto struct fmodsw *fmend = &fmodsw[fmodcnt]; 22354359Sroberto struct fmodsw *ifm = (struct fmodsw *)0; 22454359Sroberto char *mname = parseinfo.st_rdinit->qi_minfo->mi_idname; 22554359Sroberto 22654359Sroberto switch (fc) 22754359Sroberto { 22854359Sroberto case VDLOAD: 22954359Sroberto vdp->vdd_vdtab = (struct vdlinkage *)&parsesync_vd; 23054359Sroberto /* 23154359Sroberto * now, jog along fmodsw scanning for an empty slot 23254359Sroberto * and deposit our name there 23354359Sroberto */ 23454359Sroberto while (fm <= fmend) 23554359Sroberto { 23654359Sroberto if (!Strncmp(fm->f_name, mname, FMNAMESZ)) 23754359Sroberto { 23854359Sroberto printf("vddrinit[%s]: STREAMS module already loaded.\n", mname); 23954359Sroberto return(EBUSY); 24054359Sroberto } 24154359Sroberto else 24254359Sroberto if ((ifm == (struct fmodsw *)0) && 24354359Sroberto (fm->f_name[0] == '\0') && 24454359Sroberto (fm->f_str == (struct streamtab *)0)) 24554359Sroberto { 24654359Sroberto /* 24754359Sroberto * got one - so move in 24854359Sroberto */ 24954359Sroberto ifm = fm; 25054359Sroberto break; 25154359Sroberto } 25254359Sroberto fm++; 25354359Sroberto } 25454359Sroberto 25554359Sroberto if (ifm == (struct fmodsw *)0) 25654359Sroberto { 25754359Sroberto printf("vddrinit[%s]: no slot free for STREAMS module\n", mname); 25854359Sroberto return (ENOSPC); 25954359Sroberto } 26054359Sroberto else 26154359Sroberto { 26256746Sroberto static char revision[] = "4.7"; 26354359Sroberto char *s, *S, *t; 26454359Sroberto 26554359Sroberto s = rcsid; /* NOOP - keep compilers happy */ 26654359Sroberto 26754359Sroberto Strncpy(ifm->f_name, mname, FMNAMESZ); 26854359Sroberto ifm->f_name[FMNAMESZ] = '\0'; 26954359Sroberto ifm->f_str = &parseinfo; 27054359Sroberto /* 27154359Sroberto * copy RCS revision into Drv_name 27254359Sroberto * 27354359Sroberto * are we forcing RCS here to do things it was not built for ? 27454359Sroberto */ 27554359Sroberto s = revision; 27654359Sroberto if (*s == '$') 27754359Sroberto { 27854359Sroberto /* 27954359Sroberto * skip "$Revision: " 28054359Sroberto * if present. - not necessary on a -kv co (cvs export) 28154359Sroberto */ 28254359Sroberto while (*s && (*s != ' ')) 28354359Sroberto { 28454359Sroberto s++; 28554359Sroberto } 28654359Sroberto if (*s == ' ') s++; 28754359Sroberto } 28854359Sroberto 28954359Sroberto t = parsesync_vd.Drv_name; 29054359Sroberto while (*t && (*t != ' ')) 29154359Sroberto { 29254359Sroberto t++; 29354359Sroberto } 29454359Sroberto if (*t == ' ') t++; 29554359Sroberto 29654359Sroberto S = s; 29754359Sroberto while (*S && (((*S >= '0') && (*S <= '9')) || (*S == '.'))) 29854359Sroberto { 29954359Sroberto S++; 30054359Sroberto } 30154359Sroberto 30254359Sroberto if (*s && *t && (S > s)) 30354359Sroberto { 30454359Sroberto if (Strlen(t) >= (S - s)) 30554359Sroberto { 30654359Sroberto (void) Strncpy(t, s, S - s); 30754359Sroberto } 30854359Sroberto } 30954359Sroberto return (0); 31054359Sroberto } 31154359Sroberto break; 31254359Sroberto 31354359Sroberto case VDUNLOAD: 31454359Sroberto if (parsebusy > 0) 31554359Sroberto { 31654359Sroberto printf("vddrinit[%s]: STREAMS module has still %d instances active.\n", mname, parsebusy); 31754359Sroberto return (EBUSY); 31854359Sroberto } 31954359Sroberto else 32054359Sroberto { 32154359Sroberto while (fm <= fmend) 32254359Sroberto { 32354359Sroberto if (!Strncmp(fm->f_name, mname, FMNAMESZ)) 32454359Sroberto { 32554359Sroberto /* 32654359Sroberto * got it - kill entry 32754359Sroberto */ 32854359Sroberto fm->f_name[0] = '\0'; 32954359Sroberto fm->f_str = (struct streamtab *)0; 33054359Sroberto fm++; 33154359Sroberto 33254359Sroberto break; 33354359Sroberto } 33454359Sroberto fm++; 33554359Sroberto } 33654359Sroberto if (fm > fmend) 33754359Sroberto { 33854359Sroberto printf("vddrinit[%s]: cannot find entry for STREAMS module\n", mname); 33954359Sroberto return (ENXIO); 34054359Sroberto } 34154359Sroberto else 34254359Sroberto return (0); 34354359Sroberto } 34454359Sroberto 34554359Sroberto 34654359Sroberto case VDSTAT: 34754359Sroberto return (0); 34854359Sroberto 34954359Sroberto default: 35054359Sroberto return (EIO); 35154359Sroberto 35254359Sroberto } 35354359Sroberto return EIO; 35454359Sroberto} 35554359Sroberto 35654359Sroberto#endif 35754359Sroberto 35854359Sroberto/*--------------- stream module definition ----------------------------*/ 35954359Sroberto 36054359Srobertostatic int parseopen P((queue_t *, dev_t, int, int)); 36154359Srobertostatic int parseclose P((queue_t *, int)); 36254359Srobertostatic int parsewput P((queue_t *, mblk_t *)); 36354359Srobertostatic int parserput P((queue_t *, mblk_t *)); 36454359Srobertostatic int parsersvc P((queue_t *)); 36554359Sroberto 36654359Srobertostatic char mn[] = "parse"; 36754359Sroberto 36854359Srobertostatic struct module_info driverinfo = 36954359Sroberto{ 37054359Sroberto 0, /* module ID number */ 37154359Sroberto mn, /* module name */ 37254359Sroberto 0, /* minimum accepted packet size */ 37354359Sroberto INFPSZ, /* maximum accepted packet size */ 37454359Sroberto 1, /* high water mark - flow control */ 37554359Sroberto 0 /* low water mark - flow control */ 37654359Sroberto}; 37754359Sroberto 37854359Srobertostatic struct qinit rinit = /* read queue definition */ 37954359Sroberto{ 38054359Sroberto parserput, /* put procedure */ 38154359Sroberto parsersvc, /* service procedure */ 38254359Sroberto parseopen, /* open procedure */ 38354359Sroberto parseclose, /* close procedure */ 38454359Sroberto NULL, /* admin procedure - NOT USED FOR NOW */ 38554359Sroberto &driverinfo, /* information structure */ 38654359Sroberto NULL /* statistics */ 38754359Sroberto}; 38854359Sroberto 38954359Srobertostatic struct qinit winit = /* write queue definition */ 39054359Sroberto{ 39154359Sroberto parsewput, /* put procedure */ 39254359Sroberto NULL, /* service procedure */ 39354359Sroberto NULL, /* open procedure */ 39454359Sroberto NULL, /* close procedure */ 39554359Sroberto NULL, /* admin procedure - NOT USED FOR NOW */ 39654359Sroberto &driverinfo, /* information structure */ 39754359Sroberto NULL /* statistics */ 39854359Sroberto}; 39954359Sroberto 40054359Srobertostruct streamtab parseinfo = /* stream info element for dpr driver */ 40154359Sroberto{ 40254359Sroberto &rinit, /* read queue */ 40354359Sroberto &winit, /* write queue */ 40454359Sroberto NULL, /* read mux */ 40554359Sroberto NULL, /* write mux */ 40654359Sroberto NULL /* module auto push */ 40754359Sroberto}; 40854359Sroberto 40954359Sroberto/*--------------- driver data structures ----------------------------*/ 41054359Sroberto 41154359Sroberto/* 41254359Sroberto * we usually have an inverted signal - but you 41354359Sroberto * can change this to suit your needs 41454359Sroberto */ 41554359Srobertoint cd_invert = 1; /* invert status of CD line - PPS support via CD input */ 41654359Sroberto 41754359Srobertoint parsedebug = ~0; 41854359Sroberto 41954359Srobertoextern void uniqtime P((struct timeval *)); 42054359Sroberto 42154359Sroberto/*--------------- module implementation -----------------------------*/ 42254359Sroberto 42354359Sroberto#define TIMEVAL_USADD(_X_, _US_) {\ 42454359Sroberto (_X_)->tv_usec += (_US_);\ 42554359Sroberto if ((_X_)->tv_usec >= 1000000)\ 42654359Sroberto {\ 42754359Sroberto (_X_)->tv_sec++;\ 42854359Sroberto (_X_)->tv_usec -= 1000000;\ 42954359Sroberto }\ 43054359Sroberto } while (0) 43154359Sroberto 43254359Srobertostatic int init_linemon P((queue_t *)); 43354359Srobertostatic void close_linemon P((queue_t *, queue_t *)); 43454359Sroberto 43554359Sroberto#define M_PARSE 0x0001 43654359Sroberto#define M_NOPARSE 0x0002 43754359Sroberto 43854359Srobertostatic int 43954359Srobertosetup_stream( 44054359Sroberto queue_t *q, 44154359Sroberto int mode 44254359Sroberto ) 44354359Sroberto{ 44454359Sroberto mblk_t *mp; 44554359Sroberto 44654359Sroberto mp = allocb(sizeof(struct stroptions), BPRI_MED); 44754359Sroberto if (mp) 44854359Sroberto { 44954359Sroberto struct stroptions *str = (struct stroptions *)(void *)mp->b_rptr; 45054359Sroberto 45154359Sroberto str->so_flags = SO_READOPT|SO_HIWAT|SO_LOWAT; 45254359Sroberto str->so_readopt = (mode == M_PARSE) ? RMSGD : RNORM; 45354359Sroberto str->so_hiwat = (mode == M_PARSE) ? sizeof(parsetime_t) : 256; 45454359Sroberto str->so_lowat = 0; 45554359Sroberto mp->b_datap->db_type = M_SETOPTS; 45654359Sroberto mp->b_wptr += sizeof(struct stroptions); 45754359Sroberto putnext(q, mp); 45854359Sroberto return putctl1(WR(q)->q_next, M_CTL, (mode == M_PARSE) ? MC_SERVICEIMM : 45954359Sroberto MC_SERVICEDEF); 46054359Sroberto } 46154359Sroberto else 46254359Sroberto { 46354359Sroberto parseprintf(DD_OPEN,("parse: setup_stream - FAILED - no MEMORY for allocb\n")); 46454359Sroberto return 0; 46554359Sroberto } 46654359Sroberto} 46754359Sroberto 46854359Sroberto/*ARGSUSED*/ 46954359Srobertostatic int 47054359Srobertoparseopen( 47154359Sroberto queue_t *q, 47254359Sroberto dev_t dev, 47354359Sroberto int flag, 47454359Sroberto int sflag 47554359Sroberto ) 47654359Sroberto{ 47754359Sroberto register parsestream_t *parse; 47854359Sroberto static int notice = 0; 47954359Sroberto 48054359Sroberto parseprintf(DD_OPEN,("parse: OPEN\n")); 48154359Sroberto 48254359Sroberto if (sflag != MODOPEN) 48354359Sroberto { /* open only for modules */ 48454359Sroberto parseprintf(DD_OPEN,("parse: OPEN - FAILED - not MODOPEN\n")); 48554359Sroberto return OPENFAIL; 48654359Sroberto } 48754359Sroberto 48854359Sroberto if (q->q_ptr != (caddr_t)NULL) 48954359Sroberto { 49054359Sroberto u.u_error = EBUSY; 49154359Sroberto parseprintf(DD_OPEN,("parse: OPEN - FAILED - EXCLUSIVE ONLY\n")); 49254359Sroberto return OPENFAIL; 49354359Sroberto } 49454359Sroberto 49554359Sroberto#ifdef VDDRV 49654359Sroberto parsebusy++; 49754359Sroberto#endif 49854359Sroberto 49954359Sroberto q->q_ptr = (caddr_t)kmem_alloc(sizeof(parsestream_t)); 50054359Sroberto if (q->q_ptr == (caddr_t)0) 50154359Sroberto { 50254359Sroberto parseprintf(DD_OPEN,("parse: OPEN - FAILED - no memory\n")); 50354359Sroberto#ifdef VDDRV 50454359Sroberto parsebusy--; 50554359Sroberto#endif 50654359Sroberto return OPENFAIL; 50754359Sroberto } 50854359Sroberto WR(q)->q_ptr = q->q_ptr; 50954359Sroberto 51054359Sroberto parse = (parsestream_t *)(void *)q->q_ptr; 51154359Sroberto bzero((caddr_t)parse, sizeof(*parse)); 51254359Sroberto parse->parse_queue = q; 51354359Sroberto parse->parse_status = PARSE_ENABLE; 51454359Sroberto parse->parse_ppsclockev.tv.tv_sec = 0; 51554359Sroberto parse->parse_ppsclockev.tv.tv_usec = 0; 51654359Sroberto parse->parse_ppsclockev.serial = 0; 51754359Sroberto 51854359Sroberto if (!parse_ioinit(&parse->parse_io)) 51954359Sroberto { 52054359Sroberto /* 52154359Sroberto * ok guys - beat it 52254359Sroberto */ 52354359Sroberto kmem_free((caddr_t)parse, sizeof(parsestream_t)); 52454359Sroberto#ifdef VDDRV 52554359Sroberto parsebusy--; 52654359Sroberto#endif 52754359Sroberto return OPENFAIL; 52854359Sroberto } 52954359Sroberto 53054359Sroberto if (setup_stream(q, M_PARSE)) 53154359Sroberto { 53254359Sroberto (void) init_linemon(q); /* hook up PPS ISR routines if possible */ 53354359Sroberto 53454359Sroberto parseprintf(DD_OPEN,("parse: OPEN - SUCCEEDED\n")); 53554359Sroberto 53654359Sroberto /* 53754359Sroberto * I know that you know the delete key, but you didn't write this 53854359Sroberto * code, did you ? - So, keep the message in here. 53954359Sroberto */ 54054359Sroberto if (!notice) 54154359Sroberto { 54254359Sroberto#ifdef VDDRV 543182007Sroberto printf("%s: Copyright (C) 1991-2005, Frank Kardel\n", parsesync_vd.Drv_name); 54454359Sroberto#else 545182007Sroberto printf("%s: Copyright (C) 1991-2005, Frank Kardel\n", "parsestreams.c,v 4.11 2005/04/16 17:32:10 kardel RELEASE_20050508_A"); 54654359Sroberto#endif 54754359Sroberto notice = 1; 54854359Sroberto } 54954359Sroberto 55054359Sroberto return MODOPEN; 55154359Sroberto } 55254359Sroberto else 55354359Sroberto { 55454359Sroberto kmem_free((caddr_t)parse, sizeof(parsestream_t)); 55554359Sroberto 55654359Sroberto#ifdef VDDRV 55754359Sroberto parsebusy--; 55854359Sroberto#endif 55954359Sroberto return OPENFAIL; 56054359Sroberto } 56154359Sroberto} 56254359Sroberto 56354359Sroberto/*ARGSUSED*/ 56454359Srobertostatic int 56554359Srobertoparseclose( 56654359Sroberto queue_t *q, 56754359Sroberto int flags 56854359Sroberto ) 56954359Sroberto{ 57054359Sroberto register parsestream_t *parse = (parsestream_t *)(void *)q->q_ptr; 57154359Sroberto register unsigned long s; 57254359Sroberto 57354359Sroberto parseprintf(DD_CLOSE,("parse: CLOSE\n")); 57454359Sroberto 57554359Sroberto s = splhigh(); 57654359Sroberto 57754359Sroberto if (parse->parse_dqueue) 57854359Sroberto close_linemon(parse->parse_dqueue, q); 57954359Sroberto parse->parse_dqueue = (queue_t *)0; 58054359Sroberto 58154359Sroberto (void) splx(s); 58254359Sroberto 58354359Sroberto parse_ioend(&parse->parse_io); 58454359Sroberto 58554359Sroberto kmem_free((caddr_t)parse, sizeof(parsestream_t)); 58654359Sroberto 58754359Sroberto q->q_ptr = (caddr_t)NULL; 58854359Sroberto WR(q)->q_ptr = (caddr_t)NULL; 58954359Sroberto 59054359Sroberto#ifdef VDDRV 59154359Sroberto parsebusy--; 59254359Sroberto#endif 59354359Sroberto return 0; 59454359Sroberto} 59554359Sroberto 59654359Sroberto/* 59754359Sroberto * move unrecognized stuff upward 59854359Sroberto */ 59954359Srobertostatic int 60054359Srobertoparsersvc( 60154359Sroberto queue_t *q 60254359Sroberto ) 60354359Sroberto{ 60454359Sroberto mblk_t *mp; 60554359Sroberto 60654359Sroberto while ((mp = getq(q))) 60754359Sroberto { 60854359Sroberto if (canput(q->q_next) || (mp->b_datap->db_type > QPCTL)) 60954359Sroberto { 61054359Sroberto putnext(q, mp); 61154359Sroberto parseprintf(DD_RSVC,("parse: RSVC - putnext\n")); 61254359Sroberto } 61354359Sroberto else 61454359Sroberto { 61554359Sroberto putbq(q, mp); 61654359Sroberto parseprintf(DD_RSVC,("parse: RSVC - flow control wait\n")); 61754359Sroberto break; 61854359Sroberto } 61954359Sroberto } 62054359Sroberto return 0; 62154359Sroberto} 62254359Sroberto 62354359Sroberto/* 62454359Sroberto * do ioctls and 62554359Sroberto * send stuff down - dont care about 62654359Sroberto * flow control 62754359Sroberto */ 62854359Srobertostatic int 62954359Srobertoparsewput( 63054359Sroberto queue_t *q, 63154359Sroberto register mblk_t *mp 63254359Sroberto ) 63354359Sroberto{ 63454359Sroberto register int ok = 1; 63554359Sroberto register mblk_t *datap; 63654359Sroberto register struct iocblk *iocp; 63754359Sroberto parsestream_t *parse = (parsestream_t *)(void *)q->q_ptr; 63854359Sroberto 63954359Sroberto parseprintf(DD_WPUT,("parse: parsewput\n")); 64054359Sroberto 64154359Sroberto switch (mp->b_datap->db_type) 64254359Sroberto { 64354359Sroberto default: 64454359Sroberto putnext(q, mp); 64554359Sroberto break; 64654359Sroberto 64754359Sroberto case M_IOCTL: 64854359Sroberto iocp = (struct iocblk *)(void *)mp->b_rptr; 64954359Sroberto switch (iocp->ioc_cmd) 65054359Sroberto { 65154359Sroberto default: 65254359Sroberto parseprintf(DD_WPUT,("parse: parsewput - forward M_IOCTL\n")); 65354359Sroberto putnext(q, mp); 65454359Sroberto break; 65554359Sroberto 65654359Sroberto case CIOGETEV: 65754359Sroberto /* 65854359Sroberto * taken from Craig Leres ppsclock module (and modified) 65954359Sroberto */ 66054359Sroberto datap = allocb(sizeof(struct ppsclockev), BPRI_MED); 66154359Sroberto if (datap == NULL || mp->b_cont) 66254359Sroberto { 66354359Sroberto mp->b_datap->db_type = M_IOCNAK; 66454359Sroberto iocp->ioc_error = (datap == NULL) ? ENOMEM : EINVAL; 66554359Sroberto if (datap != NULL) 66654359Sroberto freeb(datap); 66754359Sroberto qreply(q, mp); 66854359Sroberto break; 66954359Sroberto } 67054359Sroberto 67154359Sroberto mp->b_cont = datap; 67254359Sroberto *(struct ppsclockev *)(void *)datap->b_wptr = parse->parse_ppsclockev; 67354359Sroberto datap->b_wptr += 67454359Sroberto sizeof(struct ppsclockev) / sizeof(*datap->b_wptr); 67554359Sroberto mp->b_datap->db_type = M_IOCACK; 67654359Sroberto iocp->ioc_count = sizeof(struct ppsclockev); 67754359Sroberto qreply(q, mp); 67854359Sroberto break; 67954359Sroberto 68054359Sroberto case PARSEIOC_ENABLE: 68154359Sroberto case PARSEIOC_DISABLE: 68254359Sroberto { 68354359Sroberto parse->parse_status = (parse->parse_status & (unsigned)~PARSE_ENABLE) | 68454359Sroberto (iocp->ioc_cmd == PARSEIOC_ENABLE) ? 68554359Sroberto PARSE_ENABLE : 0; 68654359Sroberto if (!setup_stream(RD(q), (parse->parse_status & PARSE_ENABLE) ? 68754359Sroberto M_PARSE : M_NOPARSE)) 68854359Sroberto { 68954359Sroberto mp->b_datap->db_type = M_IOCNAK; 69054359Sroberto } 69154359Sroberto else 69254359Sroberto { 69354359Sroberto mp->b_datap->db_type = M_IOCACK; 69454359Sroberto } 69554359Sroberto qreply(q, mp); 69654359Sroberto break; 69754359Sroberto } 69854359Sroberto 69954359Sroberto case PARSEIOC_TIMECODE: 70054359Sroberto case PARSEIOC_SETFMT: 70154359Sroberto case PARSEIOC_GETFMT: 70254359Sroberto case PARSEIOC_SETCS: 70354359Sroberto if (iocp->ioc_count == sizeof(parsectl_t)) 70454359Sroberto { 70554359Sroberto parsectl_t *dct = (parsectl_t *)(void *)mp->b_cont->b_rptr; 70654359Sroberto 70754359Sroberto switch (iocp->ioc_cmd) 70854359Sroberto { 70954359Sroberto case PARSEIOC_TIMECODE: 71054359Sroberto parseprintf(DD_WPUT,("parse: parsewput - PARSEIOC_TIMECODE\n")); 71154359Sroberto ok = parse_timecode(dct, &parse->parse_io); 71254359Sroberto break; 71354359Sroberto 71454359Sroberto case PARSEIOC_SETFMT: 71554359Sroberto parseprintf(DD_WPUT,("parse: parsewput - PARSEIOC_SETFMT\n")); 71654359Sroberto ok = parse_setfmt(dct, &parse->parse_io); 71754359Sroberto break; 71854359Sroberto 71954359Sroberto case PARSEIOC_GETFMT: 72054359Sroberto parseprintf(DD_WPUT,("parse: parsewput - PARSEIOC_GETFMT\n")); 72154359Sroberto ok = parse_getfmt(dct, &parse->parse_io); 72254359Sroberto break; 72354359Sroberto 72454359Sroberto case PARSEIOC_SETCS: 72554359Sroberto parseprintf(DD_WPUT,("parse: parsewput - PARSEIOC_SETCS\n")); 72654359Sroberto ok = parse_setcs(dct, &parse->parse_io); 72754359Sroberto break; 72854359Sroberto } 72954359Sroberto mp->b_datap->db_type = ok ? M_IOCACK : M_IOCNAK; 73054359Sroberto } 73154359Sroberto else 73254359Sroberto { 73354359Sroberto mp->b_datap->db_type = M_IOCNAK; 73454359Sroberto } 73554359Sroberto parseprintf(DD_WPUT,("parse: parsewput qreply - %s\n", (mp->b_datap->db_type == M_IOCNAK) ? "M_IOCNAK" : "M_IOCACK")); 73654359Sroberto qreply(q, mp); 73754359Sroberto break; 73854359Sroberto } 73954359Sroberto } 74054359Sroberto return 0; 74154359Sroberto} 74254359Sroberto 74354359Sroberto/* 74454359Sroberto * read characters from streams buffers 74554359Sroberto */ 74654359Srobertostatic unsigned long 74754359Srobertordchar( 74854359Sroberto register mblk_t **mp 74954359Sroberto ) 75054359Sroberto{ 75154359Sroberto while (*mp != (mblk_t *)NULL) 75254359Sroberto { 75354359Sroberto if ((*mp)->b_wptr - (*mp)->b_rptr) 75454359Sroberto { 75554359Sroberto return (unsigned long)(*(unsigned char *)((*mp)->b_rptr++)); 75654359Sroberto } 75754359Sroberto else 75854359Sroberto { 75954359Sroberto register mblk_t *mmp = *mp; 76054359Sroberto 76154359Sroberto *mp = (*mp)->b_cont; 76254359Sroberto freeb(mmp); 76354359Sroberto } 76454359Sroberto } 76554359Sroberto return (unsigned)~0; 76654359Sroberto} 76754359Sroberto 76854359Sroberto/* 76954359Sroberto * convert incoming data 77054359Sroberto */ 77154359Srobertostatic int 77254359Srobertoparserput( 77354359Sroberto queue_t *q, 77454359Sroberto mblk_t *mp 77554359Sroberto ) 77654359Sroberto{ 77754359Sroberto unsigned char type; 77854359Sroberto 77954359Sroberto switch (type = mp->b_datap->db_type) 78054359Sroberto { 78154359Sroberto default: 78254359Sroberto /* 78354359Sroberto * anything we don't know will be put on queue 78454359Sroberto * the service routine will move it to the next one 78554359Sroberto */ 78654359Sroberto parseprintf(DD_RPUT,("parse: parserput - forward type 0x%x\n", type)); 78754359Sroberto if (canput(q->q_next) || (mp->b_datap->db_type > QPCTL)) 78854359Sroberto { 78954359Sroberto putnext(q, mp); 79054359Sroberto } 79154359Sroberto else 79254359Sroberto putq(q, mp); 79354359Sroberto break; 79454359Sroberto 79554359Sroberto case M_BREAK: 79654359Sroberto case M_DATA: 79754359Sroberto { 79854359Sroberto register parsestream_t * parse = (parsestream_t *)(void *)q->q_ptr; 79954359Sroberto register mblk_t *nmp; 80054359Sroberto register unsigned long ch; 80154359Sroberto timestamp_t ctime; 80254359Sroberto 80354359Sroberto /* 80454359Sroberto * get time on packet delivery 80554359Sroberto */ 80654359Sroberto uniqtime(&ctime.tv); 80754359Sroberto 80854359Sroberto if (!(parse->parse_status & PARSE_ENABLE)) 80954359Sroberto { 81054359Sroberto parseprintf(DD_RPUT,("parse: parserput - parser disabled - forward type 0x%x\n", type)); 81154359Sroberto if (canput(q->q_next) || (mp->b_datap->db_type > QPCTL)) 81254359Sroberto { 81354359Sroberto putnext(q, mp); 81454359Sroberto } 81554359Sroberto else 81654359Sroberto putq(q, mp); 81754359Sroberto } 81854359Sroberto else 81954359Sroberto { 82054359Sroberto parseprintf(DD_RPUT,("parse: parserput - M_%s\n", (type == M_DATA) ? "DATA" : "BREAK")); 82154359Sroberto 82254359Sroberto if (type == M_DATA) 82354359Sroberto { 82454359Sroberto /* 82554359Sroberto * parse packet looking for start an end characters 82654359Sroberto */ 82754359Sroberto while (mp != (mblk_t *)NULL) 82854359Sroberto { 82954359Sroberto ch = rdchar(&mp); 83054359Sroberto if (ch != ~0 && parse_ioread(&parse->parse_io, (unsigned int)ch, &ctime)) 83154359Sroberto { 83254359Sroberto /* 83354359Sroberto * up up and away (hopefully ...) 83454359Sroberto * don't press it if resources are tight or nobody wants it 83554359Sroberto */ 83654359Sroberto nmp = (mblk_t *)NULL; 83754359Sroberto if (canput(parse->parse_queue->q_next) && (nmp = allocb(sizeof(parsetime_t), BPRI_MED))) 83854359Sroberto { 83954359Sroberto bcopy((caddr_t)&parse->parse_io.parse_dtime, (caddr_t)nmp->b_rptr, sizeof(parsetime_t)); 84054359Sroberto nmp->b_wptr += sizeof(parsetime_t); 84154359Sroberto putnext(parse->parse_queue, nmp); 84254359Sroberto } 84354359Sroberto else 84454359Sroberto if (nmp) freemsg(nmp); 84554359Sroberto parse_iodone(&parse->parse_io); 84654359Sroberto } 84754359Sroberto } 84854359Sroberto } 84954359Sroberto else 85054359Sroberto { 85154359Sroberto if (parse_ioread(&parse->parse_io, (unsigned int)0, &ctime)) 85254359Sroberto { 85354359Sroberto /* 85454359Sroberto * up up and away (hopefully ...) 85554359Sroberto * don't press it if resources are tight or nobody wants it 85654359Sroberto */ 85754359Sroberto nmp = (mblk_t *)NULL; 85854359Sroberto if (canput(parse->parse_queue->q_next) && (nmp = allocb(sizeof(parsetime_t), BPRI_MED))) 85954359Sroberto { 86054359Sroberto bcopy((caddr_t)&parse->parse_io.parse_dtime, (caddr_t)nmp->b_rptr, sizeof(parsetime_t)); 86154359Sroberto nmp->b_wptr += sizeof(parsetime_t); 86254359Sroberto putnext(parse->parse_queue, nmp); 86354359Sroberto } 86454359Sroberto else 86554359Sroberto if (nmp) freemsg(nmp); 86654359Sroberto parse_iodone(&parse->parse_io); 86754359Sroberto } 86854359Sroberto freemsg(mp); 86954359Sroberto } 87054359Sroberto break; 87154359Sroberto } 87254359Sroberto } 87354359Sroberto 87454359Sroberto /* 87554359Sroberto * CD PPS support for non direct ISR hack 87654359Sroberto */ 87754359Sroberto case M_HANGUP: 87854359Sroberto case M_UNHANGUP: 87954359Sroberto { 88054359Sroberto register parsestream_t * parse = (parsestream_t *)(void *)q->q_ptr; 88154359Sroberto timestamp_t ctime; 88254359Sroberto register mblk_t *nmp; 88354359Sroberto register int status = cd_invert ^ (type == M_UNHANGUP); 88454359Sroberto 88554359Sroberto uniqtime(&ctime.tv); 88654359Sroberto 88754359Sroberto parseprintf(DD_RPUT,("parse: parserput - M_%sHANGUP\n", (type == M_HANGUP) ? "" : "UN")); 88854359Sroberto 88954359Sroberto if ((parse->parse_status & PARSE_ENABLE) && 89054359Sroberto parse_iopps(&parse->parse_io, (int)(status ? SYNC_ONE : SYNC_ZERO), &ctime)) 89154359Sroberto { 89254359Sroberto nmp = (mblk_t *)NULL; 89354359Sroberto if (canput(parse->parse_queue->q_next) && (nmp = allocb(sizeof(parsetime_t), BPRI_MED))) 89454359Sroberto { 89554359Sroberto bcopy((caddr_t)&parse->parse_io.parse_dtime, (caddr_t)nmp->b_rptr, sizeof(parsetime_t)); 89654359Sroberto nmp->b_wptr += sizeof(parsetime_t); 89754359Sroberto putnext(parse->parse_queue, nmp); 89854359Sroberto } 89954359Sroberto else 90054359Sroberto if (nmp) freemsg(nmp); 90154359Sroberto parse_iodone(&parse->parse_io); 90254359Sroberto freemsg(mp); 90354359Sroberto } 90454359Sroberto else 90554359Sroberto if (canput(q->q_next) || (mp->b_datap->db_type > QPCTL)) 90654359Sroberto { 90754359Sroberto putnext(q, mp); 90854359Sroberto } 90954359Sroberto else 91054359Sroberto putq(q, mp); 91154359Sroberto 91254359Sroberto if (status) 91354359Sroberto { 91454359Sroberto parse->parse_ppsclockev.tv = ctime.tv; 91554359Sroberto ++(parse->parse_ppsclockev.serial); 91654359Sroberto } 91754359Sroberto } 91854359Sroberto } 91954359Sroberto return 0; 92054359Sroberto} 92154359Sroberto 92254359Srobertostatic int init_zs_linemon P((queue_t *, queue_t *)); /* handle line monitor for "zs" driver */ 92354359Srobertostatic void close_zs_linemon P((queue_t *, queue_t *)); 92454359Sroberto 92554359Sroberto/*-------------------- CD isr status monitor ---------------*/ 92654359Sroberto 92754359Srobertostatic int 92854359Srobertoinit_linemon( 92954359Sroberto register queue_t *q 93054359Sroberto ) 93154359Sroberto{ 93254359Sroberto register queue_t *dq; 93354359Sroberto 93454359Sroberto dq = WR(q); 93554359Sroberto /* 93654359Sroberto * we ARE doing very bad things down here (basically stealing ISR 93754359Sroberto * hooks) 93854359Sroberto * 93954359Sroberto * so we chase down the STREAMS stack searching for the driver 94054359Sroberto * and if this is a known driver we insert our ISR routine for 94154359Sroberto * status changes in to the ExternalStatus handling hook 94254359Sroberto */ 94354359Sroberto while (dq->q_next) 94454359Sroberto { 94554359Sroberto dq = dq->q_next; /* skip down to driver */ 94654359Sroberto } 94754359Sroberto 94854359Sroberto /* 94954359Sroberto * find appropriate driver dependent routine 95054359Sroberto */ 95154359Sroberto if (dq->q_qinfo && dq->q_qinfo->qi_minfo) 95254359Sroberto { 95354359Sroberto register char *dname = dq->q_qinfo->qi_minfo->mi_idname; 95454359Sroberto 95554359Sroberto parseprintf(DD_INSTALL, ("init_linemon: driver is \"%s\"\n", dname)); 95654359Sroberto 95754359Sroberto#ifdef sun 95854359Sroberto if (dname && !Strcmp(dname, "zs")) 95954359Sroberto { 96054359Sroberto return init_zs_linemon(dq, q); 96154359Sroberto } 96254359Sroberto else 96354359Sroberto#endif 96454359Sroberto { 96554359Sroberto parseprintf(DD_INSTALL, ("init_linemon: driver \"%s\" not suitable for CD monitoring\n", dname)); 96654359Sroberto return 0; 96754359Sroberto } 96854359Sroberto } 96954359Sroberto parseprintf(DD_INSTALL, ("init_linemon: cannot find driver\n")); 97054359Sroberto return 0; 97154359Sroberto} 97254359Sroberto 97354359Srobertostatic void 97454359Srobertoclose_linemon( 97554359Sroberto register queue_t *q, 97654359Sroberto register queue_t *my_q 97754359Sroberto ) 97854359Sroberto{ 97954359Sroberto /* 98054359Sroberto * find appropriate driver dependent routine 98154359Sroberto */ 98254359Sroberto if (q->q_qinfo && q->q_qinfo->qi_minfo) 98354359Sroberto { 98454359Sroberto register char *dname = q->q_qinfo->qi_minfo->mi_idname; 98554359Sroberto 98654359Sroberto#ifdef sun 98754359Sroberto if (dname && !Strcmp(dname, "zs")) 98854359Sroberto { 98954359Sroberto close_zs_linemon(q, my_q); 99054359Sroberto return; 99154359Sroberto } 99254359Sroberto parseprintf(DD_INSTALL, ("close_linemon: cannot find driver close routine for \"%s\"\n", dname)); 99354359Sroberto#endif 99454359Sroberto } 99554359Sroberto parseprintf(DD_INSTALL, ("close_linemon: cannot find driver name\n")); 99654359Sroberto} 99754359Sroberto 99854359Sroberto#ifdef sun 99954359Sroberto 100054359Sroberto#include <sundev/zsreg.h> 100154359Sroberto#include <sundev/zscom.h> 100254359Sroberto#include <sundev/zsvar.h> 100354359Sroberto 100454359Srobertostatic unsigned long cdmask = ZSRR0_CD; 100554359Sroberto 100654359Srobertostruct savedzsops 100754359Sroberto{ 100854359Sroberto struct zsops zsops; 100954359Sroberto struct zsops *oldzsops; 101054359Sroberto}; 101154359Sroberto 101254359Srobertostruct zsops *emergencyzs; 101354359Srobertoextern void zsopinit P((struct zscom *, struct zsops *)); 101454359Srobertostatic int zs_xsisr P((struct zscom *)); /* zs external status interupt handler */ 101554359Sroberto 101654359Srobertostatic int 101754359Srobertoinit_zs_linemon( 101854359Sroberto register queue_t *q, 101954359Sroberto register queue_t *my_q 102054359Sroberto ) 102154359Sroberto{ 102254359Sroberto register struct zscom *zs; 102354359Sroberto register struct savedzsops *szs; 102454359Sroberto register parsestream_t *parsestream = (parsestream_t *)(void *)my_q->q_ptr; 102554359Sroberto /* 102654359Sroberto * we expect the zsaline pointer in the q_data pointer 102754359Sroberto * from there on we insert our on EXTERNAL/STATUS ISR routine 102854359Sroberto * into the interrupt path, before the standard handler 102954359Sroberto */ 103054359Sroberto zs = ((struct zsaline *)(void *)q->q_ptr)->za_common; 103154359Sroberto if (!zs) 103254359Sroberto { 103354359Sroberto /* 103454359Sroberto * well - not found on startup - just say no (shouldn't happen though) 103554359Sroberto */ 103654359Sroberto return 0; 103754359Sroberto } 103854359Sroberto else 103954359Sroberto { 104054359Sroberto unsigned long s; 104154359Sroberto 104254359Sroberto /* 104354359Sroberto * we do a direct replacement, in case others fiddle also 104454359Sroberto * if somebody else grabs our hook and we disconnect 104554359Sroberto * we are in DEEP trouble - panic is likely to be next, sorry 104654359Sroberto */ 104754359Sroberto szs = (struct savedzsops *)(void *)kmem_alloc(sizeof(struct savedzsops)); 104854359Sroberto 104954359Sroberto if (szs == (struct savedzsops *)0) 105054359Sroberto { 105154359Sroberto parseprintf(DD_INSTALL, ("init_zs_linemon: CD monitor NOT installed - no memory\n")); 105254359Sroberto 105354359Sroberto return 0; 105454359Sroberto } 105554359Sroberto else 105654359Sroberto { 105754359Sroberto parsestream->parse_data = (void *)szs; 105854359Sroberto 105954359Sroberto s = splhigh(); 106054359Sroberto 106154359Sroberto parsestream->parse_dqueue = q; /* remember driver */ 106254359Sroberto 106354359Sroberto szs->zsops = *zs->zs_ops; 106454359Sroberto szs->zsops.zsop_xsint = zs_xsisr; /* place our bastard */ 106554359Sroberto szs->oldzsops = zs->zs_ops; 106654359Sroberto emergencyzs = zs->zs_ops; 106754359Sroberto 106854359Sroberto zsopinit(zs, &szs->zsops); /* hook it up */ 106954359Sroberto 107054359Sroberto (void) splx(s); 107154359Sroberto 107254359Sroberto parseprintf(DD_INSTALL, ("init_zs_linemon: CD monitor installed\n")); 107354359Sroberto 107454359Sroberto return 1; 107554359Sroberto } 107654359Sroberto } 107754359Sroberto} 107854359Sroberto 107954359Sroberto/* 108054359Sroberto * unregister our ISR routine - must call under splhigh() 108154359Sroberto */ 108254359Srobertostatic void 108354359Srobertoclose_zs_linemon( 108454359Sroberto register queue_t *q, 108554359Sroberto register queue_t *my_q 108654359Sroberto ) 108754359Sroberto{ 108854359Sroberto register struct zscom *zs; 108954359Sroberto register parsestream_t *parsestream = (parsestream_t *)(void *)my_q->q_ptr; 109054359Sroberto 109154359Sroberto zs = ((struct zsaline *)(void *)q->q_ptr)->za_common; 109254359Sroberto if (!zs) 109354359Sroberto { 109454359Sroberto /* 109554359Sroberto * well - not found on startup - just say no (shouldn't happen though) 109654359Sroberto */ 109754359Sroberto return; 109854359Sroberto } 109954359Sroberto else 110054359Sroberto { 110154359Sroberto register struct savedzsops *szs = (struct savedzsops *)parsestream->parse_data; 110254359Sroberto 110354359Sroberto zsopinit(zs, szs->oldzsops); /* reset to previous handler functions */ 110454359Sroberto 110554359Sroberto kmem_free((caddr_t)szs, sizeof (struct savedzsops)); 110654359Sroberto 110754359Sroberto parseprintf(DD_INSTALL, ("close_zs_linemon: CD monitor deleted\n")); 110854359Sroberto return; 110954359Sroberto } 111054359Sroberto} 111154359Sroberto 111254359Sroberto#define MAXDEPTH 50 /* maximum allowed stream crawl */ 111354359Sroberto 111454359Sroberto#ifdef PPS_SYNC 111554359Srobertoextern void hardpps P((struct timeval *, long)); 111654359Sroberto#ifdef PPS_NEW 111754359Srobertoextern struct timeval timestamp; 111854359Sroberto#else 111954359Srobertoextern struct timeval pps_time; 112054359Sroberto#endif 112154359Sroberto#endif 112254359Sroberto 112354359Sroberto/* 112454359Sroberto * take external status interrupt (only CD interests us) 112554359Sroberto */ 112654359Srobertostatic int 112754359Srobertozs_xsisr( 112854359Sroberto struct zscom *zs 112954359Sroberto ) 113054359Sroberto{ 113154359Sroberto register struct zsaline *za = (struct zsaline *)(void *)zs->zs_priv; 113254359Sroberto register struct zscc_device *zsaddr = zs->zs_addr; 113354359Sroberto register queue_t *q; 113454359Sroberto register unsigned char zsstatus; 113554359Sroberto register int loopcheck; 113654359Sroberto register char *dname; 113754359Sroberto#ifdef PPS_SYNC 113854359Sroberto register unsigned int s; 113954359Sroberto register long usec; 114054359Sroberto#endif 114154359Sroberto 114254359Sroberto /* 114354359Sroberto * pick up current state 114454359Sroberto */ 114554359Sroberto zsstatus = zsaddr->zscc_control; 114654359Sroberto 114754359Sroberto if ((za->za_rr0 ^ zsstatus) & (cdmask)) 114854359Sroberto { 114954359Sroberto timestamp_t cdevent; 115054359Sroberto register int status; 115154359Sroberto 115254359Sroberto za->za_rr0 = (za->za_rr0 & ~(cdmask)) | (zsstatus & (cdmask)); 115354359Sroberto 115454359Sroberto#ifdef PPS_SYNC 115554359Sroberto s = splclock(); 115654359Sroberto#ifdef PPS_NEW 115754359Sroberto usec = timestamp.tv_usec; 115854359Sroberto#else 115954359Sroberto usec = pps_time.tv_usec; 116054359Sroberto#endif 116154359Sroberto#endif 116254359Sroberto /* 116354359Sroberto * time stamp 116454359Sroberto */ 116554359Sroberto uniqtime(&cdevent.tv); 116654359Sroberto 116754359Sroberto#ifdef PPS_SYNC 116854359Sroberto (void)splx(s); 116954359Sroberto#endif 117054359Sroberto 117154359Sroberto /* 117254359Sroberto * logical state 117354359Sroberto */ 117454359Sroberto status = cd_invert ? (zsstatus & cdmask) == 0 : (zsstatus & cdmask) != 0; 117554359Sroberto 117654359Sroberto#ifdef PPS_SYNC 117754359Sroberto if (status) 117854359Sroberto { 117954359Sroberto usec = cdevent.tv.tv_usec - usec; 118054359Sroberto if (usec < 0) 118154359Sroberto usec += 1000000; 118254359Sroberto 118354359Sroberto hardpps(&cdevent.tv, usec); 118454359Sroberto } 118554359Sroberto#endif 118654359Sroberto 118754359Sroberto q = za->za_ttycommon.t_readq; 118854359Sroberto 118954359Sroberto /* 119054359Sroberto * ok - now the hard part - find ourself 119154359Sroberto */ 119254359Sroberto loopcheck = MAXDEPTH; 119354359Sroberto 119454359Sroberto while (q) 119554359Sroberto { 119654359Sroberto if (q->q_qinfo && q->q_qinfo->qi_minfo) 119754359Sroberto { 119854359Sroberto dname = q->q_qinfo->qi_minfo->mi_idname; 119954359Sroberto 120054359Sroberto if (!Strcmp(dname, parseinfo.st_rdinit->qi_minfo->mi_idname)) 120154359Sroberto { 120254359Sroberto /* 120354359Sroberto * back home - phew (hopping along stream queues might 120454359Sroberto * prove dangerous to your health) 120554359Sroberto */ 120654359Sroberto 120754359Sroberto if ((((parsestream_t *)(void *)q->q_ptr)->parse_status & PARSE_ENABLE) && 120854359Sroberto parse_iopps(&((parsestream_t *)(void *)q->q_ptr)->parse_io, (int)(status ? SYNC_ONE : SYNC_ZERO), &cdevent)) 120954359Sroberto { 121054359Sroberto /* 121154359Sroberto * XXX - currently we do not pass up the message, as 121254359Sroberto * we should. 121354359Sroberto * for a correct behaviour wee need to block out 121454359Sroberto * processing until parse_iodone has been posted via 121554359Sroberto * a softcall-ed routine which does the message pass-up 121654359Sroberto * right now PPS information relies on input being 121754359Sroberto * received 121854359Sroberto */ 121954359Sroberto parse_iodone(&((parsestream_t *)(void *)q->q_ptr)->parse_io); 122054359Sroberto } 122154359Sroberto 122254359Sroberto if (status) 122354359Sroberto { 122454359Sroberto ((parsestream_t *)(void *)q->q_ptr)->parse_ppsclockev.tv = cdevent.tv; 122554359Sroberto ++(((parsestream_t *)(void *)q->q_ptr)->parse_ppsclockev.serial); 122654359Sroberto } 122754359Sroberto 122854359Sroberto parseprintf(DD_ISR, ("zs_xsisr: CD event %s has been posted for \"%s\"\n", status ? "ONE" : "ZERO", dname)); 122954359Sroberto break; 123054359Sroberto } 123154359Sroberto } 123254359Sroberto 123354359Sroberto q = q->q_next; 123454359Sroberto 123554359Sroberto if (!loopcheck--) 123654359Sroberto { 123754359Sroberto panic("zs_xsisr: STREAMS Queue corrupted - CD event"); 123854359Sroberto } 123954359Sroberto } 124054359Sroberto 124154359Sroberto /* 124254359Sroberto * only pretend that CD has been handled 124354359Sroberto */ 124454359Sroberto ZSDELAY(2); 124554359Sroberto 124654359Sroberto if (!((za->za_rr0 ^ zsstatus) & ~(cdmask))) 124754359Sroberto { 124854359Sroberto /* 124954359Sroberto * all done - kill status indication and return 125054359Sroberto */ 125154359Sroberto zsaddr->zscc_control = ZSWR0_RESET_STATUS; /* might kill other conditions here */ 125254359Sroberto return 0; 125354359Sroberto } 125454359Sroberto } 125554359Sroberto 125654359Sroberto if (zsstatus & cdmask) /* fake CARRIER status */ 125754359Sroberto za->za_flags |= ZAS_CARR_ON; 125854359Sroberto else 125954359Sroberto za->za_flags &= ~ZAS_CARR_ON; 126054359Sroberto 126154359Sroberto /* 126254359Sroberto * we are now gathered here to process some unusual external status 126354359Sroberto * interrupts. 126454359Sroberto * any CD events have also been handled and shouldn't be processed 126554359Sroberto * by the original routine (unless we have a VERY busy port pin) 126654359Sroberto * some initializations are done here, which could have been done before for 126754359Sroberto * both code paths but have been avoided for minimum path length to 126854359Sroberto * the uniq_time routine 126954359Sroberto */ 127054359Sroberto dname = (char *) 0; 127154359Sroberto q = za->za_ttycommon.t_readq; 127254359Sroberto 127354359Sroberto loopcheck = MAXDEPTH; 127454359Sroberto 127554359Sroberto /* 127654359Sroberto * the real thing for everything else ... 127754359Sroberto */ 127854359Sroberto while (q) 127954359Sroberto { 128054359Sroberto if (q->q_qinfo && q->q_qinfo->qi_minfo) 128154359Sroberto { 128254359Sroberto dname = q->q_qinfo->qi_minfo->mi_idname; 128354359Sroberto if (!Strcmp(dname, parseinfo.st_rdinit->qi_minfo->mi_idname)) 128454359Sroberto { 128554359Sroberto register int (*zsisr) P((struct zscom *)); 128654359Sroberto 128754359Sroberto /* 128854359Sroberto * back home - phew (hopping along stream queues might 128954359Sroberto * prove dangerous to your health) 129054359Sroberto */ 129154359Sroberto if ((zsisr = ((struct savedzsops *)((parsestream_t *)(void *)q->q_ptr)->parse_data)->oldzsops->zsop_xsint)) 129254359Sroberto return zsisr(zs); 129354359Sroberto else 129454359Sroberto panic("zs_xsisr: unable to locate original ISR"); 129554359Sroberto 129654359Sroberto parseprintf(DD_ISR, ("zs_xsisr: non CD event was processed for \"%s\"\n", dname)); 129754359Sroberto /* 129854359Sroberto * now back to our program ... 129954359Sroberto */ 130054359Sroberto return 0; 130154359Sroberto } 130254359Sroberto } 130354359Sroberto 130454359Sroberto q = q->q_next; 130554359Sroberto 130654359Sroberto if (!loopcheck--) 130754359Sroberto { 130854359Sroberto panic("zs_xsisr: STREAMS Queue corrupted - non CD event"); 130954359Sroberto } 131054359Sroberto } 131154359Sroberto 131254359Sroberto /* 131354359Sroberto * last resort - shouldn't even come here as it indicates 131454359Sroberto * corrupted TTY structures 131554359Sroberto */ 131654359Sroberto printf("zs_zsisr: looking for \"%s\" - found \"%s\" - taking EMERGENCY path\n", parseinfo.st_rdinit->qi_minfo->mi_idname, dname ? dname : "-NIL-"); 131754359Sroberto 131854359Sroberto if (emergencyzs && emergencyzs->zsop_xsint) 131954359Sroberto emergencyzs->zsop_xsint(zs); 132054359Sroberto else 132154359Sroberto panic("zs_xsisr: no emergency ISR handler"); 132254359Sroberto return 0; 132354359Sroberto} 132454359Sroberto#endif /* sun */ 132554359Sroberto 132654359Sroberto/* 132754359Sroberto * History: 132854359Sroberto * 132954359Sroberto * parsestreams.c,v 1330182007Sroberto * Revision 4.11 2005/04/16 17:32:10 kardel 1331182007Sroberto * update copyright 1332182007Sroberto * 1333182007Sroberto * Revision 4.10 2004/11/14 16:06:08 kardel 1334182007Sroberto * update Id tags 1335182007Sroberto * 1336182007Sroberto * Revision 4.9 2004/11/14 15:29:41 kardel 1337182007Sroberto * support PPSAPI, upgrade Copyright to Berkeley style 1338182007Sroberto * 133956746Sroberto * Revision 4.7 1999/11/28 09:13:53 kardel 134056746Sroberto * RECON_4_0_98F 134156746Sroberto * 134254359Sroberto * Revision 4.6 1998/12/20 23:45:31 kardel 134354359Sroberto * fix types and warnings 134454359Sroberto * 134554359Sroberto * Revision 4.5 1998/11/15 21:23:38 kardel 134654359Sroberto * ntp_memset() replicated in Sun kernel files 134754359Sroberto * 134854359Sroberto * Revision 4.4 1998/06/13 12:15:59 kardel 134954359Sroberto * superfluous variable removed 135054359Sroberto * 135154359Sroberto * Revision 4.3 1998/06/12 15:23:08 kardel 135254359Sroberto * fix prototypes 135354359Sroberto * adjust for ansi2knr 135454359Sroberto * 135554359Sroberto * Revision 4.2 1998/05/24 18:16:22 kardel 135654359Sroberto * moved copy of shadow status to the beginning 135754359Sroberto * 135854359Sroberto * Revision 4.1 1998/05/24 09:38:47 kardel 135954359Sroberto * streams initiated iopps calls (M_xHANGUP) are now consistent with the 136054359Sroberto * respective calls from zs_xsisr() 136154359Sroberto * simulation of CARRIER status to avoid unecessary M_xHANGUP messages 136254359Sroberto * 136354359Sroberto * Revision 4.0 1998/04/10 19:45:38 kardel 136454359Sroberto * Start 4.0 release version numbering 136554359Sroberto * 136654359Sroberto * from V3 3.37 log info deleted 1998/04/11 kardel 136754359Sroberto */ 1368