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

📄 dp.c

📁 UNIX v6源代码 这几乎是最经典的unix版本 unix操作系统设计和莱昂氏unix源代码分析都是用的该版
💻 C
字号:
#/* *//* * DP-11 Synchronous interface driver * This driver is rather insensitive to the remote * device it talks to, which is to say most of the protocol * must be supplied by the calling program. * Exceptions: parity is even; 7 data bits per character; * max. of 512 characters per record; 10 second timeout * on waiting to receive; half-duplex transmission. */#include "../param.h"#include "../conf.h"#include "../user.h"#include "../buf.h"/* control info */struct {	char	*dp_buf;	char	*dp_bufp;	int	dp_nxmit;	char	dp_state;	char	dp_timer;	int	dp_proc;} dp11;/* device registers */struct {	int	dprcsr;	char	dprbuf;	char	dpsyn0;	int	dptcsr;	char	dptbuf;	char	dpsyn1;};/* bits */#define	ODDPAR	010000#define	IENABLE	0100#define	HDUPLX	02#define	CTRANS	0100000#define	RORUN	040000#define	RING	020000#define	DSRDY	010000#define	CARRIER	04000#define	DONE	0200#define	IENABLE	0100#define	SIENABL	040#define	WRITE	1#define	READ	0#define	DTRDY	01#define	RCVACT	04000#define	DPADDR	0174770#define	DPPRI	5#define	SYN	026		/* (receive) sync character *//* * The open fails unless the device is not open or * the opening process is the one that has it open already. */dpopen(dev, flag){	int dptimeout();	if (dp11.dp_proc!=0 && dp11.dp_proc!=u.u_procp) {		u.u_error = ENXIO;		return;	}	dp11.dp_proc = u.u_procp;	dp11.dp_state = READ;	if (dp11.dp_buf==0) {		dp11.dp_buf = getblk(NODEV);		dp11.dp_bufp = dp11.dp_buf->b_addr;		dp11.dp_timer = HZ;		timeout(dptimeout, 0, HZ);	}	DPADDR->dpsyn0 = SYN;	DPADDR->dprcsr = HDUPLX|IENABLE;	DPADDR->dptcsr = IENABLE|SIENABL|DTRDY;}dpclose(){	DPADDR->dprcsr = 0;	DPADDR->dptcsr = 0;	dp11.dp_timer = 0;	dp11.dp_proc = 0;	if (dp11.dp_buf != 0) {		brelse(dp11.dp_buf);		dp11.dp_buf = 0;	}}/* * Read waits until: *  there is loss of "data set ready", or *  a timeout occurs, or *  a full record has been received. * The former two result in an error. */dpread(){	register char *bp, **epp;	bp = dp11.dp_buf->b_addr;	epp = &dp11.dp_bufp;	for(;;) {		if(dpwait())			return;		if (*epp > bp)			break;		spl6();		if (dp11.dp_timer <= 1) {			spl0();			return;		}		sleep(&dp11, DPPRI);		spl0();	}	iomove(dp11.dp_buf, 0, min(u.u_count, *epp-bp), B_READ);}/* * write checks to make sure that the data set is not reading, * and that it is ready.  Then the record is copied * and transmission started. */dpwrite(){	register char *bp;	if (u.u_count==0 || dpwait())		return;	dp11.dp_state = WRITE;	bp = dp11.dp_buf->b_addr;	dp11.dp_bufp = bp;	if (u.u_count>512)		u.u_count = 512;	dp11.dp_nxmit = u.u_count;	iomove(dp11.dp_buf, 0, u.u_count, B_WRITE);	dpstart();}/* * If "data set ready" is down return an error; otherwise * wait until the dataset is in read state with no carrier, * which means a record has just been received. */dpwait(){	for(;;) {		if ((DPADDR->dptcsr&DSRDY)==0 || dp11.dp_buf==0) {			u.u_error = EIO;			return(1);		}		spl6();		if (dp11.dp_state==READ && (DPADDR->dptcsr&CARRIER)==0) {			spl0();			return(0);		}		sleep(&dp11, DPPRI);		spl0();	}}/* * Start off the next character to be transmitted; * when the record is done, drop back into read state. */dpstart(){	register int c;	extern char partab[];	dp11.dp_timer = 10;	if (--dp11.dp_nxmit >= 0) {		c = (*dp11.dp_bufp++) & 0177;		DPADDR->dptbuf = c | ~partab[c]&0200;	} else {		dp11.dp_bufp = dp11.dp_buf->b_addr;		dp11.dp_state = READ;	}}/* * Count down the DP timer (once per second) * If it runs out, it presumably means the other station * won't speak. */dptimeout(){	if (dp11.dp_timer==0)		return;	if (--dp11.dp_timer==0) {		dpturnaround();		dp11.dp_timer = 1;	}	timeout(dptimeout, 0, HZ);}/* * Receiver interrupt: if reading, stash character * unless there is an overrun. */dprint(){	register int c;	c = DPADDR->dprbuf & 0177;	if (dp11.dp_state==READ) {		if ((DPADDR->dprcsr&ODDPAR) == 0)			c =| 0200;		if (dp11.dp_bufp < dp11.dp_buf->b_addr+512)			*dp11.dp_bufp++ = c;	}}/* * Transmitter interrupt: * Knock down hardware bits. * If carrier has dropped, the record is done, so turn the line around; * otherwise start another character. */dpxint(){	register int dpstat;	dpstat = DPADDR->dptcsr;	DPADDR->dptcsr =& ~(CTRANS|RORUN|RING|DONE);	if (dpstat & (CTRANS|RORUN))		dpturnaround();	else if (dpstat&DONE && dp11.dp_state==WRITE)		dpstart();}/* * Change the state from writing to reading at the end of a record. */dpturnaround(){	DPADDR->dprcsr =& ~RCVACT;	if (dp11.dp_state==WRITE) {		dp11.dp_timer = 10;		dp11.dp_state = READ;		dp11.dp_bufp = dp11.dp_buf->b_addr;	}	wakeup(&dp11);}

⌨️ 快捷键说明

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