예제 #1
0
/*
 * parse_inp_fnc_t inp_rcc8000
 *
 * grab data from input stream
 */
static u_long
inp_rcc8000(
	    parse_t      *parseio,
	    char         ch,
	    timestamp_t  *tstamp
	  )
{
	unsigned int rtc;

	parseprintf(DD_PARSE, ("inp_rcc8000(0x%p, 0x%x, ...)\n", (void*)parseio, ch));

	switch (ch)
	{
	case '\n':
		parseprintf(DD_PARSE, ("inp_rcc8000: EOL seen\n"));
		if ((rtc = parse_addchar(parseio, ch)) == PARSE_INP_SKIP)
			return parse_end(parseio);
		else
			return rtc;


	default:
		if (parseio->parse_index == 0) /* take sample at start of message */
		{
			parseio->parse_dtime.parse_stime = *tstamp; /* collect timestamp */
		}
		return parse_addchar(parseio, ch);
	}
}
예제 #2
0
파일: parse.c 프로젝트: ntpsec/ntpsec
bool
parse_timedout(
	       parse_t *parseio,
	       timestamp_t *tstamp,
	       struct timespec *del
	       )
{
	struct timespec delta;

	l_fp delt;

	delt = tstamp->fp;
	L_SUB(&delt, &parseio->parse_lastchar.fp);
	delta = lfp_uintv_to_tspec(delt);
	if (cmp_tspec(delta, *del) == TIMESPEC_GREATER_THAN)
	{
		parseprintf(DD_PARSE, ("parse: timedout: TRUE\n"));
		return true;
	}
	else
	{
		parseprintf(DD_PARSE, ("parse: timedout: FALSE\n"));
		return false;
	}
}
예제 #3
0
/*
 * parse_inp_fnc_t mbg_input
 *
 * grab data from input stream
 */
static u_long
mbg_input(
	  parse_t      *parseio,
	  char         ch,
	  timestamp_t  *tstamp
	  )
{
	unsigned int rtc;

	parseprintf(DD_PARSE, ("mbg_input(0x%p, 0x%x, ...)\n", (void*)parseio, ch));

	switch (ch)
	{
	case STX:
		parseprintf(DD_PARSE, ("mbg_input: STX seen\n"));

		parseio->parse_index = 1;
		parseio->parse_data[0] = ch;
		parseio->parse_dtime.parse_stime = *tstamp; /* collect timestamp */
		return PARSE_INP_SKIP;

	case ETX:
		parseprintf(DD_PARSE, ("mbg_input: ETX seen\n"));
		if ((rtc = parse_addchar(parseio, ch)) == PARSE_INP_SKIP)
			return parse_end(parseio);
		else
			return rtc;

	default:
		return parse_addchar(parseio, ch);
	}
}
예제 #4
0
/*
 * parse_inp_fnc_t inp_trimtaip
 *
 * grab data from input stream
 */
static u_long
inp_trimtaip(
	     parse_t      *parseio,
	     char         ch,
	     timestamp_t  *tstamp
	  )
{
	unsigned int rtc;

	parseprintf(DD_PARSE, ("inp_trimtaip(0x%lx, 0x%x, ...)\n", (long)parseio, ch));

	switch (ch)
	{
	case '>':
		parseprintf(DD_PARSE, ("inp_trimptaip: START seen\n"));

		parseio->parse_index = 1;
		parseio->parse_data[0] = ch;
		parseio->parse_dtime.parse_stime = *tstamp; /* collect timestamp */
		return PARSE_INP_SKIP;

	case '<':
		parseprintf(DD_PARSE, ("inp_trimtaip: END seen\n"));
		if ((rtc = parse_addchar(parseio, ch)) == PARSE_INP_SKIP)
			return parse_end(parseio);
		else
			return rtc;


	default:
		return parse_addchar(parseio, ch);
	}
}
예제 #5
0
/*
 * parse_inp_fnc_t inp_hopf6021
 *
 * grab data from input stream
 */
static u_long
inp_hopf6021(
	     parse_t      *parseio,
	     char         ch,
	     timestamp_t  *tstamp
	  )
{
	unsigned int rtc;

	parseprintf(DD_PARSE, ("inp_hopf6021(0x%lx, 0x%x, ...)\n", (long)parseio, ch));

	switch (ch)
	{
	case ETX:
		parseprintf(DD_PARSE, ("inp_hopf6021: EOL seen\n"));
		parseio->parse_dtime.parse_stime = *tstamp; /* collect timestamp */
		if ((rtc = parse_addchar(parseio, ch)) == PARSE_INP_SKIP)
			return parse_end(parseio);
		else
			return rtc;

	default:
		return parse_addchar(parseio, ch);
	}
}
예제 #6
0
파일: parse.c 프로젝트: ntpsec/ntpsec
unsigned int
parse_restart(
	      parse_t *parseio,
	      char ch
	      )
{
	unsigned int updated = PARSE_INP_SKIP;

	/*
	 * re-start packet - timeout - overflow - start symbol
	 */

	if (parseio->parse_index)
	{
		/*
		 * filled buffer - thus not end character found
		 * do processing now
		 */
		parseio->parse_data[parseio->parse_index] = '\0';
		memcpy(parseio->parse_ldata, parseio->parse_data, (unsigned)(parseio->parse_index+1));
		parseio->parse_ldsize = parseio->parse_index;
		updated = PARSE_INP_TIME;
	}

	parseio->parse_index = 1;
	parseio->parse_data[0] = ch;
	parseprintf(DD_PARSE, ("parse: parse_restart: buffer start (updated = %x)\n", updated));
	return updated;
}
예제 #7
0
static unsigned long
inp_sel240x( parse_t      *parseio,
	     unsigned int ch,
	     timestamp_t  *tstamp
	   )
{
	unsigned long rc;

	parseprintf( DD_PARSE,
	             ("inp_sel240x(0x%lx, 0x%x, ...)\n",(long)parseio, ch));

	switch( ch )
	{
	case '\x01':
		parseio->parse_index = 1;
		parseio->parse_data[0] = ch;
		parseio->parse_dtime.parse_stime = *tstamp;
		rc = PARSE_INP_SKIP;
		break;
	case '\n':
		if( (rc = parse_addchar(parseio, ch)) == PARSE_INP_SKIP )
		{
			rc = parse_end( parseio );
		}
		break;
	default:
		rc = parse_addchar( parseio, ch );
	}

	return rc;
}
예제 #8
0
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;
	}
}
예제 #9
0
/*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;
}
예제 #10
0
/*
 * 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;
	}
}
예제 #11
0
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;
}
예제 #12
0
파일: parse.c 프로젝트: ntpsec/ntpsec
/*ARGSUSED*/
void
parse_iodone(
	register parse_t *parseio
	)
{
	/*
	 * we need to clean up certain flags for the next round
	 */
	parseprintf(DD_PARSE, ("parse_iodone: DONE\n"));
	parseio->parse_dtime.parse_state = 0; /* no problems with ISRs */
}
예제 #13
0
파일: parse.c 프로젝트: ntpsec/ntpsec
/*ARGSUSED*/
void
parse_ioend(
	register parse_t *parseio
	)
{
	parseprintf(DD_PARSE, ("parse_ioend\n"));

	if (parseio->parse_pdata)
	    free(parseio->parse_pdata);

	if (parseio->parse_data)
	    free(parseio->parse_data);
}
예제 #14
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;
}
예제 #15
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"));
}
예제 #16
0
파일: parse.c 프로젝트: ntpsec/ntpsec
/*ARGSUSED*/
int
parse_iopps(
	register parse_t *parseio,
	register int status,
	register timestamp_t *ptime
	)
{
	register unsigned int updated = CVT_NONE;

	/*
	 * PPS pulse information will only be delivered to ONE clock format
	 * this is either the last successful conversion module with a ppssync
	 * routine, or a fixed format with a ppssync routine
	 */
	parseprintf(DD_PARSE, ("parse_iopps: STATUS %s\n", (status == SYNC_ONE) ? "ONE" : "ZERO"));

	if (clockformats[parseio->parse_lformat]->syncpps)
	{
		updated = (unsigned int) clockformats[parseio->parse_lformat]->syncpps(parseio, status == SYNC_ONE, ptime);
		parseprintf(DD_PARSE, ("parse_iopps: updated = 0x%x\n", updated));
	}

	return (updated & CVT_MASK) != CVT_NONE;
}
예제 #17
0
파일: parse.c 프로젝트: ntpsec/ntpsec
unsigned int
parse_end(
	  parse_t *parseio
	  )
{
	/*
	 * message complete processing
	 */
	parseio->parse_data[parseio->parse_index] = '\0';
	memcpy(parseio->parse_ldata, parseio->parse_data, (unsigned)(parseio->parse_index+1));
	parseio->parse_ldsize = parseio->parse_index;
	parseio->parse_index = 0;
	parseprintf(DD_PARSE, ("parse: parse_end: buffer end\n"));
	return PARSE_INP_TIME;
}
예제 #18
0
파일: parse.c 프로젝트: ntpsec/ntpsec
unsigned long
updatetimeinfo(
	       register parse_t *parseio,
	       register unsigned long   flags
	       )
{
		parseio->parse_lstate          = parseio->parse_dtime.parse_state | flags | PARSEB_TIMECODE;

		parseio->parse_dtime.parse_state = parseio->parse_lstate;

	parseprintf(DD_PARSE, ("updatetimeinfo status=0x%lx, time=%x\n",
			       (long)parseio->parse_dtime.parse_state,
	                       parseio->parse_dtime.parse_time.fp.l_ui));

	return CVT_OK;		/* everything fine and dandy... */
}
예제 #19
0
파일: parse.c 프로젝트: ntpsec/ntpsec
/*ARGSUSED*/
bool
parse_ioinit(
	register parse_t *parseio
	)
{
	parseprintf(DD_PARSE, ("parse_iostart\n"));

	parseio->parse_plen = 0;
	parseio->parse_pdata = (void *)0;

	parseio->parse_data = 0;
	parseio->parse_ldata = 0;
	parseio->parse_dsize = 0;

	parseio->parse_badformat = 0;
	parseio->parse_ioflags   = PARSE_IO_CS7;	/* usual unix default */
	parseio->parse_index     = 0;
	parseio->parse_ldsize    = 0;

	return true;
}
예제 #20
0
파일: parse.c 프로젝트: ntpsec/ntpsec
unsigned int
parse_addchar(
	      parse_t *parseio,
	      char ch
	      )
{
	/*
	 * add to buffer
	 */
	if (parseio->parse_index < parseio->parse_dsize)
	{
		/*
		 * collect into buffer
		 */
		parseprintf(DD_PARSE, ("parse: parse_addchar: buffer[%d] = 0x%x\n", parseio->parse_index, ch));
		parseio->parse_data[parseio->parse_index++] = (char)ch;
		return PARSE_INP_SKIP;
	}
	else
		/*
		 * buffer overflow - attempt to make the best of it
		 */
		return parse_restart(parseio, ch);
}
예제 #21
0
static u_long 
inp_varitext(
	     parse_t	 *parseio,
	     unsigned int ch,
	     timestamp_t *tstamp
	     )
{
  struct varitext *t = (struct varitext *)parseio->parse_pdata;
  int    rtc;

  parseprintf(DD_PARSE, ("inp_varitext(0x%lx, 0x%x, ...)\n", (long)parseio, ch));

  if (!t) 
    return PARSE_INP_SKIP;	/* local data not allocated - sigh! */

  if (ch == 'T') 
    t->tstamp = *tstamp;

  if ((t->previous_ch == 'T') && (ch == ':'))
    {
      parseprintf(DD_PARSE, ("inp_varitext: START seen\n"));

      parseio->parse_data[0] = 'T';
      parseio->parse_index=1;
      parseio->parse_dtime.parse_stime = t->tstamp; /* Time stamp at packet start */
      t->start_found = 1;
      t->end_found = 0;
      t->end_count = 0;
    }

  if (t->start_found)
    {
      if ((rtc = parse_addchar(parseio, ch)) != PARSE_INP_SKIP)
	{
	  parseprintf(DD_PARSE, ("inp_varitext: ABORTED due to too many characters\n"));

	  memset(t, 0, sizeof(struct varitext));
	  return rtc;
	}

      if (t->end_found) 
	{
	  if (++(t->end_count) == 4) /* Finally found the end of the message */
	    {
	      parseprintf(DD_PARSE, ("inp_varitext: END seen\n"));

	      memset(t, 0, sizeof(struct varitext));
	      if ((rtc = parse_addchar(parseio, 0)) == PARSE_INP_SKIP)
		return parse_end(parseio);
	      else
		return rtc;
	    }	
	}

      if ((t->previous_ch == '\r') && (ch == '\n')) 
	{
	  t->end_found = 1;
	}

    }
 
  t->previous_ch = ch;

  return PARSE_INP_SKIP;
}
예제 #22
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;
}
예제 #23
0
파일: parse.c 프로젝트: ntpsec/ntpsec
/*ARGSUSED*/
bool
parse_setfmt(
	parsectl_t *dct,
	parse_t    *parse
	)
{
	if (dct->parseformat.parse_count <= PARSE_TCMAX)
	{
		if (dct->parseformat.parse_count)
		{
			register unsigned short i;

			for (i = 0; i < nformats; i++)
			{
				if (!strcmp(dct->parseformat.parse_buffer, clockformats[i]->name))
				{
					if (parse->parse_pdata)
						free(parse->parse_pdata);
					parse->parse_pdata = 0;

					parse->parse_plen = clockformats[i]->plen;

					if (parse->parse_plen)
					{
						parse->parse_pdata = malloc(parse->parse_plen);
						if (!parse->parse_pdata)
						{
							parseprintf(DD_PARSE, ("set format failed: malloc for private data area failed\n"));
							return false;
						}
						memset((char *)parse->parse_pdata, 0, parse->parse_plen);
					}

					if (parse->parse_data)
						free(parse->parse_data);
					parse->parse_ldata = parse->parse_data = 0;

					parse->parse_dsize = clockformats[i]->length;

					if (parse->parse_dsize)
					{
						parse->parse_data = (char*)malloc((unsigned)(parse->parse_dsize * 2 + 2));
						if (!parse->parse_data)
						{
							if (parse->parse_pdata)
								free(parse->parse_pdata);
							parse->parse_pdata = 0;

							parseprintf(DD_PARSE, ("init failed: malloc for data area failed\n"));
							return false;
						}
					}


					/*
					 * leave room for '\0'
					 */
					parse->parse_ldata     = parse->parse_data + parse->parse_dsize + 1;

					parse->parse_lformat  = i;

					return true;
				}
			}
		}
	}
	return false;
}
예제 #24
0
파일: clk_rawdcf.c 프로젝트: execunix/vinos
static u_long
convert_rawdcf(
	       unsigned char   *buffer,
	       int              size,
	       struct dcfparam *dcfprm,
	       clocktime_t     *clock_time
	       )
{
	unsigned char *s = buffer;
	const unsigned char *b = dcfprm->onebits;
	const unsigned char *c = dcfprm->zerobits;
	int i;

	parseprintf(DD_RAWDCF,("parse: convert_rawdcf: \"%s\"\n", buffer));

	if (size < 57)
	{
#ifndef PARSEKERNEL
		msyslog(LOG_ERR, "parse: convert_rawdcf: INCOMPLETE DATA - time code only has %d bits", size);
#endif
		return CVT_NONE;
	}

	for (i = 0; i < size; i++)
	{
		if ((*s != *b) && (*s != *c))
		{
			/*
			 * we only have two types of bytes (ones and zeros)
			 */
#ifndef PARSEKERNEL
			msyslog(LOG_ERR, "parse: convert_rawdcf: BAD DATA - no conversion");
#endif
			return CVT_NONE;
		}
		if (*b) b++;
		if (*c) c++;
		s++;
	}

	/*
	 * check Start and Parity bits
	 */
	if ((ext_bf(buffer, DCF_S, dcfprm->zerobits) == 1) &&
	    pcheck(buffer, DCF_P_P1, dcfprm->zerobits) &&
	    pcheck(buffer, DCF_P_P2, dcfprm->zerobits) &&
	    pcheck(buffer, DCF_P_P3, dcfprm->zerobits))
	{
		/*
		 * buffer OK
		 */
		parseprintf(DD_RAWDCF,("parse: convert_rawdcf: parity check passed\n"));

		clock_time->flags  = PARSEB_S_ANTENNA|PARSEB_S_LEAP;
		clock_time->utctime= 0;
		clock_time->usecond= 0;
		clock_time->second = 0;
		clock_time->minute = ext_bf(buffer, DCF_M10, dcfprm->zerobits);
		clock_time->minute = TIMES10(clock_time->minute) + ext_bf(buffer, DCF_M1, dcfprm->zerobits);
		clock_time->hour   = ext_bf(buffer, DCF_H10, dcfprm->zerobits);
		clock_time->hour   = TIMES10(clock_time->hour) + ext_bf(buffer, DCF_H1, dcfprm->zerobits);
		clock_time->day    = ext_bf(buffer, DCF_D10, dcfprm->zerobits);
		clock_time->day    = TIMES10(clock_time->day) + ext_bf(buffer, DCF_D1, dcfprm->zerobits);
		clock_time->month  = ext_bf(buffer, DCF_MO0, dcfprm->zerobits);
		clock_time->month  = TIMES10(clock_time->month) + ext_bf(buffer, DCF_MO, dcfprm->zerobits);
		clock_time->year   = ext_bf(buffer, DCF_Y10, dcfprm->zerobits);
		clock_time->year   = TIMES10(clock_time->year) + ext_bf(buffer, DCF_Y1, dcfprm->zerobits);

		switch (ext_bf(buffer, DCF_Z, dcfprm->zerobits))
		{
		    case DCF_Z_MET:
			clock_time->utcoffset = -1*60*60;
			break;

		    case DCF_Z_MED:
			clock_time->flags     |= PARSEB_DST;
			clock_time->utcoffset  = -2*60*60;
			break;

		    default:
			parseprintf(DD_RAWDCF,("parse: convert_rawdcf: BAD TIME ZONE\n"));
			return CVT_FAIL|CVT_BADFMT;
		}

		if (ext_bf(buffer, DCF_A1, dcfprm->zerobits))
		    clock_time->flags |= PARSEB_ANNOUNCE;

		if (ext_bf(buffer, DCF_A2, dcfprm->zerobits))
		    clock_time->flags |= PARSEB_LEAPADD; /* default: DCF77 data format deficiency */

		if (ext_bf(buffer, DCF_R, dcfprm->zerobits))
		    clock_time->flags |= PARSEB_CALLBIT;

		parseprintf(DD_RAWDCF,("parse: convert_rawdcf: TIME CODE OK: %d:%d, %d.%d.%d, flags 0x%lx\n",
				       (int)clock_time->hour, (int)clock_time->minute, (int)clock_time->day, (int)clock_time->month,(int) clock_time->year,
				       (u_long)clock_time->flags));
		return CVT_OK;
	}
	else
	{
		/*
		 * bad format - not for us
		 */
#ifndef PARSEKERNEL
		msyslog(LOG_ERR, "parse: convert_rawdcf: parity check FAILED for \"%s\"", buffer);
#endif
		return CVT_FAIL|CVT_BADFMT;
	}
}
예제 #25
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;
}
예제 #26
0
파일: clk_rawdcf.c 프로젝트: execunix/vinos
/*
 * parse_cvt_fnc_t cvt_rawdcf
 * raw dcf input routine - needs to fix up 50 baud
 * characters for 1/0 decision
 */
static u_long
cvt_rawdcf(
	   unsigned char   *buffer,
	   int              size,
	   struct format   *param,
	   clocktime_t     *clock_time,
	   void            *local
	   )
{
	last_tcode_t  *t = (last_tcode_t *)local;
	unsigned char *s = (unsigned char *)buffer;
	unsigned char *e = s + size;
	const unsigned char *b = dcfparameter.onebits;
	const unsigned char *c = dcfparameter.zerobits;
	u_long       rtc = CVT_NONE;
	unsigned int i, lowmax, highmax, cutoff, span;
#define BITS 9
	unsigned char     histbuf[BITS];
	/*
	 * the input buffer contains characters with runs of consecutive
	 * bits set. These set bits are an indication of the DCF77 pulse
	 * length. We assume that we receive the pulse at 50 Baud. Thus
	 * a 100ms pulse would generate a 4 bit train (20ms per bit and
	 * start bit)
	 * a 200ms pulse would create all zeroes (and probably a frame error)
	 */

	for (i = 0; i < BITS; i++)
	{
		histbuf[i] = 0;
	}

	cutoff = 0;
	lowmax = 0;

	while (s < e)
	{
		unsigned int ch = *s ^ 0xFF;
		/*
		 * these lines are left as an excercise to the reader 8-)
		 */
		if (!((ch+1) & ch) || !*s)
		{

			for (i = 0; ch; i++)
			{
				ch >>= 1;
			}

			*s = (unsigned char) i;
			histbuf[i]++;
			cutoff += i;
			lowmax++;
		}
		else
		{
			parseprintf(DD_RAWDCF,("parse: cvt_rawdcf: character check for 0x%x@%d FAILED\n", *s, (int)(s - (unsigned char *)buffer)));
			*s = (unsigned char)~0;
			rtc = CVT_FAIL|CVT_BADFMT;
		}
		s++;
	}
예제 #27
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;
	}
}
예제 #28
0
/*
 * parse_inp_fnc_t gps_input
 *
 * grep binary data from input stream
 */
