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

📄 fas.c

📁 一个通讯程序源码
💻 C
📖 第 1 页 / 共 5 页
字号:
			fip->characters_transmitted = 0;			fip->modem_status_events = 0;			fip->overrun_errors = 0;			fip->framing_errors = 0;			fip->parity_errors = 0;			fip->rings_detected = 0;			fip->breaks_detected = 0;			fip->xmtr_hw_flow_count = 0;			fip->xmtr_sw_flow_count = 0;			fip->rcvr_hw_flow_count = 0;			fip->rcvr_sw_flow_count = 0;			(void)splx(old_level);			break;#endif /* FASI */#if defined (HAVE_VPIX)		case AIOCINTTYPE:	/* set pseudorupt type */			switch (arg3.iarg)			{				case V86VI_KBD:				case V86VI_SERIAL0:				case V86VI_SERIAL1:					intr_disable ();					fip->v86_intmask = arg3.iarg;					intr_restore ();					break;				default:					intr_disable ();					fip->v86_intmask = V86VI_SERIAL0;					intr_restore ();					break;			}			break;		case AIOCDOSMODE:	/* enable dos mode */			if (!(fip->iflag & DOSMODE))			{				old_level = SPLINT ();				fip->v86_proc = u.u_procp->p_v86;				if (!(fip->v86_intmask))					fip->v86_intmask = V86VI_SERIAL0;				ttyp->t_iflag |= DOSMODE;				if (fip->v86_intmask != V86VI_KBD)					ttyp->t_cflag |= CLOCAL;				fas_param (fip, SOFT_INIT);				(void) splx (old_level);			}			u.u_r.r_reg.r_val1 = 0;			break;		case AIOCNONDOSMODE:	/* disable dos mode */			if (fip->iflag & DOSMODE)			{				old_level = SPLINT ();				fip->v86_proc = (v86_t *) NULL;				fip->v86_intmask = 0;				ttyp->t_iflag &= ~DOSMODE;				if (fip->flow_flags.i & FF_RXFER_STOPPED)				{					fip->flow_flags.s &= ~FF_RXFER_STOPPED;					/* schedule character transfer					   to UNIX buffer					*/					if (fip->recv_ring_cnt)						event_sched (fip, EF_DO_RXFER);				}				fip->lcr &= ~LC_SET_BREAK_LEVEL;				fas_param (fip, HARD_INIT);				(void) splx (old_level);			}			u.u_r.r_reg.r_val1 = 0;			break;		case AIOCSERIALOUT:	/* setup port registers for dos */			if ((fip->iflag & DOSMODE) && fip->v86_proc)			{				/* wait until output is done */				old_level = SPLINT ();				while (ttyp->t_outq.c_cc					|| (ttyp->t_state & (BUSY | TIMEOUT)))				{					ttyp->t_state |= TTIOW;					(void) sleep ((caddr_t) &ttyp->t_oflag,									TTOPRI);				}				/* block transmitter and wait until it is				   empty				*/				fip->device_flags.s |= DF_XMIT_LOCKED;				while (fip->device_flags.i & (DF_XMIT_BUSY							| DF_XMIT_BREAK							| DF_GUARD_TIMEOUT))					(void) sleep ((caddr_t) &fip->								device_flags.i,							PZERO - 1);				(void) splx (old_level);				/* get port write command */				v86_cmd = fubyte (arg3.cparg);				/* set divisor lsb requested */				if (v86_cmd & SIO_MASK(SO_DIVLLSB))				{					v86_data = fubyte (arg3.cparg								+ SO_DIVLLSB);					intr_disable ();					fas_first_outb (fip, LINE_CTL_PORT, fip->lcr							| LC_ENABLE_DIVISOR);					fas_outb (fip, DIVISOR_LSB_PORT, v86_data);					fas_outb (fip, LINE_CTL_PORT, fip->lcr							& ~LC_ENABLE_DIVISOR);					intr_restore ();				}				/* set divisor msb requested */				if (v86_cmd & SIO_MASK(SO_DIVLMSB))				{					v86_data = fubyte (arg3.cparg								+ SO_DIVLMSB);					intr_disable ();					fas_first_outb (fip, LINE_CTL_PORT, fip->lcr							| LC_ENABLE_DIVISOR);					fas_outb (fip, DIVISOR_MSB_PORT, v86_data);					fas_outb (fip, LINE_CTL_PORT, fip->lcr							& ~LC_ENABLE_DIVISOR);					intr_restore ();				}				/* set lcr requested */				if (v86_cmd & SIO_MASK(SO_LCR))				{					v86_data = fubyte (arg3.cparg + SO_LCR);					intr_disable ();					fip->lcr = v86_data							& ~LC_ENABLE_DIVISOR;					fas_first_outb (fip, LINE_CTL_PORT, fip->lcr);					intr_restore ();				}				/* set mcr requested */				if (v86_cmd & SIO_MASK(SO_MCR))				{					v86_data = fubyte (arg3.cparg + SO_MCR);					old_level = SPLINT ();					/* virtual dtr processing */					if (v86_data & MC_SET_DTR)					{						fip->device_flags.s							|= DF_MODEM_ENABLED;						fip->mcr |= (fip->o_state								& OS_WAIT_OPEN)							? fip->modem.m.ei							: fip->modem.m.eo;					}					else					{						fip->device_flags.s							&= ~DF_MODEM_ENABLED;						fip->mcr &= (fip->o_state								& OS_WAIT_OPEN)							? ~fip->modem.m.ei							: ~fip->modem.m.eo;					}					/* virtual rts processing */					if (fip->flow_flags.i							& FF_HWI_HANDSHAKE)					{					  if (v86_data & MC_SET_RTS)					  {						if (fip->flow_flags.i							& FF_RXFER_STOPPED)						{						  fip->flow_flags.s							&= ~FF_RXFER_STOPPED;						  /* schedule character transfer						     to UNIX buffer						  */						  if (fip->recv_ring_cnt)							event_sched (fip,								EF_DO_RXFER);						}					  }					  else						fip->flow_flags.s							|= FF_RXFER_STOPPED;					}					else if (!(fip->flow_flags.i							& FF_HDX_HANDSHAKE))					{						if (v86_data & MC_SET_RTS)						{							fip->flow_flags.s							  |= FF_HDX_STARTED;							fip->mcr							  |= fip->flow.m.hc;						}						else						{							fip->flow_flags.s							  &= ~FF_HDX_STARTED;							fip->mcr							  &= ~fip->flow.m.hc;						}					}					fas_first_outb (fip, MDM_CTL_PORT, fip->mcr);					(void) splx (old_level);				}				old_level = SPLINT ();				/* enable transmitter and restart output */				fip->device_flags.s &= ~DF_XMIT_LOCKED;				fas_xproc (fip);				(void) splx (old_level);			}			break;		case AIOCSERIALIN:	/* read port registers for dos */			if ((fip->iflag & DOSMODE) && fip->v86_proc)			{				v86_cmd = fubyte (arg3.cparg);				if (v86_cmd & SIO_MASK(SI_MSR))				{					(void) subyte (arg3.cparg + SI_MSR,							((fip->flow_flags.i							  & FF_HWO_HANDSHAKE)							? fip->msr							  | fip->flow.m.oc							  | fip->flow.m.oe							: fip->msr)							& MS_ANY_PRESENT);				}			}			break;		case AIOCSETSS:	/* set start/stop characters */			intr_disable ();			*((short *) (&fip->v86_ss)) = arg3.iarg;			intr_restore ();			break;		case AIOCINFO:	/* show what type of device we are */			u.u_r.r_reg.r_val1 = ('a' << 8) | (uint) ((unchar) dev);			break;#endif		default:	/* default ioctl processing */			/* if it is a TCSETA* command, call fas_param () */			if (ttiocom (ttyp, cmd, arg3, arg4))			{				old_level = SPLINT ();				fas_param (fip, SOFT_INIT);				(void) splx (old_level);			}			break;	}	return (0);}/* pass fas commands to the fas multi-function procedure */static intfas_proc (ttyp, arg2)struct tty	*ttyp;int	arg2;{	register uint	physical_unit;	int	old_level;	physical_unit = ttyp - &fas_tty [0];	if (physical_unit >= fas_physical_units)		physical_unit -= fas_physical_units;	old_level = SPLINT ();	fas_cmd (fas_info_ptr [physical_unit], ttyp, arg2);	(void) splx (old_level);	return (0);}/* set up a port according to the given termio structure */static voidfas_param (fip, init_type)register struct	fas_info	*fip;int	init_type;{	register uint	cflag;	uint	divisor;	int	xmit_ring_size;	REGVAR;	cflag = fip->tty->t_cflag;#if defined (HAVE_VPIX)	/* we don't set port registers if we are in dos mode */	if (fip->tty->t_iflag & DOSMODE)		goto setflags2;#endif	/* if soft init mode: don't set port registers if cflag didn't change */	if ((init_type == SOFT_INIT) && !((cflag ^ fip->cflag)						& (CBAUD | CSIZE | CSTOPB							| PARENB | PARODD)))		goto setflags;	/* lock transmitter and wait until it is empty */	fip->device_flags.s |= DF_XMIT_LOCKED;	while (fip->device_flags.i & (DF_XMIT_BUSY | DF_XMIT_BREAK							| DF_GUARD_TIMEOUT))		(void) sleep ((caddr_t) &fip->device_flags.i, PZERO - 1);	/* hangup line if it is baud rate 0, else enable line */	if ((cflag & CBAUD) == B0)	{		fip->mcr &= (fip->o_state & OS_WAIT_OPEN)				? ~fip->modem.m.ei				: ~fip->modem.m.eo;		fas_first_outb (fip, MDM_CTL_PORT, fip->mcr);		fip->device_flags.s &= ~DF_MODEM_ENABLED;	}	else	{		if (!(fip->device_flags.i & DF_MODEM_ENABLED))		{			fip->mcr |= (fip->o_state & OS_WAIT_OPEN)					? fip->modem.m.ei					: fip->modem.m.eo;			fas_first_outb (fip, MDM_CTL_PORT, fip->mcr);			fip->device_flags.s |= DF_MODEM_ENABLED;		}	}	/* don't change break flag */	fip->lcr &= LC_SET_BREAK_LEVEL;	/* set character size */	switch (cflag & CSIZE)	{	case CS5:		fip->lcr |= LC_WORDLEN_5;		break;	case CS6:		fip->lcr |= LC_WORDLEN_6;		break;	case CS7:		fip->lcr |= LC_WORDLEN_7;		break;	default:		fip->lcr |= LC_WORDLEN_8;		break;	}	/* set # of stop bits */	if (cflag & CSTOPB)		fip->lcr |= LC_STOPBITS_LONG;	/* set parity */	if (cflag & PARENB)	{		fip->lcr |= LC_ENABLE_PARITY;		if (!(cflag & PARODD))			fip->lcr |= LC_EVEN_PARITY;	}	/* set divisor registers only if baud rate is valid */	if ((cflag & CBAUD) != B0)	{		/* get counter divisor for selected baud rate */		divisor = fas_speeds [cflag & CBAUD];		/* set LCR and baud rate */		fas_first_outb (fip, LINE_CTL_PORT, fip->lcr							| LC_ENABLE_DIVISOR);		fas_outb (fip, DIVISOR_LSB_PORT, divisor);		fas_outb (fip, DIVISOR_MSB_PORT, divisor >> 8);	}	fas_first_outb (fip, LINE_CTL_PORT, fip->lcr);setflags:	/* check dynamic xmit ring buffer size against boundaries,	   modify it if necessary and update the fas_info structure	*/	if ((cflag & CBAUD) != B0)	{		xmit_ring_size = fas_xbuf_size [cflag & CBAUD]					- tthiwat [cflag & CBAUD];		if (xmit_ring_size < MAX_OUTPUT_FIFO_SIZE * 2)		{setflags2:			xmit_ring_size = MAX_OUTPUT_FIFO_SIZE * 2;		}		if (xmit_ring_size > XMIT_BUFF_SIZE)			xmit_ring_size = XMIT_BUFF_SIZE;		fip->xmit_ring_size = xmit_ring_size;	}	/* setup character time for B0 mode */	fas_ctimes [B0] = fas_ctimes [cflag & CBAUD];	/* disable modem control signals if required by open mode */	if (fip->o_state & OS_CLOCAL)		cflag |= CLOCAL;	/* Select hardware handshake depending on the minor device	   number and the CTSFLOW and RTSFLOW flags (if they are	   available).	*/	fip->flow_flags.s &= ~(FF_HWO_HANDSHAKE				| FF_HWI_HANDSHAKE				| FF_HDX_HANDSHAKE);	if (fip->o_state & (OS_HWO_HANDSHAKE | OS_HWI_HANDSHAKE					| OS_HDX_HANDSHAKE))	{		if (fip->o_state & OS_HWO_HANDSHAKE)			fip->flow_flags.s |= FF_HWO_HANDSHAKE;		if (fip->o_state & OS_HWI_HANDSHAKE)			fip->flow_flags.s |= FF_HWI_HANDSHAKE;		if (fip->o_state & OS_HDX_HANDSHAKE)			fip->flow_flags.s |= FF_HDX_HANDSHAKE;	}	else	{#if defined (CTSFLOW)	/* SYSV 3.2 Xenix compatibility */		if ((cflag & (CTSFLOW | CLOCAL)) == CTSFLOW)			fip->flow_flags.s |= FF_HWO_HANDSHAKE;#endif#if defined (RTSFLOW)	/* SYSV 3.2 Xenix compatibility */		if ((cflag & (RTSFLOW | CLOCAL)) == RTSFLOW)			fip->flow_flags.s |= FF_HDX_HANDSHAKE;#endif	}	/* Fake the carrier detect state flag if CLOCAL mode or if	   requested by open mode.	*/	if (!(~fip->msr & fip->modem.m.ca)		|| (fip->o_state & OS_FAKE_CARR_ON)		|| (cflag & CLOCAL))		fip->tty->t_state |= CARR_ON;	else		fip->tty->t_state &= ~CARR_ON;#if defined (XCLUDE)	/* SYSV 3.2 Xenix compatibility */	/* Permit exclusive use of this device. */	if (cflag & XCLUDE)		fip->o_state |= OS_EXCLUSIVE_OPEN_2;	else		fip->o_state &= ~OS_EXCLUSIVE_OPEN_2;#endif	fip->cflag = cflag;	fip->iflag = fip->tty->t_iflag;	/* enable transmitter */	fip->device_flags.s &= ~DF_XMIT_LOCKED;	/* setup handshake flags */	fas_hdx_check (fip);	fas_ihlw_check (fip);	fas_fproc (fip, fip->new_msr);	/* restart output */	fas_xproc (fip);}/* Main fas interrupt handler. Actual character processing is splitted   into sub-functions.*/intfasintr (vect)int	vect;{	register struct fas_info	*fip;	register uint	status;	struct fas_info	*old_fip;	int	done, drop_mode;	uint	port, old_recv_count;	REGVAR;#if defined(FASI)	fasiintr_entries++;#endif /* FASI */	drop_mode = FALSE;	/* The 8259 interrupt controller is set up for edge trigger.	   Therefor, we must loop until we make a complete pass without	   getting any UARTs that are interrupting.	*/	do	{		done = TRUE;		fip = fas_first_int_user [vect];		/* loop through all users of this interrupt vector */		for (;; fip = fip->next_int_user)		{			if (!fip)				break;	/* all users done */			/* process only ports that we expect ints from			   and that actually need to be serviced			*/fastloop:			if (fas_first_inb (fip, INT_ID_PORT)					& II_NO_INTS_PENDING)			{				/* restore the normal receiver trigger level */				if (fip->device_flags.i & DF_NS16550A_DROP_MODE)				{					fip->device_flags.s &=							~DF_NS16550A_DROP_MODE;					fas_outb (fip, NS_FIFO_CTL_PORT,							NS_FIFO_SETUP_CMD);				}				/* speed beats beauty */				fip = fip->next_int_user;				if (fip)					goto fastloop;				break;			}			/* restore the normal receiver trigger level */			if (fip->device_flags.i & DF_NS16550A_DROP_MODE)			{				fip->device_flags.s &= ~DF_NS16550A_DROP_MODE;				fas_outb (fip, NS_FIFO_CTL_PORT,							NS_FIFO_SETUP_CMD);			}

⌨️ 快捷键说明

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