📄 dhu.c
字号:
/* * Wait for carrier, then process line discipline specific open. */ s=spltty(); if (addr->fun.fs.stat & DHU11) { /* * only the dhu11 has a timer. manual says we have to * point to line 0 before we set the timer * This timer causes a delay before interrupting on the first * character in hopes that more than one character can be * processed by a single interrupt. */ addr->csr.low = DHU_RIE|(0 & LINEMASK); /* set to line 0 */ WBFLUSH(); addr->run.rxtimer = 10; WBFLUSH(); } if (tp->t_cflag & CLOCAL) { /* this is a local connection - ignore carrier */ tp->t_state |= TS_CARR_ON; dhumodem[unit] |= MODEM_CTS|MODEM_CD|MODEM_DSR; addr->csr.low = DHU_RIE|(unit & LINEMASK); /* set to line #*/ /* enable interrupts*/ WBFLUSH(); addr->lnctrl &= ~(DHU_MODEM); addr->lnctrl |= (DHU_DTR|DHU_RTS|DHU_REN); WBFLUSH(); splx(s); /* * 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; return ((*linesw[tp->t_line].l_open)(dev, tp)); } addr->csr.low = DHU_RIE|(unit & LINEMASK); WBFLUSH(); addr->lnctrl |= (DHU_DTR|DHU_RTS|DHU_MODEM|DHU_REN); WBFLUSH(); /* * If the DSR signal is followed, give carrier 30 secs to come up, * and do not transmit/receive data for the first 500ms. Otherwise * immediately to to dhu_dsr_check tolook for CD and CTS. */ if ((flag & (O_NDELAY|O_NONBLOCK)) == 0) { if (dhudsr) { if ((addr->fun.fs.stat)&DHU_DSR) { dhumodem[unit] |= (MODEM_DSR_START|MODEM_DSR); tp->t_dev = dev; /* need it for timeouts */ timeout(dhu_dsr_check, tp, hz*30); timeout(dhu_dsr_check, tp, hz/2); } } else { dhumodem[unit] |= (MODEM_DSR_START|MODEM_DSR); dhu_dsr_check(tp); } }#ifdef DHUDEBUG if (dhudebug) mprintf("dhuopen: line=%d, state=%x, pid=%d\n", unit, tp->t_state, u.u_procp->p_pid);#endif if (flag & (O_NDELAY|O_NONBLOCK)) tp->t_state |= TS_ONDELAY; else { while ((tp->t_state&TS_CARR_ON)==0) { inuse = tp->t_state&TS_INUSE; /* * Sleep until all the necessary modem signals * come up. */ sleep((caddr_t)&tp->t_rawq, TTIPRI); /* * See if wakeup is due to a false call. */ if (dhumodem[unit]&MODEM_BADCALL){ splx(s); return(EWOULDBLOCK); } /* if we opened "block if in use" and * the terminal was not inuse at that time * but is became "in use" while we were * waiting for carrier then return */ if ((flag & O_BLKINUSE) && (inuse==0) && (tp->t_state&TS_INUSE)) { splx(s); return(EALREADY); } } } splx(s); /* * 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; return ((*linesw[tp->t_line].l_open)(dev, tp));}/* * Close a DHU11 line. *//*ARGSUSED*/dhuclose(dev, flag) dev_t dev; int flag;{ register struct tty *tp; register int unit, s; register struct dhudevice *addr; register int dhu; extern int wakeup(); int turnoff = 0; unit = minor(dev); dhu = unit >> 4; tp = &dhu11[unit]; addr = (struct dhudevice *)tp->t_addr; tp->t_state |= TS_CLOSING; if (tp->t_line) (*linesw[tp->t_line].l_close)(tp); if ((tp->t_cflag&HUPCL) || (tp->t_state&TS_ISOPEN)==0) { s = spltty(); turnoff++; addr->csr.low = DHU_RIE|(unit & LINEMASK); WBFLUSH(); addr->lnctrl &= ~(DHU_DTR|DHU_RTS); /* turn off DTR */ WBFLUSH(); tp->t_state &= ~TS_CARR_ON; /* prevents recv intr. timeouts */ if ((tp->t_cflag & CLOCAL) == 0) {#ifdef DHUDEBUG if (dhudebug) mprintf("dhuclose: DTR drop line=%d, state=%x, pid=%d\n", unit, tp->t_state, u.u_procp->p_pid);#endif /* * Wait an additional 5 seconds for DSR to drop if * the DSR signal is being watched. */ if (dhudsr && (addr->fun.fs.stat&DHU_DSR)) { timeout(wakeup, (caddr_t) &tp->t_dev, 5*hz); sleep((caddr_t)&tp->t_dev, PZERO-10); } timeout(wakeup, (caddr_t) &tp->t_dev, hz/5); sleep((caddr_t)&tp->t_dev, PZERO-10); } splx(s); }#ifdef DHUDEBUG if (dhudebug) mprintf("dhuclose: line=%d, state=%x, pid=%d\n", unit, tp->t_state, u.u_procp->p_pid);#endif dhusoftCAR[dhu] &= ~(1<<(unit&LINEMASK)); dhusoftCAR[dhu] |= (1<<(unit&LINEMASK)) & dhudefaultCAR[dhu]; ttyclose(tp); /* remember this will clear out t_state */ if (turnoff) { /* we have to do this after the ttyclose so that output * can still drain */ s = spltty(); addr->csr.low = DHU_RIE|(unit & LINEMASK); WBFLUSH(); addr->lnctrl = NULL; /* turn off interrupts also */ WBFLUSH(); splx(s); } dhumodem[unit] = 0; tty_def_close(tp); wakeup((caddr_t)&tp->t_rawq); /* wake up anyone in dhuopen */ }dhuread(dev, uio) dev_t dev; struct uio *uio;{ register struct tty *tp = &dhu11[minor(dev)]; return ((*linesw[tp->t_line].l_read)(tp, uio));}dhuwrite(dev, uio) dev_t dev; struct uio *uio;{ register struct tty *tp = &dhu11[minor(dev)]; return ((*linesw[tp->t_line].l_write)(tp, uio));}/* * DHU11 receiver interrupt. */dhurint(dhu) int dhu; /* module number */{ register struct tty *tp; register int c, flg; register struct dhudevice *addr; struct tty *tp0; register struct uba_device *ui; int overrun = 0; register u_char *modem0, *modem; int unit; int modem_cont; ui = dhuinfo[dhu]; if (ui == 0 || ui->ui_alive == 0) return; addr = (struct dhudevice *)ui->ui_addr; tp0 = &dhu11[dhu<<4]; /* first tty structure that corresponds * to this dhu11 module */ modem0 = &dhumodem[dhu<<4]; /* * Loop fetching characters from receive fifo for this * dhu until there are no more in the receive fifo. */ while ((c = addr->run.rbuf) < 0) { /* if c < 0 then data valid is set */ unit = (c>>8)&LINEMASK; tp = tp0 + unit; /* tty struct for this line */ flg = tp->t_iflag; modem = modem0 + unit;#ifdef DHUDEBUG if (dhudebug > 7) mprintf("dhurint0: c=%x, tp=%x\n", c, tp);#endif /* check for modem transitions */ if ((c & DHU_STAT)==DHU_STAT) { if (c & DHU_DIAG) /* ignore diagnostic info */ continue;#ifdef DHUDEBUG if (dhudebug > 4) mprintf("dhurint: c=%x, tp=%x\n", c, tp);#endif /* * Don't respond to modem status changes on a * direct connect line. Actually there should not * be any modem status interrupts on a direct connect * line because the link type is set to non-modem. */ if (tp->t_cflag & CLOCAL) continue; /* set to line #*/ addr->csr.low = DHU_RIE|(unit & LINEMASK); WBFLUSH(); modem_cont = 0; /* examine modem status */ /* * Drop DTR immediately if DSR has gone away. * If really an active close then do not * send signals. */ if ((addr->fun.fs.stat&DHU_DSR)==0) { if (tp->t_state&TS_CLOSING) { untimeout(wakeup, (caddr_t) &tp->t_dev); wakeup((caddr_t) &tp->t_dev); continue; } if (tp->t_state&TS_CARR_ON) {#ifdef DHUDEBUG if (dhudebug) mprintf("dhurint: DSR dropped,line=%d\n",unit);#endif DHUDEBUG /* * Only drop if DSR is being followed. */ if (dhudsr) { dhu_tty_drop(tp); /* * Moved the continue here, so * that if both DSR & CD change * in same interval, we'll see * both. */ continue; } } } /* * 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->fun.fs.stat&DHU_CD)==0){ if ( *modem & MODEM_CD) { /* only start timer once */#ifdef DHUDEBUG if (dhudebug) mprintf("dhurint, cd_drop, tp=%x\n", tp);#endif DHUDEBUG *modem &= ~MODEM_CD; dhutimestamp[minor(tp->t_dev)] = time; timeout(dhu_cd_drop, tp, hz*dhucdtime); 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(dhu_cd_drop, tp); if (dhu_cd_down(tp)) { /* drop connection */ dhu_tty_drop(tp); } *modem |= MODEM_CD; modem_cont = 1; } /* CTS flow control check */ if (tp->t_state&TS_CARR_ON) if ((addr->fun.fs.stat&DHU_CTS)==0) { tp->t_state |= TS_TTSTOP; *modem &= ~MODEM_CTS;#ifdef DHUDEBUG if (dhudebug) mprintf("dhurint: CTS stop, line=%d\n", unit);#endif DHUDEBUG dhustop(tp, 0); continue; } else if ((*modem&MODEM_CTS)==0) { tp->t_state &= ~TS_TTSTOP; *modem |= MODEM_CTS;#ifdef DHUDEBUG if (dhudebug) mprintf("dhurint: CTS start, line=%d\n", unit);#endif DHUDEBUG dhustart(tp); continue; } /* * Avoid calling dhu_start_tty for a CD transition if * the connection has already been established. */ if (modem_cont) continue; /* * If 500 ms timer has not expired then dont * check anything yet. * Check to see if DSR|CTS|CD are asserted. * If so we have a live connection. * If DSR is set for the first time we allow * 30 seconds for a live connection. * * * 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 && (*modem&MODEM_DSR_START)==0) dhu_start_tty(tp); else if ((addr->fun.fs.stat&DHU_DSR) && (*modem&MODEM_DSR)==0) { *modem |= (MODEM_DSR_START|MODEM_DSR); /* * we should not look for CTS|CD for * about 500 ms. */ timeout(dhu_dsr_check, tp, hz*30); timeout(dhu_dsr_check, tp, hz/2); } } /* * Ignore DSR. */ else { if ((addr->fun.fs.stat&(DHU_CD|DHU_CTS))==(DHU_CD|DHU_CTS)) dhu_start_tty(tp); } /* * Examination of modem status character is complete. * Go back for the next character to avoid passing this * status info in the receiver buffer back to the user * as a valid character. */ continue; }#ifndef PORTSELECTOR if ((tp->t_state&TS_ISOPEN)==0) {#else if ((tp->t_state&(TS_ISOPEN|TS_WOPEN))==0) {#endif wakeup((caddr_t)tp); continue; }/* This code handles the following termio input flags. Also * listed is what the default should be for propper Ultrix * backward compatibility. * * IGNBRK FALSE * BRKINT TRUE * IGNPAR TRUE * PARMRK FALSE * INPCK TRUE * ISTRIP TRUE */ /* DHU_FERR is interpreted as a break */ if (c & DHU_FERR) { /* * If configured for trusted path, initiate * trusted path handling. */ if (do_tpath) { tp->t_tpath |= TP_DOSAK; (*linesw[tp->t_line].l_rint)(c, tp); break; } if (flg & IGNBRK) continue; if (flg & BRKINT) {#ifdef DHUDEBUG if (dhudebug) mprintf("dhurint: BREAK RECEIVED, tp =%x\n", tp);#endif DHUDEBUG if ((tp->t_lflag_ext & PRAW) && (tp->t_line != TERMIODISC)) c = 0; else { ttyflush(tp, FREAD|FWRITE);#ifdef DHUDEBUG if (dhudebug) mprintf("sending signal to tp->t_pgrp = %d\n", tp->t_pgrp);#endif DHUDEBUG gsignal(tp->t_pgrp, SIGINT); continue; } } /* * TERMIO: If neither IGNBRK or BRKINT is set, a * break condition is read as a single '\0',
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -