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

📄 pk0.c

📁 unix v7是最后一个广泛发布的研究型UNIX版本
💻 C
字号:
#define	KERNEL	1#include "../h/pk.p"/* * packet driver */char next[8]	={ 1,2,3,4,5,6,7,0};	/* packet sequence numbers */char mask[8]	={ 1,2,4,010,020,040,0100,0200 };struct pack *pklines[NPLINES];/* * receive control messages */pkcntl(cntl, pk)register cntl;register struct pack *pk;{register val;register m;	val = cntl & MOD8;	if ( NOTCNTL(cntl) ) {		pkbadframe(pk);		return;	}	cntl >>= 3;	pk->p_state &= ~BADFRAME;	m = pk->p_msg;	switch(cntl) {	case INITB:		val++;		pk->p_xsize = pksizes[val];		pk->p_lpsize = val;		pk->p_bits = DTOM(pk->p_xsize);		if (pk->p_state & LIVE) {			pk->p_msg |= M_INITC;			break;		}		pk->p_state |= INITb;		if ((pk->p_state & INITa)==0) {			break;		}		pk->p_rmsg &= ~M_INITA;		pk->p_msg |= M_INITC;		break;	case INITC:		if ((pk->p_state&INITab)==INITab) {			pk->p_state = LIVE;			WAKEUP(&pk->p_state);			pk->p_rmsg &= ~(M_INITA|M_INITB);		} else			if ((pk->p_state&LIVE)==0)				pk->p_msg |= M_INITB;		if (val)			pk->p_swindow = val;		break;	case INITA:		if (val==0 && pk->p_state&LIVE) {			printf("alloc change\n");			break;		}		if (val) {			pk->p_state |= INITa;			pk->p_msg |= M_INITB;			pk->p_rmsg |= M_INITB;			pk->p_swindow = val;		}		break;	case RJ:		pk->p_state |= RXMIT;		pk->p_msg |= M_RR;	case RR:		pk->p_rpr = val;		if (pksack(pk)==0) {			WAKEUP(&pk->p_ps);		}		break;	case CLOSE:		pk->p_state = DOWN+RCLOSE;		pk->p_rmsg = 0;		WAKEUP(&pk->p_pr);		WAKEUP(&pk->p_ps);		WAKEUP(&pk->p_state);		return;	}	if (pk->p_msg==0)		pk->p_msg |= pk->p_rmsg;	if (m==0 && pk->p_msg)		pkoutput(pk);}/* * Send RJ message on first framing error. * Cleared by receiving a good frame  * (pkcntl or pkdata). */pkbadframe(pk)register struct pack *pk;{	WAKEUP(&pk->p_pr);	if (pk->p_state & BADFRAME)		return;	pk->p_state |= BADFRAME;	pk->p_timer = 2;}/* * Look at sequence numbers (mostly). */pkaccept(pk)register struct pack *pk;{register x, seq;char m, cntl, *p, imask, **bp;int bad, accept, skip, s, t, cc;unsigned short sum;	bad = accept = skip = 0;	/*	 * wait for input	 */	LOCK;	x = next[pk->p_pr];	if((imask=pk->p_imap)==0 && pk->p_rcount==0) {		UNLOCK;		goto out;	}	pk->p_imap = 0;	UNLOCK;	/*	 * determine input window in m.	 */	t = (~(-1<<pk->p_rwindow)) <<x;	m = t;	m |= t>>8;	/*	 * mark newly accepted input buffers	 */	for(x=0; x<8; x++) {		if ((imask & mask[x]) == 0)			continue;		if (((cntl=pk->p_is[x])&0200)==0) {			bad++;free:			bp = (char **)pk->p_ib[x];			LOCK;			*bp = (char *)pk->p_ipool;			pk->p_ipool = bp;			pk->p_is[x] = 0;			UNLOCK;			continue;		}		pk->p_is[x] = ~(B_COPY+B_MARK);		sum = (unsigned)chksum(pk->p_ib[x], pk->p_rsize) ^ (unsigned)cntl;		sum += pk->p_isum[x];		if (sum == CHECK) {			seq = (cntl>>3) & MOD8;			if (m & mask[seq]) {				if (pk->p_is[seq] & (B_COPY | B_MARK)) {				dup:					skip++;					goto free;				}				if (x != seq) {					LOCK;					p = pk->p_ib[x];					pk->p_ib[x] = pk->p_ib[seq];					pk->p_is[x] = pk->p_is[seq];					pk->p_ib[seq] = p;					UNLOCK;				}				pk->p_is[seq] = B_MARK;				accept++;				cc = 0;				if (cntl&B_SHORT) {					pk->p_is[seq] = B_MARK+B_SHORT;					p = pk->p_ib[seq];					cc = (unsigned)*p++;					if (cc & 0200) {						cc &= 0177;						cc |= *p << 7;					}				}				pk->p_isum[seq] = pk->p_rsize - cc;			} else {				goto dup;			}		} else {			bad++;			goto free;		}	}	/*	 * scan window again turning marked buffers into	 * COPY buffers and looking for missing sequence	 * numbers.	 */	accept = 0;	for(x=next[pk->p_pr],t= -1; m & mask[x]; x = next[x]) {		if (pk->p_is[x] & B_MARK)			pk->p_is[x] |= B_COPY;		if (pk->p_is[x] & B_COPY) {			if (t >= 0) {				bp = (char **)pk->p_ib[x];				LOCK;				*bp = (char *)pk->p_ipool;				pk->p_ipool = bp;				pk->p_is[x] = 0;				UNLOCK;				skip++;			} else 				accept++;		} else {			if (t<0)				t = x;		}	}	if (bad) {		pk->p_msg |= M_RJ;	} else 	if (skip) {		pk->p_msg |= M_RR;	}	pk->p_rcount = accept;out:	if (pk->p_msg)		pkoutput(pk);	return(accept);}pkread(S)SDEF;{register struct pack *pk;register x,s;int is,cc,xfr,count;char *cp, **bp;	pk = PADDR;	xfr = 0;	count = -1;	while (pkaccept(pk) == 0) {		PKGETPKT(pk);		if (pk->p_state&DOWN) {			SETERROR;			goto out;		}		if (SLEEPNO) {			count++;			goto out;		}		SLEEP(&pk->p_pr, PKIPRI);	}	count = 0;	while (UCOUNT) {		x = next[pk->p_pr];		is = pk->p_is[x];		if (is & B_COPY) {			cc = MIN(pk->p_isum[x], UCOUNT);			if (cc==0 && xfr) {				break;			}			if (is & B_RESID)				cp = pk->p_rptr;			else {				cp = pk->p_ib[x];				if (is & B_SHORT) {					if (*cp++ & 0200)						*cp++;				}			}			IOMOVE(cp,cc,B_READ);			count += cc;			xfr++;			pk->p_isum[x] -= cc;			if (pk->p_isum[x] == 0) {				LOCK;				pk->p_pr = x;				bp = (char **)pk->p_ib[x];				*bp = (char *)pk->p_ipool;				pk->p_ipool = bp;				pk->p_is[x] = 0;				pk->p_rcount--;				UNLOCK;				pk->p_msg |= M_RR;			} else {				pk->p_rptr = cp+cc;				pk->p_is[x] |= B_RESID;			}			if (cc==0)				break;		} else			break;	}	pkoutput(pk);	if (SLEEPNO)		count = pk->p_rcount;out:	return(count);}pkwrite(S)SDEF;{register struct pack *pk;register x;int partial;caddr_t cp;int cc, s, fc, count;int pktimeout();	pk = PADDR;	if ((pk->p_state&LIVE)==0) {	down:		SIGNAL;		SETERROR;		return(-1);	}	count = UCOUNT;	do {		LOCK;		while (pk->p_xcount>=pk->p_swindow)  {			pkoutput(pk);			PKGETPKT(pk);			SLEEP(&pk->p_ps,PKOPRI);			if (pk->p_state&DOWN)				goto down;		}		x = next[pk->p_pscopy];		while (pk->p_os[x]!=B_NULL)  {			goto down;		}		pk->p_os[x] = B_MARK;		pk->p_pscopy = x;		pk->p_xcount++;		UNLOCK;		cp = pk->p_ob[x] = (char *)GETEPACK;		partial = 0;		if ((int)UCOUNT < pk->p_xsize) {			cc = UCOUNT;			fc = pk->p_xsize - cc;			*cp = fc&0177;			if (fc > 127) {				*cp++ |= 0200;				*cp++ = fc>>7;			} else				cp++;			partial = B_SHORT;		} else			cc = pk->p_xsize;		IOMOVE(cp,cc,B_WRITE);		pk->p_osum[x] = chksum(pk->p_ob[x], pk->p_xsize);		pk->p_os[x] = B_READY+partial;		pkoutput(pk);	} while (UCOUNT);	return(count-UCOUNT);}pksack(pk)register struct pack *pk;{register x, i;int s;	i = 0;	LOCK;	for(x=pk->p_ps; x!=pk->p_rpr; ) {		x = next[x];		if (pk->p_os[x]&B_SENT) {			i++;			FREEPACK(pk->p_ob[x], pk->p_bits);			pk->p_os[x] = B_NULL;			pk->p_state &= ~WAITO;			pk->p_xcount--;			pk->p_ps = x;			WAKEUP(&pk->p_ps);		}	}	UNLOCK;	return(i);}pkoutput(pk)register struct pack *pk;{register x;int s;char bstate;int i;SDEF;extern pkzot;	ISYSTEM;	LOCK;	if (OBUSY) {		UNLOCK;		return;	}	/*	 * find seq number and buffer state	 * of next output packet	 */	if (pk->p_state&RXMIT)  {		pk->p_nxtps = next[pk->p_rpr];		pk->p_state &= ~RXMIT;	}	x = pk->p_nxtps;	bstate = pk->p_os[x];	/*	 * Send control packet if indicated	 */	if (pk->p_msg) {		if (pk->p_msg & ~M_RR || !(bstate&B_READY) ) {			x = pk->p_msg;			for(i=0; i<8; i++) 				if (x&1)					break; else				x >>= 1;			x = i;			x <<= 3;			switch(i) {			case CLOSE:				break;			case RJ:			case RR:				x += pk->p_pr;				break;			case SRJ:				break;			case INITB:				x += pksize(pk->p_rsize);				break;			case INITC:				x += pk->p_rwindow;				break;			case INITA:				x += pk->p_rwindow;				break;			}			pk->p_msg &= ~mask[i];			pkxstart(pk, x, -1);			goto out;		}	}	/*	 * Don't send data packets if line is marked dead.	 */	if (pk->p_state&DOWN || (pk->p_state&LIVE)==0) {		WAKEUP(&pk->p_ps);		goto out;	}	/*	 * Start transmission (or retransmission) of data packets.	 */	if (bstate & (B_READY|B_SENT)) {		char seq;		bstate |= B_SENT;		seq = x;		pk->p_nxtps = next[x];		x = 0200+pk->p_pr+(seq<<3);		if (bstate & B_SHORT)			x |= 0100;		pkxstart(pk, x, seq);		if (pk->p_os[seq])			pk->p_os[seq] = bstate;		pk->p_nout++;		goto out;	}	/*	 * enable timeout if there's nothing to send	 * and transmission buffers are languishing	 */	if (pk->p_xcount) {		pk->p_timer = 10+pkzot;		pk->p_state |= WAITO;	} else		pk->p_state &= ~WAITO;	WAKEUP(&pk->p_ps);out:	pk->p_obusy = 0;	UNLOCK;}/* * shut down line by *	ignoring new input *	letting output drain *	releasing space and turning off line discipline */pkclose(S)SDEF;{register struct pack *pk;register i,s,rbits;char **bp;#define	NTRIES	1	pk = PADDR;	pk->p_state |= DRAINO;	/*	 * try to flush output	 */	i = 0;	LOCK;	if (pklive(pk)==0) {		pk->p_state = DOWN;		UNLOCK;		goto final;	}	pk->p_timer = 2;	while (pk->p_xcount && pk->p_state&LIVE) {		if (pk->p_state&(RCLOSE+DOWN) || ++i > NTRIES)			break;		pkoutput(pk);		SLEEP(&pk->p_ps,PKOPRI);	}	pk->p_timer = 0;	pk->p_state |= DOWN;	UNLOCK;	/*	 * try to exchange CLOSE messages	 */	i = 0;	while ((pk->p_state&RCLOSE)==0 && i<NTRIES) {		pk->p_msg = M_CLOSE;		pk->p_timer = 2;		pkoutput(pk);		SLEEP(&pk->p_ps, PKOPRI);		i++;	}final:	TURNOFF;	/*	 * free space	 */	rbits = DTOM(pk->p_rsize);	for (i=0;i<8;i++) {		if (pk->p_os[i]!=B_NULL) {			FREEPACK(pk->p_ob[i],pk->p_bits);			pk->p_xcount--;		}		if (pk->p_is[i]!=B_NULL)  {			FREEPACK(pk->p_ib[i],rbits);		}	}	LOCK;	while (pk->p_ipool != NULL) {		bp = pk->p_ipool;		pk->p_ipool = (char **)*bp;		FREEPACK((caddr_t)bp, rbits);	}	UNLOCK;	for(i=0;i<NPLINES;i++)		if (pklines[i]==pk)  {			pklines[i] = NULL;		}	FREEPACK((caddr_t)pk, npbits);}pkreset(pk)register struct pack *pk;{	pk->p_ps = pk->p_pr =  pk->p_rpr = 0;	pk->p_nxtps = 1;}chksum(s,n)register char *s;register n;{	register short sum;	register unsigned t;	register x;	sum = -1;	x = 0;	do {		if (sum<0) {			sum <<= 1;			sum++;		} else			sum <<= 1;		t = sum;		sum += (unsigned)*s++;		x += sum^n;		if ((unsigned)sum <= t) {			sum ^= x;		}	} while (--n > 0);	return(sum);}pkline(pk)register struct pack *pk;{register i;	for(i=0;i<NPLINES;i++) {		if (pklines[i]==pk)			return(i);	}	return(-i);}pkzero(s,n)register char *s;register n;{	while (n--)		*s++ = 0;}pksize(n)register n;{register k;	n >>= 5;	for(k=0; n >>= 1; k++);	return(k);}

⌨️ 快捷键说明

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