static u_long
gps_input(
	  parse_t      *parseio,
	  char ch,
	  timestamp_t  *tstamp
	  )
{
  CSUM calc_csum;                    /* used to compare the incoming csums */
  GPS_MSG_HDR header;
  struct msg_buf *msg_buf;

  msg_buf = (struct msg_buf *)parseio->parse_pdata;

  parseprintf(DD_PARSE, ("gps_input(0x%p, 0x%x, ...)\n", (void*)parseio, ch));

  if (!msg_buf)
    return PARSE_INP_SKIP;

  if ( msg_buf->phase == MBG_NONE )
    {                  /* not receiving yet */
      switch (ch)
	{
	case SOH:
	  parseprintf(DD_PARSE, ("gps_input: SOH seen\n"));

	  msg_buf->len = sizeof( header ); /* prepare to receive msg header */
	  msg_buf->phase = MBG_HEADER; /* receiving header */
	  break;

	case STX:
	  parseprintf(DD_PARSE, ("gps_input: STX seen\n"));

	  msg_buf->len = 0;
	  msg_buf->phase = MBG_STRING; /* prepare to receive ASCII ETX delimited message */
	  parseio->parse_index = 1;
	  parseio->parse_data[0] = ch;
	  break;

	default:
	  return PARSE_INP_SKIP;	/* keep searching */
	}

      parseio->parse_dtime.parse_msglen = 1; /* reset buffer pointer */
      parseio->parse_dtime.parse_msg[0] = ch; /* fill in first character */
      parseio->parse_dtime.parse_stime  = *tstamp; /* collect timestamp */
      return PARSE_INP_SKIP;
    }

  /* SOH/STX has already been received */

  /* save incoming character in both buffers if needbe */
  if ((msg_buf->phase == MBG_STRING) &&
      (parseio->parse_index < parseio->parse_dsize))
    parseio->parse_data[parseio->parse_index++] = ch;

  parseio->parse_dtime.parse_msg[parseio->parse_dtime.parse_msglen++] = ch;

  if (parseio->parse_dtime.parse_msglen > sizeof(parseio->parse_dtime.parse_msg))
    {
      msg_buf->phase = MBG_NONE; /* buffer overflow - discard */
      parseio->parse_data[parseio->parse_index] = '\0';
      memcpy(parseio->parse_ldata, parseio->parse_data, (unsigned)(parseio->parse_index+1));
      parseio->parse_ldsize = parseio->parse_index;
      return PARSE_INP_DATA;
    }

  switch (msg_buf->phase)
    {
    case MBG_HEADER:
    case MBG_DATA:
      msg_buf->len--;

      if ( msg_buf->len )               /* transfer not complete */
	return PARSE_INP_SKIP;

      parseprintf(DD_PARSE, ("gps_input: %s complete\n", (msg_buf->phase == MBG_DATA) ? "data" : "header"));

      break;

    case MBG_STRING:
      if ((ch == ETX) || (parseio->parse_index >= parseio->parse_dsize))
	{
	  msg_buf->phase = MBG_NONE;
	  parseprintf(DD_PARSE, ("gps_input: string complete\n"));
	  parseio->parse_data[parseio->parse_index] = '\0';
	  memcpy(parseio->parse_ldata, parseio->parse_data, (unsigned)(parseio->parse_index+1));
	  parseio->parse_ldsize = parseio->parse_index;
	  parseio->parse_index = 0;
	  return PARSE_INP_TIME;
	}
      else
	{
	  return PARSE_INP_SKIP;
	}
    }

  /* cnt == 0, so the header or the whole message is complete */

  if ( msg_buf->phase == MBG_HEADER )
    {         /* header complete now */
      unsigned char *datap = parseio->parse_dtime.parse_msg + 1;

      get_mbg_header(&datap, &header);

      parseprintf(DD_PARSE, ("gps_input: header: cmd 0x%x, len %d, dcsum 0x%x, hcsum 0x%x\n",
			     (int)header.cmd, (int)header.len, (int)header.data_csum,
			     (int)header.hdr_csum));


      calc_csum = mbg_csum( (unsigned char *) parseio->parse_dtime.parse_msg + 1, (unsigned short)6 );

      if ( calc_csum != header.hdr_csum )
	{
	  parseprintf(DD_PARSE, ("gps_input: header checksum mismatch expected 0x%x, got 0x%x\n",
				 (int)calc_csum, (int)mbg_csum( (unsigned char *) parseio->parse_dtime.parse_msg, (unsigned short)6 )));

	  msg_buf->phase = MBG_NONE;  /* back to hunting mode */
	  return PARSE_INP_DATA;      /* invalid header checksum received - pass up for detection */
	}

      if ((header.len == 0)  ||       /* no data to wait for */
	  (header.len >= (sizeof (parseio->parse_dtime.parse_msg) - sizeof(header) - 1)))	/* blows anything we have space for */
	{
	  msg_buf->phase = MBG_NONE;  /* back to hunting mode */
	  return (header.len == 0) ? PARSE_INP_DATA : PARSE_INP_SKIP; /* message complete/throwaway */
	}

      parseprintf(DD_PARSE, ("gps_input: expecting %d bytes of data message\n", (int)header.len));

      msg_buf->len   = header.len;/* save number of bytes to wait for */
      msg_buf->phase = MBG_DATA;      /* flag header already complete */
      return PARSE_INP_SKIP;
    }

  parseprintf(DD_PARSE, ("gps_input: message data complete\n"));

  /* Header and data have been received. The header checksum has been */
  /* checked */

  msg_buf->phase = MBG_NONE;	      /* back to hunting mode */
  return PARSE_INP_DATA;              /* message complete, must be evaluated */
}
예제 #29
0
/*
 * 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) (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;
}
예제 #30
0
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;
		}
	}
}