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

📄 bsc_states.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 2 页
字号:
#ifndef lintstatic	char	*sccsid = "@(#)bsc_states.c	4.1		(ULTRIX)	7/2/90";#endif lint/************************************************************************ *									* *			Copyright (c) 1985 by				* *		Digital Equipment Corporation, Maynard, MA		* *			All rights reserved.				* *									* *   This software is furnished under a license and may be used and	* *   copied  only  in accordance with the terms of such license and	* *   with the  inclusion  of  the  above  copyright  notice.   This	* *   software  or  any  other copies thereof may not be provided or	* *   otherwise made available to any other person.  No title to and	* *   ownership of the software is hereby transferred.			* *									* *   This software is  derived  from  software  received  from  the	* *   University    of   California,   Berkeley,   and   from   Bell	* *   Laboratories.  Use, duplication, or disclosure is  subject  to	* *   restrictions  under  license  agreements  with  University  of	* *   California and with AT&T.						* *									* *   The information in this software is subject to change  without	* *   notice  and should not be construed as a commitment by Digital	* *   Equipment Corporation.						* *									* *   Digital assumes no responsibility for the use  or  reliability	* *   of its software on equipment which is not supplied by Digital.	* *									* ************************************************************************//*	bsc_states.c 	U. Sinkewicz	1.0	5/10/85			 * *					Protocol state processing for the* *					2780/3780 Emulator.		 * *									 *//**************************************************************************** * Input to bsc_output: comes from the socket and is an mbuf with data to  *			transmit but no control characters. * Input to bsc_input:	comes from the driver is bisync framed data in an mbuf *			chain. * Output from bsc_output: goes to the driver and is several mbufs of *			   different sizes that contain both data and control  *			   characters. * Output from bsc_input:  goes to the socket and is an mbuf stripped of  *		   	   everything but data.   ****************************************************************************/#include "../h/param.h"#include "../h/systm.h"#include "../h/dir.h"#include "../h/user.h"#include "../h/buf.h"#include "../h/cpudata.h"#include "../h/conf.h"#include "../h/proc.h"#include "../h/mbuf.h"#include "../h/kernel.h"#include "../h/socket.h"#include "../h/socketvar.h"#include "../net/net/if.h"#include "../net/netbsc/bsc.h"#include "../net/net/route.h"#include "../net/netbsc/bsc_var.h"#include "../net/netbsc/bsc_states.h"#include "../net/netbsc/bsc_messages.h"#include "../net/netbsc/bsc_timer.h"#include "../h/errno.h"#include "../h/protosw.h"#include "../h/types.h"#include "../h/ioctl.h"#include "../h/uio.h"unsigned short crctable[16]={0x0000,0xcc01,0xd801,0x1400,0xf001,0x3c00,		       	     0x2800,0xe401,0xa001,0x6c00,0x7800,0xb401,			     0x5000,0x9c01,0x8801,0x4400};int	flag;unsigned char	crc[2];char	xfcs0, xfcs1, rfcs0, rfcs1;char	byte, rcvs, xbcb, rbcb, xseq, ackseq;char	c1, nakctr, count, punch, rseq, actseq; /* nakctr is number of NAKs					         * rcvd for one sent block */short	waiting, exitval, seqst;short	ct0, ct1;int bsc_mbuf_len;		/* The number of data characters you can fit 				 * into m_up_ptr. */struct mbuf *m_up;		/* Mbuf that contains processed data destined				 * for the socket.  Characters from m_dvr 				 * (mbuf from the driver) are copied into 				 * m_up (mbuf going up to the socket).  				 * Control characters and the crc 			   	 * characters are eleminated.  Passed up to 				 * socket.	*/struct mbuf *m_up_ptr;  	/* Pointer to the one mbuf in the m_up chain 				 * that we're currently working with. */struct bsc_data *dat_up; 	/* Pointer to data area of m_up. */int data_loc_up;	 	/* Location in the m_up_ptr buffer where you 				 * are currently writing a character. */struct bsc_data *dat_dvr; 	/* Pointer to data area of m_dvr. */int	data_loc_dvr;	  	/* What byte we're currently reading in the			     	 * data area of m_dvr.		*/struct mbuf *m_dvr;	  	/* Contains raw data from the driver.  			     	 * Comes from bscintr().	*/struct mbuf *m_out;	  	/* Contains data and control characters that 				 * go to the driver.				 */struct 	  bsc_ifaddr	*bsc_ifaddr;bsc_output(bsc )	register struct bscpcb *bsc;{	struct sockaddr_bsc *sin = &bsc->bscp_laddr;	struct sockaddr_bsc *dst;	register struct bsc_ifaddr *bia;	struct ifaddr *ifa;	register struct ifnet *ifp;	extern short state;	int	error;	ifp = (struct ifnet *)bsc_ifpfinder( sin );	if (ifp == 0)		return(EADDRNOTAVAIL);	bia = (struct bsc_ifaddr *)bsc_biafinder( ifp );	if (bia == 0)		return(EADDRNOTAVAIL);	crcloc();	switch(state){	case MODEM:		break;	case REXMT:		 break;	case INIT:		xbcb = 0xa0;		xfcs0 = 0x8f;		xfcs1 = 0xcf;		ackseq = 0x70;		error = xmtctl(ENQ,NULL,ifp);		break;	case SENDBLK:		error = xmtdata(ifp,bsc);		bsc->bscp_state = NULL;  		break;	}	return(error);}bsc_input( m0 , dst)	struct mbuf *m0;	struct sockaddr_bsc *dst;{	register struct bsc_ifaddr *bia;	register struct ifnet *ifp;	struct bscpcb *bsc;	struct socket *so;	extern short state;	int s;	int	error;	struct sockaddr_bsc *sin;	int saveaffinity;	saveaffinity = switch_affinity(boot_cpu_mask);	m_dvr = m0;	rcvs = rec();	switch(state){	case REXMT:		break;	case INIT:			switch( rcvs ){		case R_ACK:			m_free(m0);			s = splimp();			state = SENDBLK;			bsc = bsc_pcblookup(&bsb);		 	so = bsc->bscp_socket;			soisconnected(so);  			splx(s);			bsc->b_rexmt = 0;			break;		default:			m_free(m0);			break;		}		break;	case SENDBLKLAST:		switch(rcvs){		case R_ACK:			/* If last block is received on IBM side, then send 			 * an eot message and wakeup the socket.	*/			m_free(m0);						s = splimp();			bsc = bsc_pcblookup(&bsb);			so = bsc->bscp_socket;			sin = &bsc->bscp_laddr;			ifp = (struct ifnet *)bsc_ifpfinder( sin );				if (ifp == 0){					wakeup((caddr_t)&so->so_timeo); 					sbdrop(&so->so_snd, so->so_snd.sb_cc); 					so->so_error = EADDRNOTAVAIL;					break;				}			splx(s);			ct1 = 0;			nakctr = 0;			seqst = R_ACK;			xbcb = 0x80|xseq;			incmod(xseq,16);			wakeup((caddr_t)&so->so_timeo); 			sbdrop(&so->so_snd, so->so_snd.sb_cc); 			error = xmtctl(EOT,NULL,ifp);			/* SENDACK0 is a transition state so get the			 * ack sequence set up in case we get to bid for the			 * line.					*/			ackseq = X70;   			state = SENDACK0;			break;		case R_RVI:			/* We treat the RVI as an ACK plus line turn around			 * request.  Therefore we process the RVI exactly like 			 * and ack.  We don't need to do anything special for			 * the RVI case.  We don't even need to tell the 			 * uper layers that an RVI character came in			 * because we are on the last block and			 * expect the other side to do a line bid anyway.			 */			m_free(m0);						s = splimp();			bsc = bsc_pcblookup(&bsb);			sin = &bsc->bscp_laddr;		 	so = bsc->bscp_socket;			ifp = (struct ifnet *)bsc_ifpfinder( sin );				if (ifp == 0){					wakeup((caddr_t)&so->so_timeo); 					sbdrop(&so->so_snd, so->so_snd.sb_cc); 					so->so_error = EADDRNOTAVAIL;					break;				}			splx(s);			ct1 = 0;			nakctr = 0;			seqst = R_ACK;			xbcb = 0x80|xseq;			incmod(xseq,16);			wakeup((caddr_t)&so->so_timeo); 			sbdrop(&so->so_snd, so->so_snd.sb_cc); 			error = xmtctl(EOT,NULL,ifp);			ackseq = X70;   			state = SENDACK0;			break;		case R_SEQ:			m_free(m0);			ct1 = 0;			s = splimp();			bsc = bsc_pcblookup(&bsb);			so = bsc->bscp_socket;			sin = &bsc->bscp_laddr;			splx(s);			ifp = (struct ifnet *)bsc_ifpfinder( sin );				if (ifp == 0){					wakeup((caddr_t)&so->so_timeo); 					sbdrop(&so->so_snd, so->so_snd.sb_cc); 					so->so_error = EADDRNOTAVAIL;					break;				}			error = xmtdata(ifp, bsc);			state = SENDBLKLAST;			break;		case R_NAK:		/* May need some trap here that lets you receive only		 * x NAKs for the same block.			   */			m_free(m0);			nakctr++;			seqst = R_NAK;			ct1 = 0;			if (ackseq == X70)				ackseq = 0x61;			else				ackseq = X70;				bsc = bsc_pcblookup(&bsb);			so = bsc->bscp_socket;			sin = &bsc->bscp_laddr;			ifp = (struct ifnet *)bsc_ifpfinder( sin );				if (ifp == 0){					wakeup((caddr_t)&so->so_timeo); 					sbdrop(&so->so_snd, so->so_snd.sb_cc); 					so->so_error = EADDRNOTAVAIL;					break;				}			if (nakctr >= SEND_BLK_RETRY){				bsc->b_rexmt = nakctr + 1;				so->so_error = ECONNABORTED;				wakeup((caddr_t)&so->so_timeo);				sbdrop(&so->so_snd, so->so_snd.sb_cc); 					break;			}			error = xmtdata(ifp, bsc);			state = SENDBLKLAST;			break;		default:			++ct1;			if(ct1 >= 6){				bsc = bsc_pcblookup(&bsb);				so = bsc->bscp_socket;				wakeup((caddr_t)&so->so_timeo); 				sbdrop(&so->so_snd, so->so_snd.sb_cc); 				so->so_error = ENETDOWN;				break;			}else{				m_free(m0);				bsc = bsc_pcblookup(&bsb);				so = bsc->bscp_socket;				sin = &bsc->bscp_laddr;				ifp = (struct ifnet *)bsc_ifpfinder( sin );				if (ifp == 0){					wakeup((caddr_t)&so->so_timeo); 					sbdrop(&so->so_snd, so->so_snd.sb_cc); 					so->so_error = EADDRNOTAVAIL;					break;				}				error = xmtctl(ENQ,NULL,ifp);				state = SENDBLKLAST;			}			break;		}		break;	case SENDBLK:		switch(rcvs){		case R_ACK:			m_free(m0);			bsc = bsc_pcblookup(&bsb);			/* It takes a while for the application layer			 * to generate another block so we need to			 * distinguish this state in order to send TTDs. */			bsc->bscp_state = R_ACK;  			bsc->b_rexmt = 0;	  			bsc->b_timer = 0;	  			s = splimp();			ct1 = 0;			nakctr = 0;			seqst = R_ACK;			xbcb = 0x80|xseq;			incmod(xseq,16);		 	so = bsc->bscp_socket;			wakeup((caddr_t)&so->so_timeo);			splx(s);			sbdrop(&so->so_snd, so->so_snd.sb_cc); 			break;		case R_RVI:		/*		 * Note the wakeup situation here.  We get an RVI then send		 * an EOT. Then we wakeup the send which falls to the		 * receive outofband routine which sleeps.  In the meantime		 * we put the RVI in  the outofband location in the socket		 * queue.  When data eventually comes in, we wakeup the socket		 * The socket sees the RVI character and immediately goes to		 * read what is in the receive queue.		 */			m_free(m0);			ct1 = 0;			s = splimp();			bsc = bsc_pcblookup(&bsb);			sin = &bsc->bscp_laddr;			splx(s);		 	so = bsc->bscp_socket;			ifp = (struct ifnet *)bsc_ifpfinder( sin );				if (ifp == 0){					wakeup((caddr_t)&so->so_timeo); 					sbdrop(&so->so_snd, so->so_snd.sb_cc); 					so->so_error = EADDRNOTAVAIL;					break;				}			wakeup((caddr_t)&so->so_timeo);			sbdrop(&so->so_snd, so->so_snd.sb_cc); 			error = xmtctl(EOT,NULL,ifp);			bsc_pulloutofband(bsc);			ackseq = X70;  			state = SENDACK;			break;		case R_NAK:			m_free(m0);			nakctr++;			seqst = R_NAK;			ct1 = 0;			/* if (ackseq == X70)			 *	ackseq = 0x61;			 * else			 *	ackseq = X70;				 */			bsc = bsc_pcblookup(&bsb);			sin = &bsc->bscp_laddr;			so = bsc->bscp_socket;			ifp = (struct ifnet *)bsc_ifpfinder( sin );				if (ifp == 0){					wakeup((caddr_t)&so->so_timeo); 					sbdrop(&so->so_snd, so->so_snd.sb_cc); 					so->so_error = EADDRNOTAVAIL;					break;				}			/* You may want to send an EOT message here */			if (nakctr >= SEND_BLK_RETRY){				bsc->b_rexmt = nakctr + 1;				so->so_error = ECONNABORTED;				wakeup((caddr_t)&so->so_timeo);				sbdrop(&so->so_snd, so->so_snd.sb_cc); 					break;			}			/* We are sending a TTD from the timers.  Just let			 * the timers continue to do this.		*/			if (bsc->bscp_state == R_ACK)  				break;			error = xmtdata(ifp, bsc);			state = SENDBLK;			break;		case R_SEQ:			m_free(m0);			ct1 = 0;			s = splimp();			bsc = bsc_pcblookup(&bsb);			sin = &bsc->bscp_laddr;			so = bsc->bscp_socket;			splx(s);			ifp = (struct ifnet *)bsc_ifpfinder( sin );				if (ifp == 0){					wakeup((caddr_t)&so->so_timeo); 					sbdrop(&so->so_snd, so->so_snd.sb_cc); 					so->so_error = EADDRNOTAVAIL;					break;				}			error = xmtdata(ifp, bsc);			state = SENDBLK;			break;		default:			++ct1;			if(ct1 >= 6){				bsc = bsc_pcblookup(&bsb);				so = bsc->bscp_socket;				wakeup((caddr_t)&so->so_timeo); 				sbdrop(&so->so_snd, so->so_snd.sb_cc); 				so->so_error = ENETDOWN;				break;			}else{				m_free(m0);				bsc = bsc_pcblookup(&bsb);				sin = &bsc->bscp_laddr;				so = bsc->bscp_socket;				ifp = (struct ifnet *)bsc_ifpfinder( sin );				if (ifp == 0){					wakeup((caddr_t)&so->so_timeo); 					sbdrop(&so->so_snd, so->so_snd.sb_cc); 					so->so_error = EADDRNOTAVAIL;					break;				}				error = xmtctl(ENQ,NULL,ifp);				state = SENDBLK;			}			break;		}		break;	case SENDACK0:		switch(rcvs){		case ENQ:			m_free(m0);						s = splimp();			bsc = bsc_pcblookup(&bsb);			so = bsc->bscp_socket;			bsc_pulloutofband(bsc);			splx(s);			ackseq = X70;			error = xmtack(bsc); 			ct1 = 0;			seqst = R_ACK;			xbcb = 0x80|xseq;			incmod(xseq,16);			state = SENDACK;			break;		case R_ACK:				/* Let the timers keep the line alive.  If			 * the timers kick in to do a line bid that			 * means that the other side doesn't want to			 * to send a file so we go to SENDBLK state.			 */			m_free(m0);			s = splimp();			ct1 = 0;			seqst = R_ACK;			xbcb = 0x80|xseq;			incmod(xseq,16);			bsc = bsc_pcblookup(&bsb);		 	so = bsc->bscp_socket;			wakeup((caddr_t)&so->so_timeo);			splx(s);			break;		default:			++ct1;			if(ct1 >= 6){   				m_free(m0);  				s = splimp();				bsc = bsc_pcblookup(&bsb);				splx(s);				so = bsc->bscp_socket;				so->so_error = ENETDOWN; 				bsc->b_timer = 0;					wakeup((caddr_t)&so->so_timeo);					exitval = ERRORS;			}		break;		}		break;	case SENDACK:		switch(rcvs){		case ENQ:			m_free(m0);						s = splimp();			bsc = bsc_pcblookup(&bsb);			splx(s);			bsc->b_rexmt++;			so = bsc->bscp_socket;			error = xmtack(bsc); 			if (error && (bsc->b_rexmt >= SEND_BLK_RETRY)){				bsc->b_rexmt = 0;				so->so_error = ECONNABORTED;				wakeup((caddr_t)&so->so_timeo);					break;				}			ct1 = 0;			seqst = R_ACK;			xbcb = 0x80|xseq;			incmod(xseq,16);			state = SENDACK;			break;		case R_OKBLK:			m_freem(m0); 			s = splimp();			bsc = bsc_pcblookup(&bsb);			so = bsc->bscp_socket;			bsc->b_rexmt = 0;			splx(s);			if (ackseq == X70)				ackseq = 0x61;			else				ackseq = X70;			/* An error in sending here means a message didn't get			 * out.  The other side must send ENQ in response so			 * let case ENQ handle the retransmit.	 */			error = xmtack(bsc); 			sbappend(&so->so_rcv, m_up);			wakeup((caddr_t)&so->so_timeo);				break;		case R_ERBLK:			m_freem(m0);			m_freem(m_up);   			ct1 = 0;			bsc = bsc_pcblookup(&bsb);			bsc->b_rexmt++;			so = bsc->bscp_socket;			if (bsc->b_rexmt >= SEND_BLK_RETRY){				so->so_error = ECONNABORTED;				bsc->b_rexmt = 0;				wakeup((caddr_t)&so->so_timeo);				break;			}			sin = &bsc->bscp_laddr;			ifp = (struct ifnet *)bsc_ifpfinder( sin );				if (ifp == 0){					so->so_error = EADDRNOTAVAIL;					bsc->b_rexmt = 0;					wakeup((caddr_t)&so->so_timeo);					break;				}			error = xmtctl(NAK,NULL,ifp);			if (error)				bsc->b_rexmt--;			state = SENDACK;			break;		case R_NAK:			m_freem(m0);						ct1 = 0;			seqst = R_NAK;			bsc = bsc_pcblookup(&bsb);			so = bsc->bscp_socket;			sin = &bsc->bscp_laddr;			ifp = (struct ifnet *)bsc_ifpfinder( sin );				if (ifp == 0){					so->so_error = EADDRNOTAVAIL;					bsc->b_rexmt = 0;					wakeup((caddr_t)&so->so_timeo);					break;				}			error = xmtctl(DLE,X70,ifp);			state = SENDACK;			break;		case EOT:			m_free(m0);						s = splimp();			bsc = bsc_pcblookup(&bsb);			so = bsc->bscp_socket;			bsc_pulloutofband(bsc);			splx(s);			ct1 = 0;			seqst = R_ACK;			xbcb = 0x80|xseq;			incmod(xseq,16);			state = SENDACK0;			/* SENDACK0 is a transition state so get the			 * ack sequence set up in case we get to bid for the			 * line.					*/			ackseq = X70;   			wakeup((caddr_t)&so->so_timeo);			break;		default:			++ct1;			m_freem(m0); 			if(ct1 >= 6){				bsc = bsc_pcblookup(&bsb);				so = bsc->bscp_socket;				so->so_error = ENETDOWN;				bsc->b_rexmt = 0;				wakeup((caddr_t)&so->so_timeo);				break;			}else{				bsc = bsc_pcblookup(&bsb);				so = bsc->bscp_socket;				sin = &bsc->bscp_laddr;				ifp = (struct ifnet *)bsc_ifpfinder( sin );					if (ifp == 0){						so->so_error = EADDRNOTAVAIL;						bsc->b_rexmt = 0;						wakeup((caddr_t)&so->so_timeo);						break;					}				error = xmtctl(NAK,NULL,ifp);				state = SENDACK;			}			break;		}		break;	}}/* Xmtdata prepares data for transmission to the protocol.  When we get * the data at this level, there are a few flags in the data indicating * transparent/nontransparent and eof/eobuffer.  The 0th location in the * first mbuf of data indicates transparent communication if its value is * 1.  We note the value here and then delete it from the buffer so it * won't be transmitted as data.  The last location in the last mbuf we * get tells us if this is the last buffer in the file or not.  Again, * we see what the value is, take the proper action, and then delete so it  * won't be transmitted as data. */xmtdata( ifp, bsc)	struct ifnet *ifp;	struct bscpcb *bsc;{	struct socket *so;	struct sockaddr_bsc *dst;	int i = 0;	int j = 0;	char c;	struct mbuf *m, *mp, *m_head, *m_new;	int len, off, error;	int d_flag = 0;	struct bsc_data *bm, *bmtmp;	int saveaffinity;

⌨️ 快捷键说明

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