📄 sh.c
字号:
* If input parity checking is not enabled, clear out * parity error in this character. */#ifdef SHDEBUG if (shdebug > 1) mprintf("shrint: Parity Error\n");#endif SHDEBUG if ((flg & INPCK) == 0) c &= ~SH_PERR; 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 & SH_OVERR) && overrun == 0) { printf("sh%d: recv. fifo overflow\n", sh); 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 SH. *//*ARGSUSED*/shioctl(dev, cmd, data, flag) dev_t dev; register int cmd; caddr_t data; int flag;{ register int sh, unit; register struct shdevice *addr; register struct tty *tp; register int s; struct uba_device *ui; struct sh_softc *sc; struct devget *devget; int error; unit = minor(dev); tp = &sh_tty[unit]; sh = unit >> 3; /* module number */ ui = shinfo[sh]; sc = &sh_softc[sh]; 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 */ shparam(unit); break; } return (error); } addr = (struct shdevice *)tp->t_addr;#ifdef SHDEBUG if (shdebug) mprintf("shioctl: unit=%d, cmd=%d\n", unit, cmd&0xff);#endif switch (cmd) { case TIOCSBRK: s = spl5(); addr->csr.low = SH_RIE|(unit & LINEMASK); sh_softcsr = SH_RIE|(unit & LINEMASK); addr->lnctrl |= SH_BREAK; splx(s); break; case TIOCCBRK: s = spl5(); addr->csr.low = SH_RIE|(unit & LINEMASK); sh_softcsr = SH_RIE|(unit & LINEMASK); addr->lnctrl &= ~SH_BREAK; splx(s); break; /* next 2 allowed whether or not we have modem cntl */ case TIOCSDTR: s = spl5(); addr->csr.low = SH_RIE|(unit & LINEMASK); sh_softcsr = SH_RIE|(unit & LINEMASK); addr->lnctrl |= (SH_DTR|SH_RTS); splx(s); break; case TIOCCDTR: s = spl5(); addr->csr.low = SH_RIE|(unit & LINEMASK); sh_softcsr = SH_RIE|(unit & LINEMASK); addr->lnctrl &= ~(SH_DTR|SH_RTS); splx(s); break; /* handle maintenance mode */ case TIOCSMLB: if (u.u_uid) return(EPERM); s=spl5(); addr->csr.low = SH_RIE|(unit&LINEMASK ); /*enable interrupts*/ sh_softcsr = SH_RIE|(unit&LINEMASK ); /*enable interrupts*/ addr->lnctrl |= (SH_MAINT); splx(s); break; case TIOCCMLB: if (u.u_uid) return(EPERM); s=spl5(); addr->csr.low = SH_RIE|(unit & LINEMASK); sh_softcsr = SH_RIE|(unit & LINEMASK); addr->lnctrl &= ~(SH_MAINT); splx(s); break; case TIOCNMODEM: /* ignore modem status */ /* allowed whether or not modem cntl available */ s = spl5(); shsoftCAR[sh] |= (1<<(unit&LINEMASK)); if (*(int *)data) /* make mode permanent */ shdefaultCAR[sh] |= (1<<(unit&LINEMASK)); tp->t_state |= TS_CARR_ON; addr->csr.low = SH_RIE|(unit & LINEMASK); sh_softcsr = SH_RIE|(unit & LINEMASK); addr->lnctrl &= ~(SH_MODEM); shmodem[unit] = MODEM_CTS|MODEM_CD|MODEM_DSR; tp->t_cflag |= CLOCAL; /* Map to termio */ splx(s); break; case TIOCMODEM: /* dont ignore modem status */ s = spl5(); addr->csr.low = SH_RIE|(unit & LINEMASK); sh_softcsr = SH_RIE|(unit & LINEMASK); if ((addr->fun.fs.stat&SH_MSTAT) == 0) { /* have modem cntl */ shsoftCAR[sh] &= ~(1<<(unit&LINEMASK)); if (*(int *)data) /* make mode permanent */ shdefaultCAR[sh] &= ~(1<<(unit&LINEMASK)); addr->lnctrl |= SH_MODEM; /* * If shdsr is set look for DSR|CTS|CD, otherwise look * for CD|CTS only. */ if ((shdsr && ((addr->fun.fs.stat&SH_XMIT)==SH_XMIT)) || ((shdsr == 0) && ((addr->fun.fs.stat&SH_NODSR)==SH_NODSR))) { tp->t_state |= TS_CARR_ON; tp->t_state &= ~TS_ONDELAY; shmodem[unit] = MODEM_CTS|MODEM_CD|MODEM_DSR; } else { tp->t_state &= ~(TS_CARR_ON); shmodem[unit] &= ~(MODEM_CTS|MODEM_CD|MODEM_DSR); } } tp->t_cflag &= ~CLOCAL; /* Map to termio */ splx(s); break; case TIOCWONLINE: s = spl5(); addr->csr.low = SH_RIE|(unit & LINEMASK); sh_softcsr = SH_RIE|(unit & LINEMASK); if ((addr->fun.fs.stat&SH_MSTAT) == 0) { /* have modem cntl */ /* * If shdsr is set look for DSR|CTS|CD, otherwise look * for CD|CTS only. */ if ((shdsr && ((addr->fun.fs.stat&SH_XMIT)==SH_XMIT)) || ((shdsr == 0) && ((addr->fun.fs.stat&SH_NODSR)==SH_NODSR))) { tp->t_state |= TS_CARR_ON; tp->t_state &= ~TS_ONDELAY; shmodem[unit] = MODEM_CTS|MODEM_CD|MODEM_DSR; } else while ((tp->t_state & TS_CARR_ON) == 0) sleep((caddr_t)&tp->t_rawq, TTIPRI); } splx(s); break; /* next 4 allowed whether or not we have modem cntl */ case TIOCMGET: s = spl5(); addr->csr.low = SH_RIE|(unit & LINEMASK); sh_softcsr = SH_RIE|(unit & LINEMASK); *(int *)data = shtodm(addr->lnctrl,addr->fun.fs.stat); splx(s); break; case TIOCMSET: s = spl5(); addr->csr.low = SH_RIE|(unit & LINEMASK); sh_softcsr = SH_RIE|(unit & LINEMASK); addr->lnctrl = dmtosh(*(int *)data); splx(s); break; case TIOCMBIS: s = spl5(); addr->csr.low = SH_RIE|(unit & LINEMASK); sh_softcsr = SH_RIE|(unit & LINEMASK); addr->lnctrl |= dmtosh(*(int *)data); splx(s); break; case TIOCMBIC: s = spl5(); addr->csr.low = SH_RIE|(unit & LINEMASK); sh_softcsr = SH_RIE|(unit & LINEMASK); addr->lnctrl &= ~(dmtosh(*(int *)data)); splx(s); break; case DEVIOCGET: /* device status */ devget = (struct devget *)data; bzero(devget,sizeof(struct devget)); s = spl5(); addr->csr.low = SH_RIE|(unit & LINEMASK); sh_softcsr = SH_RIE|(unit & LINEMASK); if ((addr->fun.fs.stat&SH_MSTAT) == 0) { /* have modem cntl */ sc->sc_category_flags[unit&LINEMASK] |= DEV_MODEM; if (tp->t_cflag & CLOCAL) sc->sc_category_flags[unit&LINEMASK] &= ~DEV_MODEM_ON; else sc->sc_category_flags[unit&LINEMASK] |= DEV_MODEM_ON; } else sc->sc_category_flags[unit&LINEMASK] &= ~(DEV_MODEM|DEV_MODEM_ON); splx(s); devget->category = DEV_TERMINAL; /* terminal cat.*/ devget->bus = DEV_NB; /* NO bus */ bcopy(DEV_TM_SLE,devget->interface, strlen(DEV_VS_SLU)); /* interface */ bcopy(DEV_UNKNOWN,devget->device, strlen(DEV_UNKNOWN)); /* terminal */ devget->adpt_num = 0; /* NO adapter */ devget->nexus_num = 0; /* fake nexus 0 */ devget->bus_num = 0; /* NO bus */ devget->ctlr_num = sh; /* cntlr number */ devget->slave_num = unit&LINEMASK; /* line number */ bcopy(ui->ui_driver->ud_dname, devget->dev_name, strlen(ui->ui_driver->ud_dname)); /* Ultrix "sh" */ devget->unit_num = unit&LINEMASK; /* sh line? */ devget->soft_count = sc->sc_softcnt[unit&LINEMASK]; /* soft err cnt */ devget->hard_count = sc->sc_hardcnt[unit&LINEMASK]; /* hard err cnt */ devget->stat = sc->sc_flags[unit&LINEMASK]; /* status */ devget->category_stat = sc->sc_category_flags[unit&LINEMASK]; /* cat. stat. */ break; /* * Used to specify that this device has outgoing auto flow control. * Set appropriate bit in lpar. */ case TIOAUTO: /* * Outgoing Auto flow control. * No auto flow control allowed if startc != ^q and startc != * ^s. Most drivers do not allow these chars to be changed. */ if ((tp->t_cflag_ext&PAUTOFLOW) && (tp->t_cc[VSTOP] != CTRL('s')) || (tp->t_cc[VSTART] != CTRL('q'))) tp->t_cflag_ext &= ~PAUTOFLOW; shparam(unit); break; default: if (u.u_procp->p_progenv == A_POSIX) return (EINVAL); return (ENOTTY); } return (0);}shtodm(lnctrl,lstat) register u_short lnctrl; register char lstat;{ register int b = 0; if (lnctrl&SH_RTS) b |= TIOCM_RTS; if (lnctrl&SH_DTR) b |= TIOCM_DTR; if (lstat&SH_CD) b |= TIOCM_CD; if (lstat&SH_CTS) b |= TIOCM_CTS; if (lstat&SH_RING) b |= TIOCM_RI; if (lstat&SH_DSR) b |= TIOCM_DSR; return(b);}dmtosh(bits) register int bits;{ register u_short lnctrl = 0; if (bits&TIOCM_RTS) lnctrl |= SH_RTS; if (bits&TIOCM_DTR) lnctrl |= SH_DTR; return(lnctrl);}/* * Set parameters from open or stty into the SH hardware * registers. */shparam(unit) register int unit;{ register struct tty *tp; register struct shdevice *addr; register int lpar; int tcd, br, i; int s; tp = &sh_tty[unit]; addr = (struct shdevice *)tp->t_addr; /* * Block interrupts so parameters will be set * before the line interrupts. */ s = spl5(); addr->csr.low = SH_RIE|(unit&LINEMASK); sh_softcsr = SH_RIE|(unit&LINEMASK); if ((((tp->t_cflag&CBAUD)==B0) && (u.u_procp->p_progenv != A_POSIX)) || (((tp->t_cflag_ext & CBAUD)==B0) && (u.u_procp->p_progenv == A_POSIX))) { tp->t_cflag |= HUPCL; addr->lnctrl = SH_REN; /*turn off DTR & RTS but leave enabled*/ splx(s); return; } lpar = ((sh_speeds[tp->t_cflag_ext&CBAUD])<<12) | ((sh_speeds[tp->t_cflag&CBAUD])<<8); /* * Berkeley-only dinosaurs */ if (tp->t_line != TERMIODISC) { if ((tp->t_cflag & CBAUD) == B134){ lpar |= SH_BITS6|SH_PENABLE; /* no half duplex on sh11 ? */ tp->t_cflag |= CS6|PARENB; } if ((tp->t_cflag_ext & CBAUD) == B110){ lpar |= SH_TWOSB; tp->t_cflag |= CSTOPB; } } /* * System V termio functionality. * Set device registers according to the specifications of the termio * structure. */ if (tp->t_cflag & CREAD) addr->lnctrl |= SH_REN; else addr->lnctrl &= ~SH_REN; if (tp->t_cflag & CSTOPB) lpar |= SH_TWOSB; else lpar &= ~SH_TWOSB; /* parity is enable */ if (tp->t_cflag & PARENB) { if ((tp->t_cflag & PARODD) == 0) /* set even */ lpar |= SH_PENABLE|SH_EVENPAR; else /* else set odd */ lpar = (lpar | SH_PENABLE)&~SH_EVENPAR; } /* * character size.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -