📄 scc.c
字号:
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; default: if (u.u_procp->p_progenv == A_POSIX) return (EINVAL); return (ENOTTY); } return (0);} dmtoscc(bits) register int bits;{ register int b; b = (bits >>1) & 0370; if (bits & SML_ST) b |= DC_ST; if (bits & SML_RTS) b |= DC_RTS; if (bits & SML_DTR) b |= DC_DTR; if (bits & SML_LE) b |= DC_LE; return(b);}scctodm(bits) register int bits;{ register int b; b = (bits << 1) & 0360; if (bits & DC_DSR) b |= SML_DSR; if (bits & DC_DTR) b |= SML_DTR; if (bits & DC_ST) b |= SML_ST; if (bits & DC_RTS) b |= SML_RTS; return(b);}sccparam(unit) register int unit;{ register struct scc_softc *sc = sccsc; register struct tty *tp; register struct scc_reg *rsp, *rsp0; register struct scc_saved_reg *ssp, *ssp0; register int rxen = 1, s, status; register int timo; s = spltty(); tp = &scc_tty[unit]; if (tp->t_state & TS_BUSY) { tp->t_state |= TS_NEED_PARAM; return; } rsp = sc->sc_regs[unit]; SCC_READ(rsp, SCC_RR1, status); /* read status */ for(timo=10000; timo > 0; --timo) { if (status & SCC_RR1_ALL_SENT) break; else { SCC_READ(rsp, SCC_RR1, status); } } ssp = &sc->sc_saved_regs[unit]; 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))) { SCC_CLR_DTR(unit); SCC_CLR_RTS(unit); SCC_CLR_SS(unit); splx(s); return; } /* * If diagnostic console on line 3, * line parameters must be: 9600 BPS, 8 BIT, NO PARITY, 1 STOP. */ if ((unit == 3) && (consDev != GRAPHIC_DEV)) { /* * do nothing here because line 3 parameters have already * been set in scc_cons_init. */ ; } else if (unit == 2 || unit == 3) { /* * Set parameters in accordance with user specification. */ ssp->wr4 = SCC_WR4_CLOCK16; /* * Berkeley-only dinosaur */ if (tp->t_line != TERMIODISC) { if ((tp->t_cflag_ext&CBAUD) == B110) tp->t_cflag |= CSTOPB; } /* * Set device registers according to the specifications of the * termio structure. */ if ((tp->t_cflag & CREAD) == 0) /* disable receiver */ rxen = 0; if (tp->t_cflag & CSTOPB) ssp->wr4 |= SCC_WR4_TWOSB; else ssp->wr4 |= SCC_WR4_ONESB; if (tp->t_cflag & PARENB) { if ((tp->t_cflag & PARODD) == 0) /* set even */ ssp->wr4 |= (SCC_WR4_EPAR | SCC_WR4_PENABLE); else /* else set odd */ ssp->wr4 |= SCC_WR4_PENABLE; } SCC_WRITE(rsp, SCC_WR4, ssp->wr4); /* * character size. * clear bits and check for 5, 6, 7 & 8 bits. */ ssp->wr3 &= ~(SCC_WR3_RBITS|SCC_WR3_RXEN); ssp->wr5 &= ~(SCC_WR5_TBITS|SCC_WR5_TXEN); switch(tp->t_cflag&CSIZE) { case CS5: ssp->wr3 |= SCC_WR3_RBITS5; ssp->wr5 |= SCC_WR5_TBITS5; break; case CS6: ssp->wr3 |= SCC_WR3_RBITS6; ssp->wr5 |= SCC_WR5_TBITS6; break; case CS7: ssp->wr3 |= SCC_WR3_RBITS7; ssp->wr5 |= SCC_WR5_TBITS7; break; case CS8: ssp->wr3 |= SCC_WR3_RBITS8; ssp->wr5 |= SCC_WR5_TBITS8; break; } SCC_WRITE(rsp, SCC_WR3, ssp->wr3); SCC_WRITE(rsp, SCC_WR5, ssp->wr5); ssp->wr14 &= ~(SCC_WR14_BRGEN_EN); SCC_WRITE(rsp, SCC_WR14, ssp->wr14); /* WR14 BRG disable */ SCC_WRITE(rsp, SCC_WR12, scc_speeds[tp->t_cflag&CBAUD].baud_lo); SCC_WRITE(rsp, SCC_WR13, scc_speeds[tp->t_cflag&CBAUD].baud_hi); scc_cbaud[unit] = tp->t_cflag&CBAUD; if ((tp->t_cflag & CLOCAL) == 0) sccspeedi(unit); /* check speed indicate */ /* * enable functions */ ssp->wr14 |= SCC_WR14_BRGEN_EN; SCC_WRITE(rsp, SCC_WR14, ssp->wr14); /* WR14 BRG enable */ if (rxen) { ssp->wr3 |= SCC_WR3_RXEN; SCC_WRITE(rsp, SCC_WR3, ssp->wr3); /* WR3 Rx enable */ } ssp->wr5 |= SCC_WR5_TXEN; SCC_WRITE(rsp, SCC_WR5, ssp->wr5); /* WR5 Tx enable */ } splx(s);}/* * scc_dma_xint(unit) - transmit DMA interrupt service routine * * algorithm: * -clear transmit DMA interrupt * -disable transmit DMA for comm. port designated by 'unit' * -same as dcxint with pdma stuff removed and new ndflush: * -get tty for 'unit' * -reset 'unit' to 3 if line 0 is console * -set t_state * -flush 'cc' bytes from output queue * -if we need param, call sccparam * -invoke start routine * */scc_dma_xint(unit) register int unit; { register struct scc_softc *sc = sccsc; register struct tty *tp; register char *ptr; register struct scc_reg *rsp; register int cc; /* must disable the transmit DMA before clearing the interrupt */ IOC_CLR(IOC_SSR, scc_xdma_en[unit]); /* disable transmit DMA */ IOC_WR(IOC_SIR, ~(scc_xint[unit])); /* clear transmit int */ /* read transmit DMA offset */ ptr = (char *)(((sc->ioc_regs[unit]->XDMA_REG) >> 3) & 0xfff); if (ptr == 0) ptr += (u_long)sc->tbuf[unit] + SCC_PAGE_SIZE; else ptr += (u_long)sc->tbuf[unit]; tp = &scc_tty[unit]; if ((consDev != GRAPHIC_DEV) && (unit == 0) && /* ? */ (major(tp->t_dev) == CONSOLEMAJOR)) { unit = 3; } tp->t_state &= ~TS_BUSY; cc = (u_long *)ptr - (u_long *)sc->tptr[unit]; /* cc bytes */ ndflush(&tp->t_outq, cc); /* cc bytes */ if (tp->t_state & TS_NEED_PARAM) { tp->t_state &= ~TS_NEED_PARAM; sccparam(unit); } if (tp->t_line) { (*linesw[tp->t_line].l_start)(tp); } else { sccstart(tp); }}sccstart(tp) register struct tty *tp;{ register struct scc_softc *sc = sccsc; register int cc; int s, unit; register char *bp; register char *cp; register int c_mask; s = spltty(); /* * Do not do anything if currently delaying, or active. Also only * transmit when CTS is up. */ unit = minor(tp->t_dev) & 3; if ((tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) || (((tp->t_cflag & CLOCAL) == 0) && ((tp->t_state&TS_CARR_ON) && (sccmodem[unit]&MODEM_CTS)==0))) goto out; if (tp->t_outq.c_cc <= TTLOWAT(tp)) { if (tp->t_state&TS_ASLEEP) { tp->t_state &= ~TS_ASLEEP; wakeup((caddr_t)&tp->t_outq); } if (tp->t_wsel) { selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); tp->t_wsel = 0; tp->t_state &= ~TS_WCOLL; } } 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)) { cc = ndqb(&tp->t_outq, 0); } else { cc = ndqb(&tp->t_outq, DELAY_FLAG); if (cc == 0) { cc = getc(&tp->t_outq); timeout(ttrstrt, (caddr_t)tp, (cc&0x7f) + 6); tp->t_state |= TS_TIMEOUT; goto out; } } tp->t_state |= TS_BUSY; if ((consDev != GRAPHIC_DEV) && (unit == 0) && /* ? */ (major(tp->t_dev) == CONSOLEMAJOR)) unit = 3; /* * prepare for DMA: * -point cp to first char in clist block, * -point bp to cc words from end of page, * -save bp in scc_softc for use by ndflush. * -using cp and bp, copy cc bytes from clist to * word-aligned DMA page. */ cp = tp->t_outq.c_cf; bp = sc->tbuf[unit] + SCC_PAGE_SIZE - (cc * SCC_WORD); sc->tptr[unit] = bp; /* * need to do the following because when character size is set to five, * the data format allows character sizes of one to five. See SCC * manual. */ if ((tp->t_cflag&CSIZE) == CS5) c_mask = 0x1f; else c_mask = 0xff; while (cc-- > 0) { *(u_short *)bp = (((u_short)*cp++)&c_mask)<<8; bp += SCC_WORD; } /* * set DMA transmit ptr */ sc->ioc_regs[unit]->XDMA_REG = (u_long)(svtophy(sc->tptr[unit]) << 3); IOC_SET(IOC_SSR, scc_xdma_en[unit]); /* enable transmit DMA */ out: splx(s);}sccstop(tp, flag) register struct tty *tp;{ register struct scc_softc *sc = sccsc; register int s, cc; register char *ptr; int unit; /* * If there is a graphics device and the stop call * is for it, pass the call to the graphics device driver. */ unit = minor(tp->t_dev); if ((consDev != GRAPHIC_DEV) && (unit == 0) && /* ? */ (major(tp->t_dev) == CONSOLEMAJOR)) { unit = 3; } if (vs_gdstop && (unit <= 1)) { (*vs_gdstop)(tp, flag); return; } s = spltty(); if (tp->t_state & TS_BUSY) { /* disable transmit DMA */ IOC_CLR(IOC_SSR, scc_xdma_en[unit]); /* * pgt - need to clear transmit int to handle boundary condition, * otherwise scc_dma_xint could be called and queue would be * ndflushed twice */ IOC_WR(IOC_SIR, ~(scc_xint[unit])); /* clear transmit int */ /* line discipline will flush entire queue */ if ((tp->t_state&TS_TTSTOP)==0) { ; } else { /* suspend */ /* read transmit DMA ptr */ ptr = (char *)(((sc->ioc_regs[unit]->XDMA_REG) >> 3) & 0xfff); /* if we made it to a page boundary pointer will be zero */ if (ptr == 0) ptr += (long)(sc->tbuf[unit]) + SCC_PAGE_SIZE ; else ptr += (long)(sc->tbuf[unit]); cc = (u_long *)ptr - (u_long *)sc->tptr[unit]; /* cc bytes */ ndflush(&tp->t_outq, cc); /* cc bytes */ } tp->t_state &= ~TS_BUSY; } splx(s);}sccmctl(dev, bits, how) dev_t dev; int bits, how;{ register struct scc_softc *sc = sccsc; register int unit, mbits; int b, s; unit = minor(dev); if ((unit != 2) && (unit != 3)) return(0); /* only line 2 and 3 has modem control */ s = spltty(); mbits = (SCC_DTR(unit)) ? DC_DTR : 0; mbits |= (SCC_RTS(unit)) ? DC_RTS : 0; mbits |= (SCC_DCD(unit)) ? DC_CD : 0; mbits |= (SCC_DSR(unit)) ? DC_DSR : 0; mbits |= (SCC_CTS(unit)) ? DC_CTS : 0; switch (how) { case DMSET: mbits = bits; break; case DMBIS: mbits |= bits; break; case DMBIC: mbits &= ~bits; break; case DMGET: (void) splx(s); return(mbits); } if (mbits & DC_DTR) { SCC_SET_DTR(unit); SCC_SET_RTS(unit); SCC_SET_SS(unit); } else { SCC_CLR_DTR(unit); SCC_CLR_RTS(unit); SCC_CLR_SS(unit); } (void) splx(s); return(mbits);}scc_ext_rint(i) register i;{ register struct scc_softc *sc = sccsc; register struct tty *tp; register struct scc_reg *rsp; register int brk; tp = &scc_tty[i]; /* * assume break condition will last long enough for it to be processed by * this routine. otherwise, null characters would be DMA'd into the receive * buffer. */ if (i == 2 || i == 3) { rsp = sc->sc_regs[i]; brk = ((rsp->SCC_CMD)>>8) & SCC_RR0_BREAK; /* check if there is a state change in BREAK */ if (brk && !scc_brk[i]) { scc_brk[i] = 1; sccbrkint(i); } else if (!brk && scc_brk[i]) { scc_brk[i] = 0; sccbrkint(i); } else if (brk && scc_brk[i]) { /* * handle the case where successive breaks arrive * need to call brkint twice to handle the termination of an * earlier break and the beginning of the next break */ scc_brk[i] = 0; sccbrkint(i); scc_brk[i] = 1; sccbrkint(i); } } if ((tp->t_cflag & CLOCAL) == 0) { sccspeedi(i); /* check for speed indicate changes */ /* * Drop DTR immediately if DSR has gone away. * If really an active close then do not * send signals. */ if (!(SCC_DSR(i))) { if (tp->t_state&TS_CLOSING) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -