Ejemplo n.º 1
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;
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
0
/*
 * take external status interrupt (only CD interests us)
 */
static void
zs_xsisr(
	 struct zscom *zs
	 )
{
	register struct asyncline *za = (void *)zs->zs_priv;
	register queue_t *q;
	register unsigned char zsstatus;
	register int loopcheck;
	register unsigned char cdstate;
	register const char *dname = "-UNKNOWN-";
	timespec_t hres_time;

	/*
	 * pick up current state
	 */
	zsstatus = SCC_READ0();

	if (za->za_rr0 ^ (cdstate = zsstatus & ZSRR0_CD))
	{
		timestamp_t cdevent;
		register int status;
      
		/*
		 * time stamp
		 */
		gethrestime(&hres_time);
		cdevent.tv.tv_sec  = hres_time.tv_sec;
		cdevent.tv.tv_usec = hres_time.tv_nsec / 1000;

		q = za->za_ttycommon.t_readq;

		/*
		 * logical state
		 */
		status = cd_invert ? cdstate == 0 : cdstate != 0;

		/*
		 * 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 *)q->q_ptr)->parse_status & PARSE_ENABLE) &&
					    parse_iopps(&((parsestream_t *)q->q_ptr)->parse_io, 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 *)q->q_ptr)->parse_io);
					}
		  
					if (status)
					{
						((parsestream_t *)q->q_ptr)->parse_ppsclockev.tv = cdevent.tv;
						++(((parsestream_t *)q->q_ptr)->parse_ppsclockev.serial);
					}

					pprintf(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");
			}
		}

		if (cdstate)	/* fake CARRIER status - XXX currently not coordinated */
		  za->za_flags |= ZAS_CARR_ON;
		else
		  za->za_flags &= ~ZAS_CARR_ON;

		/*
		 * only pretend that CD and ignored transistion (SYNC,CTS)
		 * have been handled
		 */
		za->za_rr0 = (za->za_rr0 & ~ZSRR0_IGNORE) | (zsstatus & ZSRR0_IGNORE);

		if (((za->za_rr0 ^ zsstatus) & ~ZSRR0_IGNORE) == 0)
		{
			/*
			 * all done - kill status indication and return
			 */
			SCC_WRITE0(ZSWR0_RESET_STATUS); /* might kill other conditions here */
			return;
		}
	}      

	pprintf(DD_ISR, "zs_xsisr: non CD event 0x%x for \"%s\"\n", 
		(za->za_rr0 ^ zsstatus) & ~ZSRR0_CD,dname);
	/*
	 * 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 avioded 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 void (*zsisr) (struct zscom *);
		  
				/*
				 * back home - phew (hopping along stream queues might
				 * prove dangerous to your health)
				 */
				if ((zsisr = ((struct savedzsops *)((parsestream_t *)q->q_ptr)->parse_data)->oldzsops->zsop_xsint))
				    zsisr(zs);
				else
				    panic("zs_xsisr: unable to locate original ISR");
		  
				pprintf(DD_ISR, "zs_xsisr: non CD event was processed for \"%s\"\n", dname);
				/*
				 * now back to our program ...
				 */
				return;
			}
		}

		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");
}