📄 dmf.c
字号:
while ((tp->t_state & TS_CARR_ON) == 0) { tp->t_state |= TS_WOPEN; inuse = tp->t_state&TS_INUSE; sleep((caddr_t)&tp->t_rawq, TTIPRI); /* * See if wakeup was due to a false call. */ if (dmfmodem[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); } } /* * 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; splx(s); return ((*linesw[tp->t_line].l_open)(dev, tp));}/* * Close a DMF32 line. *//*ARGSUSED*/dmfclose(dev, flag) dev_t dev; int flag;{ register struct tty *tp; register unit; register dmf, s; register struct dmfdevice *addr; unit = minor(dev); if(unit & 0200) return(dmflclose(dev,flag)); dmf = unit >> 3; tp = &dmf_tty[unit]; if (tp->t_line) (*linesw[tp->t_line].l_close)(tp); (void) dmfmctl(unit, DMF_BRK, DMBIC); if ((tp->t_cflag&HUPCL) || (tp->t_state&TS_ISOPEN)==0) { (void) dmfmctl(unit, DMF_OFF, DMSET); tp->t_state &= ~TS_CARR_ON; /* prevents recv intr. timeouts */ if ((tp->t_cflag & CLOCAL) == 0) { /* * Raise spl to insure that no timeouts expire before * the sleep is posted (in the event of interrupt). */ s = spl5(); /*drop DTR for at least a half sec. if modem line*/ tp->t_state |= TS_CLOSING; /* wait for DSR to drop */ addr = (struct dmfdevice *)tp->t_addr; addr->dmfcsr = DMF_IE | DMFIR_TBUF | (unit&LINEMASK); /* * If the DSR signal is being followed, give the modem * at most 5 seconds to drop. */ if (dmfdsr && (addr->dmfrms&DMF_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); tp->t_state &= ~(TS_CLOSING); wakeup((caddr_t)&tp->t_rawq); splx(s); } } dmfsoftCAR[dmf] &= ~(1<<(unit&LINEMASK)); dmfsoftCAR[dmf] |= (1<<(unit&LINEMASK)) & dmfdefaultCAR[dmf]; ttyclose(tp); dmfmodem[unit] = 0; tty_def_close(tp);}dmfread(dev, uio) dev_t dev; struct uio *uio;{ register struct tty *tp; if(minor(dev)&0200) return(ENXIO); tp = &dmf_tty[minor(dev)]; return ((*linesw[tp->t_line].l_read)(tp, uio));}dmfwrite(dev, uio) dev_t dev; struct uio *uio;{ register struct tty *tp; if(minor(dev)&0200) return(dmflwrite(dev,uio)); tp = &dmf_tty[minor(dev)]; return ((*linesw[tp->t_line].l_write)(tp, uio));}/* * DMF32 receiver interrupt. */dmfrint(dmf) int dmf;{ register struct tty *tp; register c, flg; register struct dmfdevice *addr; register struct tty *tp0; struct uba_device *ui; register int line; int overrun = 0; register u_char *modem0, *modem; int modem_cont; ui = dmfinfo[dmf]; if (ui == 0 || ui->ui_alive == 0) return; addr = (struct dmfdevice *)ui->ui_addr; tp0 = &dmf_tty[dmf<<3]; modem0 = &dmfmodem[dmf<<3]; /* * Loop fetching characters from the silo for this * dmf until there are no more in the silo. */ while ((c = addr->dmfrbuf) < 0) { line = (c>>8)&LINEMASK; tp = tp0 + line; flg = tp->t_iflag; modem = modem0 + line;#ifdef DMFDEBUG if (dmfdebug>1) mprintf("dmfrint: tp=%x, c=%x\n", tp, c);#endif /* check for modem transitions */ if (c & DMF_DSC) {#ifdef DMFDEBUG if (dmfdebug) mprintf("dmfrint: DSC, tp=%x, rms=%x\n", tp, addr->dmfrms);#endif if (tp->t_cflag & CLOCAL) continue; addr->dmfcsr = DMF_IE | DMFIR_TBUF | line; modem_cont = 0; /* * Drop DTR immediately if DSR gone away. * If really an active close then do not * send signals. */ if ((addr->dmfrms&DMF_DSR)==0) { if (tp->t_state&TS_CLOSING) { untimeout(wakeup, (caddr_t) &tp->t_dev); wakeup((caddr_t) &tp->t_dev);#ifdef DMFDEBUG if (dmfdebug) mprintf("dmfrint: dsr closing down, tp=%x\n", tp);#endif continue; } if (tp->t_state&TS_CARR_ON) { /* * Only drop line if DSR is being followed. */ if (dmfdsr) { dmf_tty_drop(tp); 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->dmfrms&DMF_CAR)==0) { if (*modem & MODEM_CD) { /* only start timer once */ if (dmfdebug) mprintf("dmfrint, cd_drop, tp=%x\n", tp); *modem &= ~MODEM_CD; dmftimestamp[minor(tp->t_dev)] = time; timeout(dmf_cd_drop, tp, hz*dmfcdtime); 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(dmf_cd_drop, tp); if (dmf_cd_down(tp)) /* drop connection */ dmf_tty_drop(tp); *modem |= MODEM_CD; modem_cont = 1; } /* CTS flow control check */ if (tp->t_state&TS_CARR_ON) if ((addr->dmfrms&DMF_CTS)==0) { tp->t_state |= TS_TTSTOP; *modem &= ~MODEM_CTS; if (dmfdebug) mprintf("dmfrint: CTS stop, tp=%x\n", tp); dmfstop(tp, 0); continue; } else if ((*modem&MODEM_CTS)==0) { tp->t_state &= ~TS_TTSTOP; *modem |= MODEM_CTS; if (dmfdebug) mprintf("dmfrint: CTS start, tp=%x\n", tp); dmfstart(tp); continue; } /* * Avoid calling dmfstart due to a carrier transition. */ 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 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 (dmfdsr) { if ((addr->dmfrms&DMF_XMIT)==DMF_XMIT && (*modem&MODEM_DSR_START)==0) dmf_start_tty(tp); else if ((addr->dmfrms&DMF_DSR) && (*modem&MODEM_DSR)==0) { *modem |= (MODEM_DSR_START|MODEM_DSR); /* * we should not look for CTS|CD for * about 500 ms. */ timeout(dmf_dsr_check, tp, hz*30); timeout(dmf_dsr_check, tp, hz/2); } } /* * Ignore DSR */ else if ((addr->dmfrms & DMF_NODSR) == DMF_NODSR) dmf_start_tty(tp); continue; } /* end of modem transition tests */ if ((tp->t_state&TS_ISOPEN)==0) { wakeup((caddr_t)&tp->t_rawq); 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 */ /* DMF_FE is interpreted as a break */ if (c & DMF_FE) { /* * 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 DMFDEBUG if (dmfdebug) mprintf("dmfrint: BREAK RECEIVED\n");#endif DMFDEBUG if ((tp->t_lflag_ext & PRAW) && (tp->t_line != TERMIODISC)) c = 0; else { ttyflush(tp, FREAD|FWRITE);#ifdef DMFDEBUG if (dmfdebug) mprintf("sending signal to tp->t_pgrp = %d\n", tp->t_pgrp);#endif DMFDEBUG gsignal(tp->t_pgrp, SIGINT); continue; } } /* * TERMIO: If neither IGNBRK or BRKINT is set, a * break condition is read as a single '\0', * or if PARMRK is set as '\377','\0,'\0'. */ else { if (flg & PARMRK){ (*linesw[tp->t_line].l_rint)(0377,tp); (*linesw[tp->t_line].l_rint)(0,tp); } c = 0; } } /* Parity Error */ else if (c & DMF_PE){ /* * If input parity checking is not enabled, clear out * parity error in this character. */#ifdef DMFDEBUG if (dmfdebug > 1) mprintf("dmfrint: Parity Error\n");#endif DMFDEBUG if ((flg & INPCK) == 0) c &= ~DMF_PE; else { if (flg & IGNPAR) continue; /* If PARMRK is set, return a character with * framing or parity errors as a 3 character * sequence (0377,0,c). */ if (flg & PARMRK){ (*linesw[tp->t_line].l_rint)(0377,tp); (*linesw[tp->t_line].l_rint)(0,tp); } /* * TERMIO: If neither PARMRK or IGNPAR is set, a * parity error is read as a single '\0'. */ else c = 0; } } /* SVID does not say what to do with overrun errors */ if ((c & DMF_DO) && overrun == 0) { printf("dmf%d: recv. fifo overflow\n", dmf); overrun = 1; } if (flg & ISTRIP){ c &= 0177; } else { c &= 0377; /* If ISTRIP is not set a valid character of 377 * is read as 0377,0377 to avoid ambiguity with * the PARMARK sequence. */ if ((c == 0377) && (tp->t_line == TERMIODISC) && (flg & PARMRK)) (*linesw[tp->t_line].l_rint)(0377,tp); }#if NHC > 0 if (tp->t_line == HCLDISC) { HCINPUT(c, tp); } else#endif (*linesw[tp->t_line].l_rint)(c, tp); }}/* * Ioctl for DMF32. *//*ARGSUSED*/dmfioctl(dev, cmd, data, flag) dev_t dev; register int cmd; caddr_t data; int flag;{ register int unit = minor(dev); register struct dmfdevice *dmfaddr; register struct tty *tp; register int dmf; register int s; struct uba_device *ui; struct dmf_softc *sc; struct devget *devget; int error; if(unit & 0200) return (ENOTTY); tp = &dmf_tty[unit]; dmf = unit >> 3; ui = dmfinfo[dmf]; sc = &dmf_softc[ui->ui_unit]; error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); if (error >= 0) return (error); error = ttioctl(tp, cmd, data, flag); if (error >= 0) { /* * If the call is to set terminal attributes which are * represented in the device's line parameter register then * call the param routine to update the device registers. */ switch(cmd) { case TCSANOW: /* POSIX termios */ case TCSADRAIN: /* POSIX termios */ case TCSAFLUSH: /* POSIX termios */ case TCSETA: /* SVID termio */ case TCSETAW: /* SVID termio */ case TCSETAF: /* SVID termio */ case TIOCSETP: /* Berkeley sgttyb */ case TIOCSETN: /* Berkeley sgttyb */ case TIOCLBIS: /* Berkeley lmode */ case TIOCLBIC: /* Berkeley lmode */ case TIOCLSET: /* Berkeley lmode */ case TIOCLGET: /* Berkeley lmode */ dmfparam(unit); break; } return (error); } switch (cmd) { case TIOCSBRK:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -