⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fas.c

📁 一个通讯程序源码
💻 C
📖 第 1 页 / 共 5 页
字号:
		goto sched;	/* Determine how many chars to put into the transmitter	   register.	*/	if (fip->xmit_ring_cnt < num_to_output)		num_to_output = fip->xmit_ring_cnt;	/* no characters available ? */	if (!num_to_output)		goto sched;	/* output characters */	fip->xmit_ring_cnt -= num_to_output;	fas_ctl (fip, XMT_DATA_PORT);#if defined(FASI)	fip->characters_transmitted += num_to_output;#endif /* FASI */	do	{		do		{			(void) outb (XMT_DATA_PORT.addr,					*fip->xmit_ring_take_ptr);			if (++fip->xmit_ring_take_ptr					== &fip->xmit_buffer [XMIT_BUFF_SIZE])				break;		} while (--num_to_output);		if (!num_to_output)			break;		fip->xmit_ring_take_ptr = &fip->xmit_buffer [0];	} while (--num_to_output);	/* signal that transmitter is busy now */	fip->device_flags.s |= DF_XMIT_BUSY;	/* disable guard timeout */	if (fip->device_flags.i & DF_GUARD_TIMEOUT)	{		fip->device_flags.s &= ~DF_GUARD_TIMEOUT;		fip->tty->t_state &= ~TIMEOUT;		(void) untimeout (fip->timeout_idx);	}	/* schedule fas_xxfer () if there are more characters to transfer	   into the transmitter ring buffer	*/sched:	if ((fip->xmit_ring_size > fip->xmit_ring_cnt)		&& (fip->tty->t_outq.c_cc || fip->tty->t_tbuf.c_count))	{		event_sched (fip, EF_DO_XXFER);	}}/* Asynchronous event handler. Scheduled by functions that can't do the   processing themselves because of execution time restrictions.*/static voidfas_event (dummy)void	*dummy;{	register struct fas_info	*fip;	register uint	unit;	int	old_level;	old_level = SPLINT ();	unit = 0;	fip = &fas_info [0];	/* loop through all fas_info structures */	for (;; fip++, unit++)	{	    if (unit >= fas_physical_units)		break;	/* all structures done */	    /* process only structures that actually need to	       be serviced	    */fastloop2:	    if (!fip->event_flags.i)	    {		/* speed beats beauty */		fip++;		if (++unit < fas_physical_units)			goto fastloop2;		break;	    }	    do	    {		/* check the modem signals */		if (fip->event_flags.i & EF_DO_MPROC)		{			fip->event_flags.s &= ~EF_DO_MPROC;			fas_mproc (fip);			/* disable the device if there were too many modem			   status interrupts			*/			if (fip->msi_cnt > (MAX_MSI_CNT / HZ)						* (EVENT_TIME * HZ / 1000))			{				fip->device_flags.s &= ~(DF_DEVICE_CONFIGURED							| DF_XMIT_BUSY							| DF_XMIT_BREAK);				fip->device_flags.s |= DF_XMIT_LOCKED;				if (fip->device_flags.i & DF_GUARD_TIMEOUT)				{					fip->device_flags.s &=							~DF_GUARD_TIMEOUT;					fip->tty->t_state &= ~TIMEOUT;					(void) untimeout (fip->timeout_idx);					(void) wakeup ((caddr_t) &(fip)->								device_flags.i);				}				fip->tty->t_state &= ~CARR_ON;				(void) SPLWRK ();				if (!(fip->cflag & CLOCAL)					&& (fip->tty->t_state & ISOPEN))					(void) signal (fip->tty->t_pgrp,								SIGHUP);				(void) ttyflush (fip->tty, FREAD | FWRITE);				(void) printf ("\nWARNING: Excessive modem status interrupts on FAS unit %d (check the cabling).\n",							fip - &fas_info [0]);				(void) SPLINT ();			}			fip->msi_cnt = 0;		}		/* do the break interrupt */		if (fip->event_flags.i & EF_DO_BRKINT)		{			fip->event_flags.s &= ~EF_DO_BRKINT;			if (fip->tty->t_state & ISOPEN)			{				(void) SPLWRK ();				(*linesw [fip->tty->t_line].l_input)							(fip->tty, L_BREAK);				(void) SPLINT ();			}		}		/* transfer characters to the UNIX input buffer */		if (fip->event_flags.i & EF_DO_RXFER)		{			fip->event_flags.s &= ~EF_DO_RXFER;			if (!(fip->flow_flags.i & FF_RXFER_STOPPED))			{				(void) SPLWRK ();				fas_rxfer (fip);				(void) SPLINT ();				/* check input buffer high/low water marks */				fas_ihlw_check (fip);			}		}		/* transfer characters to the output ring buffer */		if (fip->event_flags.i & EF_DO_XXFER)		{			fip->event_flags.s &= ~EF_DO_XXFER;			(void) SPLWRK ();			fas_xxfer (fip);			(void) SPLINT ();			fas_hdx_check (fip);			/* output characters */			fas_xproc (fip);		}#if defined (HAVE_VPIX)		/* send pseudorupt to VP/ix */		if (fip->event_flags.i & EF_SIGNAL_VPIX)		{			fip->event_flags.s &= ~EF_SIGNAL_VPIX;			if ((fip->iflag & DOSMODE) && fip->v86_proc)			{				(void) SPLWRK ();				(void) v86setint (fip->v86_proc,							fip->v86_intmask);				(void) SPLINT ();			}		}#endif	    } while (fip->event_flags.i);	    /* allow pending tty interrupts */	    (void) SPLWRK ();	    (void) SPLINT ();	}	event_scheduled = FALSE;	/* check whether there have been new requests in the mean time */	for (unit = 0, fip = &fas_info [0]; unit < fas_physical_units;							fip++, unit++)		if (fip->event_flags.i)		{			/* there is at least one new request, so			   schedule the next event processing			*/			event_scheduled = TRUE;			(void) timeout (fas_event, (void *) NULL,					(EVENT_TIME) * (HZ) / 1000);			break;		}#if defined(FASI)	(void)wakeup((caddr_t)&fip->device_flags.i);#endif /* FASI */	(void) splx (old_level);}#if defined (HAVE_VPIX)/* Send port status register to VP/ix */static intfas_vpix_sr (fip, token, status)register struct fas_info	*fip;uint	token;uint	status;{	if ((fip->recv_ring_cnt <= RECV_BUFF_SIZE - 3)		&& ((fip->tty->t_state & (ISOPEN | CARR_ON)) ==						(ISOPEN | CARR_ON)))	{		/* sent the character sequence 0xff, <token>, <status>		   to VP/ix		*/		fip->recv_ring_cnt += 3;		*fip->recv_ring_put_ptr = 0xff;		if (++fip->recv_ring_put_ptr				== &fip->recv_buffer [RECV_BUFF_SIZE])			fip->recv_ring_put_ptr				= &fip->recv_buffer [0];		*fip->recv_ring_put_ptr = token;		if (++fip->recv_ring_put_ptr				== &fip->recv_buffer [RECV_BUFF_SIZE])			fip->recv_ring_put_ptr				= &fip->recv_buffer [0];		*fip->recv_ring_put_ptr = status;		if (++fip->recv_ring_put_ptr				== &fip->recv_buffer [RECV_BUFF_SIZE])			fip->recv_ring_put_ptr				= &fip->recv_buffer [0];		return (TRUE);	}	return (FALSE);}#endif/* Receiver ring buffer -> UNIX buffer transfer function. */static voidfas_rxfer (fip)register struct fas_info	*fip;{	register struct tty	*ttyp;	register int	num_to_xfer;	int	num_save;	int	old_level;	ttyp = fip->tty;	for (;;)	{		if (!fip->recv_ring_cnt || !ttyp->t_rbuf.c_ptr)			break;	/* no characters to transfer */		/* determine how many characters to transfer */#if defined (HAVE_VPIX)		num_to_xfer = ((fip->iflag & DOSMODE)				? MAX_VPIX_FILL				: MAX_UNIX_FILL) - ttyp->t_rawq.c_cc;#else		num_to_xfer = MAX_UNIX_FILL - ttyp->t_rawq.c_cc;#endif		if (num_to_xfer < MIN_READ_CHUNK)			break;	/* input buffer full */#if defined (HAVE_VPIX)		/* wakeup VP/ix */		if ((fip->iflag & DOSMODE) && !ttyp->t_rawq.c_cc)			event_sched (fip, EF_SIGNAL_VPIX);#endif		/* determine how many characters are in one contigous block */		if (fip->recv_ring_cnt < num_to_xfer)			num_to_xfer = fip->recv_ring_cnt;		if (&fip->recv_buffer [RECV_BUFF_SIZE] - fip->recv_ring_take_ptr			< num_to_xfer)			num_to_xfer = &fip->recv_buffer [RECV_BUFF_SIZE]					- fip->recv_ring_take_ptr;		if (ttyp->t_rbuf.c_count < num_to_xfer)			num_to_xfer = ttyp->t_rbuf.c_count;		num_save = num_to_xfer;		ttyp->t_rbuf.c_count -= num_to_xfer;		/* do the transfer */		do		{			*ttyp->t_rbuf.c_ptr = *fip->recv_ring_take_ptr;			ttyp->t_rbuf.c_ptr++;			fip->recv_ring_take_ptr++;		} while (--num_to_xfer);		if (fip->recv_ring_take_ptr == &fip->recv_buffer [RECV_BUFF_SIZE])			fip->recv_ring_take_ptr = &fip->recv_buffer [0];		intr_disable ();		fip->recv_ring_cnt -= num_save;		intr_restore ();		ttyp->t_rbuf.c_ptr -= ttyp->t_rbuf.c_size					- ttyp->t_rbuf.c_count;		(*linesw [ttyp->t_line].l_input) (ttyp, L_BUF);	}}/* UNIX buffer -> transmitter ring buffer transfer function. */static voidfas_xxfer (fip)register struct fas_info	*fip;{	register struct tty	*ttyp;	register int	num_to_xfer;	int	num_save;	int	old_level;	ttyp = fip->tty;	for (;;)	{		/* Check if tbuf is empty. If it is empty, reset buffer		   pointer and counter and get the next chunk of output		   characters.		*/		if (!ttyp->t_tbuf.c_ptr || !ttyp->t_tbuf.c_count)		{			if (ttyp->t_tbuf.c_ptr)				ttyp->t_tbuf.c_ptr -= ttyp->t_tbuf.c_size;			if (!((*linesw [ttyp->t_line].l_output) (ttyp)					& CPRES))				break;		}		/* set the maximum character limit */		num_to_xfer = fip->xmit_ring_size - fip->xmit_ring_cnt;		/* Return if transmitter ring buffer is full. */		if (num_to_xfer < 1)			break;		/* Determine how many chars to transfer this time. */		if (&fip->xmit_buffer [XMIT_BUFF_SIZE] - fip->xmit_ring_put_ptr			< num_to_xfer)			num_to_xfer = &fip->xmit_buffer [XMIT_BUFF_SIZE]					- fip->xmit_ring_put_ptr;		if (ttyp->t_tbuf.c_count < num_to_xfer)			num_to_xfer = ttyp->t_tbuf.c_count;		num_save = num_to_xfer;		ttyp->t_tbuf.c_count -= num_to_xfer;		ttyp->t_state |= BUSY;		/* do the transfer */		do		{			*fip->xmit_ring_put_ptr = *ttyp->t_tbuf.c_ptr;			ttyp->t_tbuf.c_ptr++;			fip->xmit_ring_put_ptr++;		} while (--num_to_xfer);		if (fip->xmit_ring_put_ptr == &fip->xmit_buffer [XMIT_BUFF_SIZE])			fip->xmit_ring_put_ptr = &fip->xmit_buffer [0];		intr_disable ();		fip->xmit_ring_cnt += num_save;		intr_restore ();	}}/* Input buffer high/low water mark check. */static voidfas_ihlw_check (fip)register struct fas_info	*fip;{	REGVAR;	if (fip->flow_flags.i & FF_HWI_STOPPED)	{		/* If input buffer level has dropped below		   the low water mark and input was stopped		   by hardware handshake, restart input.		*/		if (fip->recv_ring_cnt < HW_LOW_WATER)		{			fip->mcr |= fip->flow.m.ic;			fas_first_outb (fip, MDM_CTL_PORT, fip->mcr);			fip->flow_flags.s &= ~FF_HWI_STOPPED;		}	}	else	{		/* If input buffer level has risen above the		   high water mark and input is not yet		   stopped, stop input by hardware handshake.		*/		if ((fip->flow_flags.i & FF_HWI_HANDSHAKE)			&& (fip->recv_ring_cnt > HW_HIGH_WATER))		{			fip->mcr &= ~fip->flow.m.ic;			fas_first_outb (fip, MDM_CTL_PORT, fip->mcr);			fip->flow_flags.s |= FF_HWI_STOPPED;#if defined(FASI)			fip->rcvr_hw_flow_count++;			(void)wakeup((caddr_t)&fip->device_flags.i);#endif /* FASI */		}	}	if (fip->flow_flags.i & FF_SWI_STOPPED)	{		/* If input buffer level has dropped below		   the low water mark and input was stopped		   by XOFF, send XON to restart input.		*/		if (!(fip->iflag & IXOFF)			|| (fip->recv_ring_cnt < SW_LOW_WATER))		{			fip->flow_flags.s &= ~FF_SWI_STOPPED;			fip->flow_flags.s ^= FF_SW_FC_REQ;			if (fip->flow_flags.i & FF_SW_FC_REQ)			{				fip->tty->t_state |= TTXON;				fas_xproc (fip);			}			else				fip->tty->t_state &= ~TTXOFF;		}	}	else	{		/* If input buffer level has risen above the		   high water mark and input is not yet		   stopped, send XOFF to stop input.		*/		if ((fip->iflag & IXOFF)			&& (fip->recv_ring_cnt > SW_HIGH_WATER))		{			fip->flow_flags.s |= FF_SWI_STOPPED;			fip->flow_flags.s ^= FF_SW_FC_REQ;			if (fip->flow_flags.i & FF_SW_FC_REQ)			{				fip->tty->t_state |= TTXOFF;				fas_xproc (fip);#if defined(FASI)				fip->rcvr_sw_flow_count++;				(void)wakeup((caddr_t)&fip->device_flags.i);#endif /* FASI */			}			else				fip->tty->t_state &= ~TTXON;		}	}}/* Half-duplex hardware flow control check. */static voidfas_hdx_check (fip)register struct fas_info	*fip;{	REGVAR;	/* don't interfere with hardware input handshake */	if (fip->flow_flags.i & FF_HWI_HANDSHAKE)		return;#if defined (HAVE_VPIX)	/* don't touch the mcr if we are in dos mode and hdx hardware	   handshake is disabled (dos handles the handshake line(s)	   on its own in this mode)	*/	if ((fip->iflag & DOSMODE) && !(fip->flow_flags.i & FF_HDX_HANDSHAKE))		return;#endif	if (fip->flow_flags.i & FF_HDX_STARTED)	{		/* If output buffer is empty signal the connected		   device that all output is done.		*/		if ((fip->flow_flags.i & FF_HDX_HANDSHAKE)			&& !(fip->tty->t_state & BUSY))		{			fip->mcr &= ~fip->flow.m.hc;			fas_first_outb (fip, MDM_CTL_PORT, fip->mcr);			fip->flow_flags.s &= ~FF_HDX_STARTED;		}	}	else	{		/* If the output ring buffer contains characters		   and was previously empty signal the connected		   device that output is resumed.		*/		if (!(fip->flow_flags.i & FF_HDX_HANDSHAKE)			|| (fip->tty->t_state & BUSY))		{			fip->mcr |= fip->flow.m.hc;			fas_first_outb (fip, MDM_CTL_PORT, fip->mcr);			fip->flow_flags.s |= FF_HDX_STARTED;		}	}}/* Handle hangup after last close */static voidfas_hangup (fip)register struct fas_info	*fip;{	int	old_level;	REGVAR;	old_level = SPLINT

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -