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

📄 sh.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 4 页
字号:
 	 * clear bits and check for 6,7,and 8, else its 5 bits. 	 */ 	lpar &= ~SH_BITS8; 	switch(tp->t_cflag&CSIZE) { 		case CS6: 			lpar |= SH_BITS6; 			break; 		case CS7: 			lpar |= SH_BITS7; 			break; 		case CS8: 			lpar |= SH_BITS8; 			break; 	}	/*	 * Outgoing Auto flow control.	 * No auto flow control allowed if startc != ^q and stopc !=	 * ^s.  Most drivers do not allow this to be changed.	 */	if ((tp->t_cflag_ext & PAUTOFLOW) && (tp->t_cc[VSTOP] == CTRL('s')) && 		(tp->t_cc[VSTART] == CTRL('q')))		addr->lnctrl |= SH_XFLOW;	else		addr->lnctrl &= ~SH_XFLOW;#ifdef SHDEBUG	if (shdebug)		mprintf("shparam: tp=%x, lpr=%x\n", tp, lpar);#endif	/*	 * Only write the line parameter register if the	 * new parameters differ from the current ones.	 * This avoids some nasty delay timing (see below).	 */	if (addr->lpr != lpar) {		/*		 * Must delay two character times before		 * we change the line parameters.		 * Find the number of microseconds of delay required,		 * based on the current speed setting.		 */		br = (addr->lpr>>12)&0x0f;		for (i=0; i<SHDTSIZE; i++)			if (br == sh_speeds[i]) {				tcd = sh_delays[i] * 2;				break;			}		/*		 * Delay long enough for two characters to be transmitted		 * (see comments above "#define SHDTSIZE").		 * Use microdelay for times less than 10 Msec		 * (speeds >= 2400 BPS), otherwise use a timeout.		 * Timeouts are inaccurate, but better than spinning at ipl.		 */		if (tcd) {		    if (tcd < 10000) {			DELAY(tcd);		    } else {			i = (tcd / 10000);	/* timeout value in ticks */			if (tcd % 10000)			    i += 1;		/* fraction of a tick */			i += 1;			/* 10 Msec clock granularity */			sh_newlpr[unit] = lpar;			timeout(sh_lpr_load, tp, i);			sleep((caddr_t)&tp->t_addr, PZERO-10);			splx(s);			return;		    }		}		addr->lpr = lpar;	}	splx(s);}/* * This routine loads a new value into the line * parameter register, after the two character * delay has expired (see shparam() abobe). * The spl7() makes sure the line select bits in * the CSR are saved and restored properly. This is * necessary because this routine is called via timeout, * which is clock driven (clock interrupts at spl6). * The current line number is saved in sh_softcsr, because * we can't read it from the csr without lossing xmit interrupts. */sh_lpr_load(tp)register struct tty *tp;{	register struct shdevice *addr = (struct shdevice *)tp->t_addr;	register int unit = minor(tp->t_dev);	register int s, oldunit;	s = spl7();	/* THIS IS REALLY NECESSARY */	oldunit = (sh_softcsr & LINEMASK);	addr->csr.low = SH_RIE|(unit & LINEMASK);	addr->lpr = sh_newlpr[unit & LINEMASK];	wakeup((caddr_t)&tp->t_addr);	addr->csr.low = (SH_RIE|oldunit);	splx(s);}/* * SH transmitter interrupt. * Restart each line which used to be active but has * terminated transmission since the last interrupt. */shxint(sh)	int sh;  /* module number */{	register struct tty *tp;	register struct shdevice *addr;	register int unit;	char csrxmt;	addr = (struct shdevice *)shmem;	while ((csrxmt = addr->csr.high) < 0) {		if (csrxmt & SH_DIAGFAIL)			printf("sh%d: DIAG. FAILURE\n", sh);		unit = sh * 8;		unit |= csrxmt&LINEMASK;		tp = &sh_tty[unit];#ifdef SHDEBUG		if (shdebug > 7)			mprintf("shxint: unit=%x, tp=%x, c_cc=%d\n",				unit, tp, tp->t_outq.c_cc);#endif		tp->t_state &= ~TS_BUSY;		if (tp->t_state&TS_FLUSH)			tp->t_state &= ~TS_FLUSH;		if (tp->t_line)			(*linesw[tp->t_line].l_start)(tp);		else			shstart(tp);	}}/* * Start (restart) transmission on the given SH line. */shstart(tp)	register struct tty *tp;{	register struct shdevice *addr;	register int unit, nch, line;	int s;	int free;	char *cp = tp->t_outq.c_cf;	union {		int	x;		char	y[2];	} wdbuf;	unit = minor(tp->t_dev);	line = unit & LINEMASK; /* unit now equals the line number */	addr = (struct shdevice *)tp->t_addr;	/*	 * Must hold interrupts in following code to prevent	 * state of the tp from changing.	 */	s = spl5();	/*	 * If it's currently active, or delaying, no need to do anything.	 * Also do not transmit if not CTS	 */	if ((tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) ||		 ((tp->t_state&TS_CARR_ON) && (shmodem[unit]&MODEM_CTS)==0))		goto out;	/*	 * If there are sleepers, and output has drained below low	 * water mark, wake up the sleepers.	 */#ifdef SHDEBUG	if (shdebug > 9)		mprintf("shstart0: tp=%x, LO=%d, cc=%d \n", tp,			TTLOWAT(tp), tp->t_outq.c_cc);#endif	if (tp->t_outq.c_cc<=TTLOWAT(tp)) {		if (tp->t_state&TS_ASLEEP) {  /* wake up when output done */			tp->t_state &= ~TS_ASLEEP;			wakeup((caddr_t)&tp->t_outq);		}		if (tp->t_wsel) {   /* for select system call */			selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);			tp->t_wsel = 0;			tp->t_state &= ~TS_WCOLL;		}	}	/*	 * If we stopped output due to XOFF	 * restart it by re-setting xmit enable.	 * Must be done before checking if the queue is empty.	 * Otherwise, last line of output may not restart.	 */	addr->csr.low = SH_RIE|line; /* select line */	sh_softcsr = SH_RIE|line; /* select line */	if ((addr->tbuffad2.high&SH_XEN) == 0) {		if (addr->lnctrl&SH_XABORT)			addr->lnctrl &= ~SH_XABORT;		free = addr->fun.fs.fifosize;		addr->tbuffad2.high = SH_XEN;		if (free < 64) {			tp->t_state |= TS_BUSY;			goto out;		}	}	/*	 * Now restart transmission unless the output queue is	 * empty.	 */	if (tp->t_outq.c_cc == 0)		goto out;	if ((tp->t_lflag_ext & PRAW) || (tp->t_oflag_ext & PLITOUT) || 	    ((tp->t_oflag & OPOST) == 0))		nch = ndqb(&tp->t_outq, 0); /* number of consecutive chars */	else {		nch = ndqb(&tp->t_outq, DELAY_FLAG);		/*		 * If first thing on queue is a delay process it.		 */		if (nch == 0) {			nch = getc(&tp->t_outq);			timeout(ttrstrt, (caddr_t)tp, (nch&0x7f)+6);			tp->t_state |= TS_TIMEOUT;			goto out;		}	}	/*	 * If characters to transmit, restart transmission.	 */	if (nch) {#ifdef SHDEBUG		if (shdebug > 9)			mprintf("shstart1: line=%x, nch=%d\n", line, nch);#endif		addr->csr.low = SH_RIE|line; /* select line */		sh_softcsr = SH_RIE|line; /* select line */		addr->csr.high = SH_XIE;		if (addr->lnctrl&SH_XABORT)			addr->lnctrl &= ~SH_XABORT;		free = addr->fun.fs.fifosize;		if (nch > free)			nch = free;		else			free = nch;		while (free > 1) {			wdbuf.y[0] = *cp++;			wdbuf.y[1] = *cp++;			addr->fun.fifodata = wdbuf.x;			free -= 2;		}		if (free == 1)			addr->fun.fs.fifosize = *cp++; /* lo byte wrt */		ndflush(&tp->t_outq, nch);		tp->t_state |= TS_BUSY;	}out:	splx(s);}/* * Stop output on a line, e.g. for ^S/^Q or output flush. *//*ARGSUSED*/shstop(tp, flag)	register struct tty *tp;{	register struct shdevice *addr;	register int unit, s;	addr = (struct shdevice *)tp->t_addr;	/*	 * Block input/output interrupts while messing with state.	 */	s = spl5();	if (tp->t_state & TS_BUSY) {		/*		 * Device is transmitting; stop output.		 * We can continue later		 * by examining the address where the sh stopped.		 */		unit = minor(tp->t_dev);		addr->csr.low = (unit&LINEMASK)|SH_RIE;		sh_softcsr = (unit&LINEMASK)|SH_RIE;		/*		 * Abort xmit only if flushing tty queues, i.e.,		 * called by ttyflush().		 * Otherwise, turn off Xmit enable to stop output.		 */		if ((tp->t_state&TS_TTSTOP)==0) {			tp->t_state |= TS_FLUSH;			addr->lnctrl |= SH_XABORT;  /* abort transmission */		} else {			/*			 * If flushing output in AUTOFLOW mode we have no			 * choice but to let the remainder drain.  If this			 * test wasn't here and SH_XFLOW was set the device			 * would be waiting for ^Q once we cleared xmit			 * enable.			 */ 			if ((tp->t_cflag_ext & PAUTOFLOW) == 0) {				/* turn off xmit enable */				addr->tbuffad2.high = 0;    				tp->t_state &= ~TS_BUSY;			}		}	}	splx(s);}shreset(uban)	int uban;{}sh_cd_drop(tp)register struct tty *tp;{	register struct shdevice *addr = (struct shdevice *)tp->t_addr;	register int unit = minor(tp->t_dev);	addr->csr.low = SH_RIE|(unit & LINEMASK);	sh_softcsr = SH_RIE|(unit & LINEMASK);	if ((tp->t_state&TS_CARR_ON) &&		((addr->fun.fs.stat&SH_CD) == 0)) {		if (shdebug)		    mprintf("sh_cd:  no CD, tp=%x\n", tp);		sh_tty_drop(tp);		return;	}	shmodem[minor(tp->t_dev)] |= MODEM_CD;	if (shdebug)	    mprintf("sh_cd:  CD is up, tp=%x\n", tp);}sh_dsr_check(tp)register struct tty *tp;{	int unit = minor(tp->t_dev);	register struct shdevice *addr = (struct shdevice *)tp->t_addr;	if (shmodem[unit]&MODEM_DSR_START) {		if (shdebug)		    mprintf("sh_dsr_check0:  tp=%x\n", tp);		shmodem[unit] &= ~MODEM_DSR_START;		addr->csr.low = SH_RIE|(unit&LINEMASK);		sh_softcsr = SH_RIE|(unit&LINEMASK);		/* 		 * If shdsr is set look for DSR|CTS|CD, otherwise look 		 * for CD|CTS only.		 */		if (shdsr) {			if ((addr->fun.fs.stat&SH_XMIT)==SH_XMIT)				sh_start_tty(tp);		}		else			if ((addr->fun.fs.stat&SH_NODSR)==SH_NODSR)				sh_start_tty(tp);		return;	}	if ((tp->t_state&TS_CARR_ON)==0)  {		sh_tty_drop(tp);		if (shdebug)		    mprintf("sh_dsr_check:  no carrier, tp=%x\n", tp);	}	else		if (shdebug)		    mprintf("sh_dsr_check:  carrier is up, tp=%x\n", tp);}/* *  cd_down return 1 if carrier has been down for at least 2 secs. */sh_cd_down(tp)struct tty *tp;{	int msecs;	int unit = minor(tp->t_dev);	msecs = 1000000 * (time.tv_sec - shtimestamp[unit].tv_sec) +		(time.tv_usec - shtimestamp[unit].tv_usec);	if (msecs > 2000000)		return(1);	else		return(0);}sh_tty_drop(tp)struct tty *tp;{	register struct shdevice *addr = (struct shdevice *)tp->t_addr;	register int unit;	if (tp->t_flags&NOHANG)		return;	unit = minor(tp->t_dev); 	shmodem[unit] = MODEM_BADCALL; 	tp->t_state &= ~(TS_CARR_ON|TS_TTSTOP|TS_BUSY|TS_ISUSP); 	wakeup((caddr_t)&tp->t_rawq);	gsignal(tp->t_pgrp, SIGHUP);	gsignal(tp->t_pgrp, SIGCONT);	addr->csr.low = SH_RIE|(unit&LINEMASK);	sh_softcsr = SH_RIE|(unit&LINEMASK);	addr->lnctrl &= ~(SH_DTR|SH_RTS);  /* turn off DTR */}sh_start_tty(tp)	register struct tty *tp;{	int unit = minor(tp->t_dev);	tp->t_state &= ~TS_ONDELAY;	tp->t_state |= TS_CARR_ON;	if (shdebug)	       mprintf("sh_start_tty:  tp=%x\n", tp);	if (shmodem[unit]&MODEM_DSR)		untimeout(sh_dsr_check, tp);	shmodem[unit] |= MODEM_CD|MODEM_CTS|MODEM_DSR;	shtimestamp[unit] = shzerotime;	wakeup((caddr_t)&tp->t_rawq);}shbaudrate(speed)register int speed;{    if (sh_valid_speeds & (1 << speed))	return (1);    else	return (0);}#endif

⌨️ 快捷键说明

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