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

📄 fas.c

📁 一个通讯程序源码
💻 C
📖 第 1 页 / 共 5 页
字号:
			done = FALSE;	/* not done if we got an int */			old_recv_count = fip->recv_ring_cnt;			do			{				/* read in all the characters from the FIFO */				if ((status = fas_inb (fip, LINE_STATUS_PORT))							& LS_RCV_INT)				{				    if (!drop_mode && (fip->device_flags.i						& DF_DEVICE_IS_NS16550A))				    {					/* Drop receiver trigger levels to make					   sure that we will see all received					   characters in all NS16550A. This					   prevents multiple interrupts if we					   receive characters on more than one					   unit.					*/					old_fip = fip;					for (fip = fas_first_int_user [vect];						fip; fip = fip->next_int_user)					{					    if ((fip->device_flags.i							& DF_DEVICE_IS_NS16550A)						&& (fip != old_fip))					    {						fip->device_flags.s |=							DF_NS16550A_DROP_MODE;						fas_first_outb (fip,							NS_FIFO_CTL_PORT,							NS_FIFO_DROP_CMD);					    }					}					fip = old_fip;					drop_mode = TRUE;				    }				    status = fas_rproc (fip, status);				    sysinfo.rcvint++;				}				/* Is it a transmitter empty int ? */				if ((status & LS_XMIT_AVAIL)					&& (fip->device_flags.i & DF_XMIT_BUSY))				{					fip->device_flags.s &= ~DF_XMIT_BUSY;					fas_xproc (fip);					if (!(fip->device_flags.i							& DF_XMIT_BUSY))					{						fip->device_flags.s |=							DF_GUARD_TIMEOUT;						fip->tty->t_state |=							TIMEOUT;						fip->timeout_idx =							timeout (							fas_timeout, fip,							fas_ctimes [fip->cflag								& CBAUD]);					}					sysinfo.xmtint++;				}				/* Has there been a polarity change on				   some of the modem lines ?				*/				if ((status = fas_inb (fip, MDM_STATUS_PORT))						& MS_ANY_DELTA)				{					/* Do special RING line handling.					   RING generates an int only on the					   trailing edge.					*/					status = (status & ~MS_RING_PRESENT)						| (fip->new_msr							& MS_RING_PRESENT);					if (status & MS_RING_TEDGE)#if defined(FASI)						fip->rings_detected++,#endif /* FASI */						status |= MS_RING_PRESENT;					if ((status ^ fip->new_msr)							& MS_ANY_PRESENT)					{						/* check for excessive modem						   status interrupts						*/						if (++fip->msi_cnt >							(MAX_MSI_CNT / HZ)							  * (EVENT_TIME * HZ								/ 1000))						{							fip->ier = IE_NONE;							fas_outb (fip,								INT_ENABLE_PORT,								fip->ier);						}						/* check hw flow flags */						fas_fproc (fip, status);						fip->new_msr = status;						event_sched (fip, EF_DO_MPROC);					}					sysinfo.mdmint++;#if defined(FASI)					fip->modem_status_events++;#endif /* FASI */				}			} while (!(fas_inb (fip, INT_ID_PORT)						& II_NO_INTS_PENDING));			/* schedule character transfer to UNIX buffer */			if (fip->recv_ring_cnt#if defined (HAVE_VPIX)				&& (((fip->iflag & DOSMODE)					? MAX_VPIX_FILL - MIN_READ_CHUNK					: MAX_UNIX_FILL - MIN_READ_CHUNK)						>= fip->tty->t_rawq.c_cc)#else				&& ((MAX_UNIX_FILL - MIN_READ_CHUNK)						>= fip->tty->t_rawq.c_cc)#endif				&& !(fip->flow_flags.i & FF_RXFER_STOPPED))			{				event_sched (fip, EF_DO_RXFER);			}			/* check input buffer high/low water marks */			if (fip->recv_ring_cnt != old_recv_count)				fas_ihlw_check (fip);		}	} while (!done);	/* clear the shared interrupt since we have scanned all	   of the ports that share this interrupt vector	*/		if (port = fas_int_ack_port [vect])		(void) outb (port, fas_int_ack [vect]);	return (0);}/* hardware flow control interrupt handler */static voidfas_fproc (fip, mdm_status)register struct fas_info	*fip;register uint	mdm_status;{	/* Check the output flow control signals and set the state flag	   accordingly.	*/	if (!(~mdm_status & fip->flow.m.oc)		|| (~mdm_status & fip->flow.m.oe)		|| !(fip->flow_flags.i & FF_HWO_HANDSHAKE))	{		if (fip->flow_flags.i & FF_HWO_STOPPED)		{			fip->flow_flags.s &= ~FF_HWO_STOPPED;			fas_xproc (fip);		}	}	else#if defined(FASI)		fip->xmtr_hw_flow_count++,		wakeup((caddr_t)&fip->device_flags.i),#endif /* FASI */		fip->flow_flags.s |= FF_HWO_STOPPED;}/* modem status handler */static voidfas_mproc (fip)register struct fas_info	*fip;{	register struct tty	*ttyp;	register uint	mdm_status;	uint	vpix_status;	int	old_level;	ttyp = fip->tty;	mdm_status = fip->new_msr;	fip->new_msr &= ~MS_RING_PRESENT;	/* Check the carrier detect signal and set the state flags	   accordingly. Also, if not in clocal mode, send SIGHUP on	   carrier loss and flush the buffers.	*/	if (!(fip->cflag & CLOCAL))	{		if (!(~mdm_status & fip->modem.m.ca))		{			ttyp->t_state |= CARR_ON;			/* Unblock getty open only if it is ready to run. */			if ((ttyp->t_state & WOPEN)				&& (~fip->msr & fip->modem.m.ca))#if defined(FASI)			{#endif				(void) wakeup ((caddr_t) &ttyp->t_canq);#if defined(FASI)				(void)wakeup((caddr_t)&fip->device_flags.i);			}#endif		}		else		{			if (!(~fip->msr & fip->modem.m.ca))			{				ttyp->t_state &= ~CARR_ON;				old_level = SPLWRK ();				if (ttyp->t_state & ISOPEN)					(void) signal (ttyp->t_pgrp, SIGHUP);				(void) ttyflush (ttyp, FREAD | FWRITE);				(void) splx (old_level);			}		}	}#if defined (HAVE_VPIX)	if (((fip->iflag & (DOSMODE | PARMRK))			== (DOSMODE | PARMRK))		&& (fip->v86_intmask != V86VI_KBD))	{		/* prepare status bits for VP/ix */		vpix_status = (((mdm_status ^ fip->msr) >> 4) & MS_ANY_DELTA)				| (mdm_status & (MS_CTS_PRESENT							| MS_DSR_PRESENT							| MS_DCD_PRESENT));		if (fip->flow_flags.i & FF_HWO_HANDSHAKE)		{			vpix_status &= ~((fip->flow.m.oc | fip->flow.m.oe)							>> 4);			vpix_status |= fip->flow.m.oc | fip->flow.m.oe;		}		/* send status bits to VP/ix */		if ((vpix_status & MS_ANY_DELTA)			&& fas_vpix_sr (fip, 2, vpix_status))			event_sched (fip, EF_DO_RXFER);	}#endif	fip->msr = mdm_status & ~MS_RING_PRESENT;	/* re-schedule if modem status flags have changed in the mean time */	if ((fip->new_msr ^ fip->msr) & MS_ANY_PRESENT)	{		event_sched (fip, EF_DO_MPROC)	}#if defined(FASI)	else		(void)wakeup((caddr_t)&fip->device_flags.i);#endif /* FASI */}/* Receiver interrupt handler. Translates input characters to character   sequences as described in TERMIO(7) man page.*/static uintfas_rproc (fip, line_status)register struct fas_info	*fip;uint	line_status;{	struct tty	*ttyp;	uint	charac;	register uint	csize;	unchar	metta [4];	REGVAR;	ttyp = fip->tty;	fas_first_ctl (fip, RCV_DATA_PORT);	/* Translate characters from FIFO according to the TERMIO(7)	   man page.	*/	do	{		charac = (line_status & LS_RCV_AVAIL)#if defined(FASI)				? (fip->characters_received++,fas_inb (fip, RCV_DATA_PORT))#else				? fas_inb (fip, RCV_DATA_PORT)#endif /* FASI */				: 0;	/* was line status int only */		/* do we have to junk the character ? */		if (!(fip->cflag & CREAD)			|| ((ttyp->t_state & (ISOPEN | CARR_ON)) !=						(ISOPEN | CARR_ON)))		{			/* if there are FIFOs we take a short cut */			if (fip->device_flags.i & DF_DEVICE_IS_NS16550A)				fas_outb (fip, NS_FIFO_CTL_PORT, NS_FIFO_SETUP_CMD							| NS_FIFO_CLR_RECV);			else if (fip->device_flags.i & DF_DEVICE_IS_I82510)			{				fas_outb (fip, I_BANK_PORT, I_BANK_1);				fas_outb (fip, I_RCM_PORT, I_FIFO_CLR_RECV);				fas_outb (fip, I_BANK_PORT, I_BANK_0);			}			continue;		}		csize = 0;		/* strip off 8th bit ? */		if (fip->iflag & ISTRIP)			charac &= 0x7f;		/* ignore parity errors ? */		if ((line_status & LS_PARITY_ERROR)			&& !(fip->iflag & INPCK))			line_status &= ~LS_PARITY_ERROR;#if defined(FASI)		if(line_status & LS_OVERRUN)			fip->overrun_errors++;#endif /* FASI */		/* do we have some kind of character error ? */		if (line_status & (LS_PARITY_ERROR					| LS_FRAMING_ERROR					| LS_BREAK_DETECTED))		{#if defined(FASI)			if(line_status & LS_PARITY_ERROR)				fip->parity_errors++;			if(line_status & LS_FRAMING_ERROR)				fip->framing_errors++;			if(line_status & LS_BREAK_DETECTED)				fip->breaks_detected++;#endif /* FASI */#if defined (HAVE_VPIX)			if ((fip->iflag & (DOSMODE | PARMRK))					== (DOSMODE | PARMRK))			{				/* send status bits to VP/ix */				(void) fas_vpix_sr (fip, 1,					(line_status & (LS_PARITY_ERROR							| LS_FRAMING_ERROR							| LS_BREAK_DETECTED))						| LS_RCV_AVAIL						| LS_XMIT_AVAIL						| LS_XMIT_COMPLETE);				goto valid_char;			}#endif			/* is it a BREAK ? */			if (line_status & LS_BREAK_DETECTED)			{				if (!(fip->iflag & IGNBRK))					if (fip->iflag & BRKINT)					{						/* do BREAK interrupt */						event_sched (fip, EF_DO_BRKINT);					}					else					{						metta [csize] = 0;						csize++;						if (fip->iflag & PARMRK)						{							metta [csize] = 0;							csize++;							metta [csize] = 0xff;							csize++;						}					}			}			else if (!(fip->iflag & IGNPAR))				if (fip->iflag & PARMRK)				{					metta [csize] = charac;					csize++;					metta [csize] = 0;					csize++;					metta [csize] = 0xff;					csize++;				}				else				{					metta [csize] = 0;					csize++;				}		}		else		/* is there a character to process ? */		if (line_status & LS_RCV_AVAIL)		{			if (fip->iflag & IXON)			{				/* do output start/stop handling */				if (fip->flow_flags.i & FF_SWO_STOPPED)				{#if defined (HAVE_VPIX)					if ((charac == fip->v86_ss.ss_start)#else					if ((charac == CSTART)#endif						|| (fip->iflag & IXANY))					{						fip->flow_flags.s &=							~FF_SWO_STOPPED;						ttyp->t_state &= ~TTSTOP;						/* restart output */						fas_xproc (fip);					}				}				else				{#if defined (HAVE_VPIX)					if (charac == fip->v86_ss.ss_stop)#else					if (charac == CSTOP)#endif					{						fip->flow_flags.s |=							FF_SWO_STOPPED;						ttyp->t_state |= TTSTOP;					}				}				/* we don't put start/stop characters				   into the receiver buffer				*/#if defined (HAVE_VPIX)				if ((charac == fip->v86_ss.ss_start)					|| (charac == fip->v86_ss.ss_stop))#else				if ((charac == CSTART)					|| (charac == CSTOP))#endif					continue;			}valid_char:			if ((charac == 0xff) && (fip->iflag & PARMRK))			{				metta [csize] = 0xff;				csize++;				metta [csize] = 0xff;				csize++;			}			else			{				/* we take a short-cut if only one character				   has to be put into the receiver buffer				*/				if (fip->recv_ring_cnt < RECV_BUFF_SIZE)				{					fip->recv_ring_cnt++;					*fip->recv_ring_put_ptr = charac;					if (++fip->recv_ring_put_ptr						!= &fip->recv_buffer							[RECV_BUFF_SIZE])						continue;					fip->recv_ring_put_ptr =							&fip->recv_buffer [0];				}				continue;			}		}		if (!(csize) || (fip->recv_ring_cnt + csize > RECV_BUFF_SIZE))			continue;	/* nothing to put into recv buffer */		fip->recv_ring_cnt += csize;		/* store translation in ring buffer */		do		{			do			{				*fip->recv_ring_put_ptr = (metta - 1) [csize];				if (++fip->recv_ring_put_ptr					== &fip->recv_buffer [RECV_BUFF_SIZE])					break;			} while (--csize);			if (!csize)				break;			fip->recv_ring_put_ptr = &fip->recv_buffer [0];		} while (--csize);	} while ((line_status = fas_inb (fip, LINE_STATUS_PORT)) & LS_RCV_INT);	return (line_status);}/* Output characters to the transmitter register. */static voidfas_xproc (fip)register struct fas_info	*fip;{	register uint	num_to_output;	REGVAR;	/* proceed only if transmitter is available */	if ((fip->device_flags.i & (DF_XMIT_BUSY | DF_XMIT_BREAK						| DF_XMIT_LOCKED))		|| (fip->flow_flags.i & FF_HWO_STOPPED))		goto sched;	num_to_output = fip->xmit_fifo_size;	/* handle XON/XOFF input flow control requests */	if (fip->flow_flags.i & FF_SW_FC_REQ)	{#if defined (HAVE_VPIX)		fas_first_outb (fip, XMT_DATA_PORT, (fip->flow_flags.i & FF_SWI_STOPPED)					? fip->v86_ss.ss_stop					: fip->v86_ss.ss_start);#else		fas_first_outb (fip, XMT_DATA_PORT, (fip->flow_flags.i & FF_SWI_STOPPED)					? CSTOP					: CSTART);#endif		fip->tty->t_state &= ~(TTXON | TTXOFF);		fip->device_flags.s |= DF_XMIT_BUSY;		fip->flow_flags.s &= ~FF_SW_FC_REQ;		/* 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);		}		num_to_output--;	}	/* bail out if output is suspended by XOFF */	if (fip->flow_flags.i & FF_SWO_STOPPED)

⌨️ 快捷键说明

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