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

📄 dhu.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 4 页
字号:
 	if (tp->t_cflag & PARENB) { 		if ((tp->t_cflag & PARODD) == 0) 			/* else set even */ 			lpar |= DHU_PENABLE|DHU_EVENPAR; 		else 			/* set odd */ 			lpar = (lpar | DHU_PENABLE)&~DHU_EVENPAR; 	} 	/* 	 * character size. 	 * clear bits and check for 6,7,and 8, else its 5 bits. 	 */ 	lpar &= ~DHU_BITS8; 	switch(tp->t_cflag&CSIZE) { 		case CS6: 			lpar |= DHU_BITS6; 			break; 		case CS7: 			lpar |= DHU_BITS7; 			break; 		case CS8: 			lpar |= DHU_BITS8; 			break; 	}	/*	 * Outgoing Auto flow control.	 * No auto flow control allowed if startc != ^q and startc !=	 * ^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 |= DHU_XFLOW;	else		addr->lnctrl &= ~DHU_XFLOW;	WBFLUSH();	addr->lpr = lpar;	WBFLUSH();#ifdef DHUDEBUG	if (dhudebug)		mprintf("dhuparam: tp=%x, lpr=%x\n", tp, lpar);#endif	splx(s);}/* * DHU11 transmitter interrupt. * Restart each line which used to be active but has * terminated transmission since the last interrupt. */dhuxint(dhu)	int dhu;  /* module number */{	register struct tty *tp;	register struct dhudevice *addr;	register struct uba_device *ui;	register int unit, totaldelay;	u_short cntr;	char csrxmt;	ui = dhuinfo[dhu];	addr = (struct dhudevice *)ui->ui_addr;	while ((csrxmt = addr->csr.high) < 0) {		if (csrxmt & DHU_DMAERR)			printf("dhu%d:%d DMA ERROR\n", dhu, csrxmt&0xf);		if (csrxmt & DHU_DIAGFAIL)			printf("dhu%d: DIAG. FAILURE\n", dhu);		unit = dhu * 16;		unit |= csrxmt&LINEMASK;		tp = &dhu11[unit];#ifdef DHUDEBUG		if (dhudebug > 4)			mprintf("dhuxint: unit=%x, tp=%x, c_cc=%d\n",				unit, tp, tp->t_outq.c_cc);#endif		tp->t_state &= ~TS_BUSY;		addr->csr.low = (unit&LINEMASK)|DHU_RIE;		WBFLUSH();		totaldelay = 0;		while ((addr->tbuffad2.low & DHU_START) && (totaldelay <= 100)){		    totaldelay++;		    DELAY(10000);		}		if (addr->tbuffad2.low & DHU_START) {		    printf("dmbxint: Resetting DMA START bit on line %d\n",unit);		    addr->tbuffad2.low &= ~DHU_START;		}		if (tp->t_state&TS_FLUSH)			tp->t_state &= ~TS_FLUSH;		else {			/*			 * Determine number of chars transmitted			 * so far and flush these from the tty			 * output queue.			 * Do arithmetic in a short to make up			 * for lost 16&17 bits (in tbuffad2).			 */			cntr = addr->tbuffad1 -				UBACVT(tp->t_outq.c_cf, ui->ui_ubanum);			ndflush(&tp->t_outq, cntr);		}		if (tp->t_state & TS_NEED_PARAM) {		    tp->t_state &= ~TS_NEED_PARAM;		    dhuparam(unit);		}		if (tp->t_line)			(*linesw[tp->t_line].l_start)(tp);		else			dhustart(tp);	}}/* * Start (restart) transmission on the given DHU11 line. */dhustart(tp)	register struct tty *tp;{	register struct dhudevice *addr;	register int car, dhu, unit, nch;	register int totaldelay;	int line, s;	unit = minor(tp->t_dev);	dhu = unit >> 4;	line = unit & LINEMASK; /* unit now equals the line number */	addr = (struct dhudevice *)tp->t_addr;	/*	 * Must hold interrupts in following code to prevent	 * state of the tp from changing.	 */	s = spltty();	/*	 * 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) && (dhumodem[unit]&MODEM_CTS)==0))		goto out;	/*	 * If there are sleepers, and output has drained below low	 * water mark, wake up the sleepers.	 */#ifdef DHUDEBUG	if (dhudebug > 9)		mprintf("dhustart0: 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;		}	}	/*	 * 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 DHUDEBUG		if (dhudebug > 9)			mprintf("dhustart1: line=%x, nch=%d\n", line, nch);#endif		addr->csr.low = DHU_RIE|line; /* select line */		WBFLUSH();		/*		 * Wait for dma start to clear to a maximum of 1 second to		 * prevent a system hang on hardware failure.  After the bit		 * has stuck once, do not repeat this check.		 */		/*		 * TODO: 		 * This should be changed to use a timeout instead of calling		 * microdelay!!!!!  Timeouts can be of granularity of 10 ms.		 * Do this in the DMB driver also.		 */		totaldelay = 0;		while ((addr->tbuffad2.low & DHU_START) && (totaldelay <= 100))                        if ((dhu_softc[dhu].sc_flags[unit&LINEMASK]) == 0) {	    			totaldelay++;	    			DELAY(10000);			}			else				totaldelay = 90000;		if ((addr->tbuffad2.low & DHU_START) && 		  ((dhu_softc[dhu].sc_flags[unit&LINEMASK]) == 0)) {				printf("dhu%d,line%d DHU HARDWARE ERROR.  TX.DMA.START failed\n",dhu,line); 				/*				 * Prevent further activity on this line by				 * setting state flag to dead.				 */				dhu_softc[dhu].sc_flags[unit&LINEMASK]++;				splx(s);				return;		}		if (addr->lnctrl & DHU_XABORT) /* clear abort if already set */			addr->lnctrl &= ~(DHU_XABORT);		addr->csr.high = DHU_XIE;		/*		 * If cblocks are ever malloc'ed we must insure that they		 * never cross VAX physical page boundaries.		 */		/*		 * Give the device the starting address of a DMA transfer.  		 * Translate the system virtual address into a physical		 * address.		 */		car = UBACVT(tp->t_outq.c_cf, dhuinfo[dhu]->ui_ubanum);		addr->tbuffad1 = car;		addr->tbuffcnt = nch;		/*		 * If Outgoing auto flow control is enabled, the hardware will		 * control the transmit enable bit.		 */		if ((tp->t_cflag_ext & PAUTOFLOW) == 0)			addr->tbuffad2.high = DHU_XEN;		/* get extended address bits and start DMA output */		if (dhuinfo[dhu]->ui_hd->uba_type&UBAUVI)			addr->tbuffad2.low = ((car>>16)&0x3f)|DHU_START;		else			addr->tbuffad2.low = ((car>>16)&0x3)|DHU_START;		WBFLUSH();		tp->t_state |= TS_BUSY;	}out:	splx(s);}/* * Stop output on a line, e.g. for ^S/^Q or output flush. *//*ARGSUSED*/dhustop(tp, flag)	register struct tty *tp;{	register struct dhudevice *addr;	register int unit, s;	addr = (struct dhudevice *)tp->t_addr;	/*	 * Block input/output interrupts while messing with state.	 */	s = spltty();	if (tp->t_state & TS_BUSY) {		/*		 * Device is transmitting; stop output.		 * We can continue later		 * by examining the address where the dhu stopped.		 */		unit = minor(tp->t_dev);		addr->csr.low = (unit&LINEMASK)|DHU_RIE;		WBFLUSH();		if ((tp->t_state&TS_TTSTOP)==0)			tp->t_state |= TS_FLUSH;		addr->lnctrl |= DHU_XABORT;  /* abort DMA transmission */		WBFLUSH();	}	splx(s);}/* * Reset state of driver if UBA reset was necessary. * Reset the csr and lpr registers on open lines, and * restart transmitters. */dhureset(uban)	int uban;{	register int dhu, unit, s;	register struct tty *tp;	register struct uba_device *ui;	register struct dhudevice *addr;	int i;	if (tty_ubinfo[uban] == 0)		return;  /* there are no dhu11's in use */	if (uba_hd[uban].uba_type&UBAUVI)		cbase[uban] = tty_ubinfo[uban]&0x3fffff;	else		cbase[uban] = tty_ubinfo[uban]&0x3ffff;	dhu = 0;	for (dhu = 0; dhu < nNDHU; dhu++) {		ui = dhuinfo[dhu];		if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban)			continue;		addr = (struct dhudevice *)ui->ui_addr;		printf(" dhu%d", dhu);		unit = dhu * 16;		for (i = 0; i < 16; i++) {			tp = &dhu11[unit];			if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) {				dhuparam(unit);				s = spltty();				addr->csr.low = (i&LINEMASK)|DHU_RIE;				WBFLUSH();				addr->lnctrl |= DHU_DTR|DHU_RTS|DHU_REN;				WBFLUSH();				splx(s);				tp->t_state &= ~TS_BUSY;				dhustart(tp);			}			unit++;		}	}	dhutimer();}/* * At software clock interrupt time or after a UNIBUS reset * empty all the dh silos. */dhutimer(){	register int dhu;	register int s = spltty();	for (dhu = 0; dhu < nNDHU; dhu++)		dhurint(dhu);	splx(s);}dhu_cd_drop(tp)register struct tty *tp;{	register struct dhudevice *addr = (struct dhudevice *)tp->t_addr;	register int unit = minor(tp->t_dev);	addr->csr.low = DHU_RIE|(unit & LINEMASK);	WBFLUSH();	if ((tp->t_state&TS_CARR_ON) &&		((addr->fun.fs.stat&DHU_CD) == 0)) {		if (dhudebug)		    mprintf("dhu_cd:  no CD, tp=%x\n", tp);		dhu_tty_drop(tp);		return;	}	dhumodem[minor(tp->t_dev)] |= MODEM_CD;	if (dhudebug)	    mprintf("dhu_cd:  CD is up, tp=%x\n", tp);}dhu_dsr_check(tp)register struct tty *tp;{	int unit = minor(tp->t_dev);	register struct dhudevice *addr = (struct dhudevice *)tp->t_addr;	if (dhumodem[unit]&MODEM_DSR_START) {		if (dhudebug)		    mprintf("dhu_dsr_check0:  tp=%x\n", tp);		dhumodem[unit] &= ~MODEM_DSR_START;		addr->csr.low = DHU_RIE|(unit&LINEMASK);		WBFLUSH();		/* 		 * If dhudsr is set look for DSR|CTS|CD, otherwise look 		 * for CD|CTS only.		 */		if (dhudsr) {			if ((addr->fun.fs.stat&DHU_XMIT)==DHU_XMIT)				dhu_start_tty(tp);		}		else			if ((addr->fun.fs.stat&(DHU_CD|DHU_CTS))==(DHU_CD|DHU_CTS))				dhu_start_tty(tp);		return;	}	if ((tp->t_state&TS_CARR_ON)==0)  {		dhu_tty_drop(tp);		if (dhudebug)		    mprintf("dhu_dsr_check:  no carrier, tp=%x\n", tp);	}	else		if (dhudebug)		    mprintf("dhu_dsr_check:  carrier is up, tp=%x\n", tp);}/* *  cd_down return 1 if carrier has been down for at least 2 secs. */dhu_cd_down(tp)struct tty *tp;{	int msecs;	int unit = minor(tp->t_dev);	msecs = 1000000 * (time.tv_sec - dhutimestamp[unit].tv_sec) +		(time.tv_usec - dhutimestamp[unit].tv_usec);	if (msecs > 2000000)		return(1);	else		return(0);}dhu_tty_drop(tp)struct tty *tp;{	register struct dhudevice *addr = (struct dhudevice *)tp->t_addr;	register int unit;	if (tp->t_flags&NOHANG)		return;	unit = minor(tp->t_dev);	dhumodem[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 = DHU_RIE|(unit&LINEMASK);	WBFLUSH();	addr->lnctrl &= ~(DHU_DTR|DHU_RTS);  /* turn off DTR */	WBFLUSH();}dhu_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 (dhudebug)	       mprintf("dhu_start_tty:  tp=%x\n", tp);	if (dhumodem[unit]&MODEM_DSR)		untimeout(dhu_dsr_check, tp);	dhumodem[unit] |= MODEM_CD|MODEM_CTS|MODEM_DSR;	dhutimestamp[unit] = dhuzerotime;	wakeup((caddr_t)&tp->t_rawq);}dhubaudrate(speed)register int speed;{    if (dhu_valid_speeds & (1 << speed))	return (1);    else	return (0);}#endif

⌨️ 快捷键说明

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