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

📄 dmb.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 5 页
字号:
	printd("dmbattach: addr = 0x%x, flags = 0x%x, unit = %d\n",		addr, ui->ui_flags, ui->ui_unit);#	endif	/*	 * ui_flags format:	 * 	DMB: 0-7  dmbsoftcar, 8-15  printer cols, 16-23 printer rows.	 * 	DHB: 0-15 dmbsoftcar	 *	 * Set soft carrier (local lines) & line printer characteristics	 */	if (dmb_lines[ui->ui_unit] == DMB_8_LINES)		{		dmbsoftCAR[ui->ui_unit] = ui->ui_flags & 0xff;		dmbdefaultCAR[ui->ui_unit] = ui->ui_flags & 0xff;		cols = (ui->ui_flags>>8) & 0xff;		lines = (ui->ui_flags>>16) & 0xff;		}	else	/* 16 line dhb device */		{		dmbsoftCAR[ui->ui_unit] = ui->ui_flags & 0xffff;		dmbdefaultCAR[ui->ui_unit] = ui->ui_flags & 0xffff;		cols = (ui->ui_flags>>16) & 0xff; /* just in case ... */		lines = (ui->ui_flags>>24) & 0xff;		}	dmbl_softc[ui->ui_unit].dmbl_cols = (cols == 0?DMBL_DEFCOLS:cols);	dmbl_softc[ui->ui_unit].dmbl_lines = (lines == 0?DMBL_DEFLINES:lines);	/*	 * Initialize SMP locks.  One lock per dmb board, and one tty lock	 * for each line on the board.  Specify this driver as being MP safe.	 */	lockinit(&lk_dmb[ui->ui_unit], &lock_device15_d);	for (i=0; i< NUMLINES ; i++) {		tp = &dmb_tty[(ui->ui_unit * NUMLINES)+i];		lockinit(&tp->t_lk_tty, &lock_tty_d);		tp->t_smp = 1;	}	}/* * Open a DMB32 line. * Turn on this dmb if this is the first use of it. *//*ARGSUSED*/dmbopen(dev, flag)	dev_t dev;	int flag;{	register struct tty *tp;	register int unit, dmb;	register struct dmb_device *addr;	register struct uba_device *ui;	int s,error;	int inuse;  /* hold state of inuse bit while blocked waiting for carr */	int post_wakeup = 0;	unit = minor(dev);	if (unit & 0200)		return(dmblopen(dev,flag));	dmb = unit >> LINEBITS;#	ifdef DEBUG	printd("dmbopen: dev = 0x%x, flag = 0x%x, unit = 0x%x\n", dev, flag, unit);#	endif	if (unit >= ndmb || (ui = dmbinfo[dmb])== 0 || ui->ui_alive == 0)		return (ENXIO);	tp = &dmb_tty[unit];	DMB_TTY_LOCK(tp,s);	if (tp->t_state&TS_XCLUDE && u.u_uid != 0) {		DMB_TTY_UNLOCK(tp,s);		return (EBUSY);	}	while (tp->t_state&TS_CLOSING) { /* let DTR stay down for awhile */		sleep_unlock((caddr_t)&tp->t_rawq, TTIPRI,&tp->t_lk_tty);		DMB_TTY_LOCK(tp,s);	}	addr = (struct dmb_device *)ui->ui_addr;	tp->t_addr = (caddr_t)addr;	tp->t_oproc = dmbstart;	tp->t_baudrate = dmbbaudrate;	tp->t_state |= TS_WOPEN;	DMB_LOCK(dmb);	tty_def_open(tp, dev, flag, (dmbsoftCAR[dmb]&(1<<(unit&LINEMASK))));	if ((tp->t_state&TS_ISOPEN) == 0) {	    dmbmodem[unit] = MODEM_DSR_START; /* prevents spurious startups */	    /*	     * Set the receive fifo timeout to this number of miliseconds.	     */	    addr->dmb_acsr2 = (dmb_timeout << 16);	}	/*	 * Interrupts are enabled in dmbparam.	 */	dmbparam(unit);	/*	 * Wait for carrier, then process line discipline specific open.	 */	addr->dmb_acsr = (unit & LINEMASK) | DMB_IE;	/* line select */	addr->dmb_lpr |= (DMB_DTR | DMB_RTS);	if (tp->t_cflag & CLOCAL)		{#		ifdef  DEBUG		printd("dmbopen: local, tp=0x%x\n", tp);#		endif		tp->t_state |= TS_CARR_ON;		dmbmodem[unit] = MODEM_CTS|MODEM_CD|MODEM_DSR;		}	else if ((flag & (O_NDELAY|O_NONBLOCK)) == 0)		{		/*		 * DSR should not normally come up until DTR is asserted		 * However if TS_HUPCL is not set, it is		 * possible to get here with all modem signals		 * already asserted.  Or we could be dealing with		 * a very slow modem and it has not deasserted DSR yet.		 * Interrupts are enabled earlier in dmbparam.		 * 		 * If the DSR signal is being followed, wait at most		 * 30 seconds for CD, and don't transmit in the first 		 * 500ms.  Otherwise immediately look for CD|CTS.		 */		if (dmbdsr) {			if (addr->dmb_lstatlow & DMB_DSR)				{#				ifdef DEBUG				printd("dmbopen: modem, unit=%d\n", unit);#				endif				dmbmodem[unit] |= (MODEM_DSR_START|MODEM_DSR);				tp->t_dev = dev; /* need it for timeouts */				timeout(dmb_dsr_check_timeout, tp, hz*30);				timeout(dmb_dsr_check_timeout, tp, hz/2);				}			}		else 	{			dmbmodem[unit] |= (MODEM_DSR_START|MODEM_DSR);			dmb_dsr_check(tp,&post_wakeup);			}		}	DMB_UNLOCK(dmb);	if (flag & (O_NDELAY|O_NONBLOCK))		tp->t_state |= TS_ONDELAY;	else		while ((tp->t_state & TS_CARR_ON) == 0)			{			tp->t_state |= TS_WOPEN;			inuse = tp->t_state&TS_INUSE;			sleep_unlock((caddr_t)&tp->t_rawq,TTIPRI,&tp->t_lk_tty);			DMB_TTY_LOCK(tp,s);			/*			 * See if wakeup was caused by a false start.			 */			if (dmbmodem[unit]&MODEM_BADCALL){				DMB_TTY_UNLOCK(tp,s);				if (post_wakeup)					wakeup((caddr_t)&tp->t_rawq);				return(EWOULDBLOCK);			}			/*			 *  If we opened "block if in use"  and			 *  the terminal was not in use at that time			 *  but it became "in use" while we were			 *  waiting for carrier then return.			 */			if ((flag & O_BLKINUSE) && (inuse==0) &&			    (tp->t_state&TS_INUSE))				{				DMB_TTY_UNLOCK(tp,s);				if (post_wakeup)					wakeup((caddr_t)&tp->t_rawq);				return(EALREADY);				}			}	/*	 * Set state bit to tell tty.c not to assign this line as the 	 * controlling terminal for the process which opens this line.	 */	if ((flag & O_NOCTTY) && (u.u_procp->p_progenv == A_POSIX))		tp->t_state |= TS_ONOCTTY;	error = (*linesw[tp->t_line].l_open)(dev, tp);	DMB_TTY_UNLOCK(tp,s);	if (post_wakeup)		wakeup((caddr_t)&tp->t_rawq);	return(error);}/* * Close a DMB32 line. *//*ARGSUSED*/dmbclose(dev, flag)	dev_t dev;	int flag;{	register struct tty *tp;	register int unit;	register int dmb;	register struct dmb_device *addr;	int post_wakeup = 0;	int s;	unit = minor(dev);	if (unit & 0200){		dmblclose(dev,flag);		return;	}	dmb = unit >> LINEBITS;	tp = &dmb_tty[unit];	addr = (struct dmb_device *)tp->t_addr;#	ifdef DEBUG	printd("dmbclose: dev = 0x%x, flag = 0x%x, unit = 0x%x, addr = 0x%x\n",		dev, flag, unit, addr);#	endif	DMB_TTY_LOCK(tp,s);	if (tp->t_line)		(*linesw[tp->t_line].l_close)(tp);	DMB_LOCK(dmb);	if ((tp->t_cflag&HUPCL) || (tp->t_state&TS_ISOPEN)==0)		{		addr->dmb_acsr = (unit & LINEMASK) | DMB_IE;		addr->dmb_lpr &= ~(DMB_DTR | DMB_RTS);		tp->t_state &= ~TS_CARR_ON; /* prevents recv intr. timeouts */		if ((tp->t_cflag & CLOCAL) == 0)			{			/*			 * Drop DTR for at least a half sec. if modem line			 */			tp->t_state |= TS_CLOSING;			/*			 * Wait for DSR to drop			 */			addr = (struct dmb_device *)tp->t_addr;			addr->dmb_acsr = DMB_IE | (unit&LINEMASK);			/* 			 * If the DSR signal is being followed, give the			 * modem at most 5 seconds to deassert it. 			 */			if (dmbdsr && (addr->dmb_lstatlow & DMB_DSR))				{				timeout(wakeup, (caddr_t) &tp->t_dev, 5*hz);				DMB_UNLOCK(dmb);				sleep_unlock((caddr_t)&tp->t_dev, PZERO-10,					&tp->t_lk_tty);				DMB_TTY_LOCK(tp,s);				DMB_LOCK(dmb);				}			timeout(wakeup, (caddr_t) &tp->t_dev, hz/5);			DMB_UNLOCK(dmb);			sleep_unlock((caddr_t)&tp->t_dev, PZERO-10,					&tp->t_lk_tty);			DMB_TTY_LOCK(tp,s);			DMB_LOCK(dmb);			tp->t_state &= ~(TS_CLOSING);			post_wakeup = WAKEUP_RAWQ;			}		addr->dmb_acsr = (unit & LINEMASK) | DMB_IE;		addr->dmb_lpr &= ~DMB_RXENA;		}	dmbsoftCAR[dmb] &= ~(1<<(unit&LINEMASK));	dmbsoftCAR[dmb] |= (1<<(unit&LINEMASK)) & dmbdefaultCAR[dmb];	DMB_UNLOCK(dmb);	ttyclose(tp);	dmbmodem[unit] = 0;	tty_def_close(tp);	DMB_TTY_UNLOCK(tp,s);	if (post_wakeup)		wakeup((caddr_t)&tp->t_rawq);}dmbread(dev, uio)	dev_t dev;	struct uio *uio;{	register struct tty *tp;        register int unit;        unit = minor(dev);	if (unit & 0200)		/* read from lp device */		return(ENXIO);	tp = &dmb_tty[unit];	return ((*linesw[tp->t_line].l_read)(tp, uio));}dmbwrite(dev, uio)	dev_t dev;	struct uio *uio;{        register int unit;	register struct tty *tp;        unit = minor(dev);	if (unit & 0200)		/* write to parallel port */		return(dmblwrite(dev,uio));	tp = &dmb_tty[unit];	return ((*linesw[tp->t_line].l_write)(tp, uio));}/* * DMB32 interrupts at one location with async interrupts. * Examine Transmitter Action bit in "tbuf" register to determine *   if there is a transmit interrupt. * Examine Data Valid bit in "rbuf" register to determine *   if there is a receive interrupt. */dmbaint(dmb)	int dmb;{	register struct dmb_device *addr;	register struct uba_device *ui;	/*	 * The dmb is interrupting at ipl14.	 * For this reason an spltty is used to bump the ipl up to ipl15.	 */	spltty();	ui = dmbinfo[dmb];	addr = (struct dmb_device *)ui->ui_addr;	if (addr->dmb_tbuf & DMB_TXACT)	    dmbxint(dmb);	if (addr->dmb_rbuf & DMB_DATAVALID)	    dmbrint(dmb);}/* * DMB32 receiver interrupt. */dmbrint(dmb)	int dmb;{	register struct tty *tp;	register long c;	register struct dmb_device *addr;	struct tty *tp0;	register struct uba_device *ui;	register int line;	register int flg;	int overrun = 0;	u_char *modem0, *modem;	int modem_cont;	int post_wakeup = 0;	ui = dmbinfo[dmb];	if (ui == 0 || ui->ui_alive == 0)		return;	addr = (struct dmb_device *)ui->ui_addr;	tp0 = &dmb_tty[dmb<<LINEBITS];	modem0 = &dmbmodem[dmb<<LINEBITS];	/*	 * Loop fetching characters from the receive fifo for this	 * dmb until there are no more in the fifo. 	 *	 * First get a copy of the rbuf then make sure no other processor 	 * is servicing this interrupt by seeing if the rbuf contents have	 * changed in the meantime.	 */	while ((c = addr->dmb_rbuf) < 0)		{	/* if c < 0 then data valid bit is set */		line = (c>>16)&LINEMASK;		tp = tp0 + line;		smp_lock(&tp->t_lk_tty,LK_RETRY);		DMB_LOCK(dmb);		if ((c = addr->dmb_rbuf) >= 0) {			DMB_UNLOCK(dmb);			smp_unlock(&tp->t_lk_tty);			break;		}		if (line != (((addr->dmb_rbuf)>>16) & LINEMASK)) {			DMB_UNLOCK(dmb);			smp_unlock(&tp->t_lk_tty);  			continue;  		}		addr->dmb_rbuf = 0;		/* pop the fifo */		DMB_UNLOCK(dmb);		flg = tp->t_iflag;		modem = modem0 + line;#		ifdef  DEBUG		printd10("dmbrint: tp = 0x%x, c = 0x%x\n", tp, c);#		endif		/*		 * Check for modem transitions		 */		if (c & DMB_NONCHAR)			{			if (c & DMB_DIAG)				goto dmbrunlock;	/* ignore diagnostic info */#			ifdef DEBUG			printd("dmbrint: modem change, line = %d, tp = 0x%x, c = 0x%x, lstat = 0x%x\n", line, tp, c, addr->dmb_lstatlow);#			endif DEBUG			if (tp->t_cflag & CLOCAL)				goto dmbrunlock;			DMB_LOCK(dmb);			addr->dmb_acsr = (line | DMB_IE);			modem_cont = 0;			/*			 * Drop DTR immediately if DSR gone away.			 * If really an active close then do not			 *    send signals.			 */			if ((addr->dmb_lstatlow & DMB_DSR) == 0)				{				if (tp->t_state&TS_CLOSING)					{					untimeout(wakeup, (caddr_t) &tp->t_dev);					post_wakeup = WAKEUP_DEV;#						ifdef	DEBUG						printd("dmbrint: dsr closing down, line=%d\n",line);#						endif	DEBUG					DMB_UNLOCK(dmb);					goto dmbrunlock;					}				 if (tp->t_state & TS_CARR_ON)					{#						ifdef	DEBUG						printd("dmbrint: DSR drop, line = %d\n",line);#						endif	DEBUG					/* 					 * Drop line if DSR is being followed. 					 */					if (dmbdsr)						{						dmb_tty_drop(tp,&post_wakeup);						/*						 * Move continue here in order						 * to examine other transitions.						 */						DMB_UNLOCK(dmb);						goto dmbrunlock;						}					}				}			/*			 * Check for transient CD drops.			 * Only drop DTR if CD is down for more than 2 secs.			 */			if (tp->t_state&TS_CARR_ON)				if ((addr->dmb_lstatlow & DMB_DCD)==0)					{					if (*modem & MODEM_CD)						{						/* only start timer once */#						ifdef DEBUG						printd("dmbrint, cd_drop,line = %d\n",line);#						endif DEBUG						*modem &= ~MODEM_CD;						dmbtimestamp[minor(tp->t_dev)] = time;						timeout(dmb_cd_drop, tp, hz*dmbcdtime);						modem_cont = 1;						}					}				else				    /*				     * CD has come up again.				     * Stop timeout from occurring if set.				     * If interval is more than 2 secs then				     *	drop DTR.				     */				    if ((*modem & MODEM_CD)==0)					    {					    untimeout(dmb_cd_drop, tp);					    if (dmb_cd_down(tp)){						    /* drop connection */						dmb_tty_drop(tp,&post_wakeup);

⌨️ 快捷键说明

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