📄 scc.c
字号:
untimeout(wakeup, (caddr_t) &tp->t_dev); wakeup((caddr_t) &tp->t_dev); } if (tp->t_state&TS_CARR_ON) { scc_tty_drop(tp); } } else { /* DSR has come up */ /* * If DSR comes up for the first time we allow * 30 seconds for a live connection. */ if ((sccmodem[i] & MODEM_DSR)==0) { sccmodem[i] |= (MODEM_DSR_START|MODEM_DSR); /* * we should not look for CTS|CD for about * 500 ms. */ timeout(scc_dsr_check, tp, hz*30); scc_dsr_check(tp);} } /* * look for modem transitions in an already * established connection. */ if (tp->t_state & TS_CARR_ON) { if (SCC_DCD(i)) { /* * CD has come up again. * Stop timeout from occurring if set. * If interval is more than 2 secs then * drop DTR. */ if ((sccmodem[i] & MODEM_CD) == 0) { untimeout(scc_cd_drop, tp); if (scc_cd_down(tp)) { /* drop connection */ scc_tty_drop(tp); } sccmodem[i] |= MODEM_CD; } } else { /* * Carrier must be down for greater than * 2 secs before closing down the line. */ if (sccmodem[i] & MODEM_CD) { /* only start timer once */ sccmodem[i] &= ~MODEM_CD; /* * Record present time so that if carrier * comes up after 2 secs, the line will drop. */ scctimestamp[i] = time; timeout(scc_cd_drop, tp, hz * 2); } } /* CTS flow control check */ if (!(SCC_CTS(i))) { /* * Only allow transmission when CTS is set. */ tp->t_state |= TS_TTSTOP; sccmodem[i] &= ~MODEM_CTS; sccstop(tp, 0); } else if (!(sccmodem[i] & MODEM_CTS)) { /* * Restart transmission upon return of CTS. */ tp->t_state &= ~TS_TTSTOP; sccmodem[i] |= MODEM_CTS; sccstart(tp); } } /* * See if a modem transition has occured. If we are waiting * for this signal, cause action to be take via * scc_start_tty. */ if ((SCC_XMIT(i)) && (!(sccmodem[i] & MODEM_DSR_START)) && (!(tp->t_state & TS_CARR_ON))) { scc_start_tty(tp); } }}/* * Note: When a break condition occurs, the SCC chip detects the condition, * sets the BREAK bit and generates an ext/status interrupt. Upon * termination of the break, the receive FIFO will contain a single * NULL character. This NULL character will cause a dma rint. The * Framing Error bit will not be set for this character, but if odd * parity has been selected, the parity error bit will be set. */ sccbrkint(unit) register int unit;{ register struct scc_softc *sc = sccsc; register struct tty *tp; register struct scc_reg *rsp; register struct scc_saved_reg *ssp; register u_short c; register int flg; tp = &scc_tty[unit]; rsp = sc->sc_regs[unit]; ssp = &sc->sc_saved_regs[unit]; c = (unit<<8)| 0x0000; /* * We need to disable both the SCC rint and the IOASIC rdma int * because we just want to read and discard the NULL character * that will be deposited in the receive FIFO upon termination * of the break. */ if (scc_brk[unit]) { ssp->wr1 &= ~SCC_WR1_RINT; /* disable rint on special conditions */ SCC_WRITE(rsp, SCC_WR1, ssp->wr1); IOC_CLR(IOC_SSR, scc_rdma_en[unit]); /* disable rdma */ if ((tp->t_state & TS_ISOPEN) == 0) { /* process break */ wakeup((caddr_t)&tp->t_rawq); return; } flg = tp->t_iflag; if (do_tpath) { tp->t_tpath |= TP_DOSAK; (*linesw[tp->t_line].l_rint)(c, tp); return; } if (flg & IGNBRK) return; if (flg & BRKINT) { if ((tp->t_lflag_ext & PRAW) && (tp->t_line != TERMIODISC)) c = 0; else { ttyflush(tp, FREAD | FWRITE); gsignal(tp->t_pgrp, SIGINT); return; } } else { if (flg & PARMRK){ (*linesw[tp->t_line].l_rint)(0377,tp); (*linesw[tp->t_line].l_rint)(0,tp); } c = 0; } if (flg & ISTRIP){ c &= 0177; } else { c &= 0377; if ((c == 0377) && (tp->t_line == TERMIODISC) && (flg & PARMRK)) (*linesw[tp->t_line].l_rint)(0377,tp); } (*linesw[tp->t_line].l_rint)(c, tp); } else { c = ((rsp->SCC_DATA)>>8)&0xff; /* read NULL character */ IOC_SET(IOC_SSR, scc_rdma_en[unit]); /* enable RDMA */ ssp->wr1 &= ~SCC_WR1_RINT; /* clear rint bits */ ssp->wr1 |= SCC_WR1_RINT_SPC; /* enable rint */ SCC_WRITE(rsp, SCC_WR1, ssp->wr1); }}int sccputc();int sccgetc();sccputc(c) register int c;{ if (consDev == GRAPHIC_DEV) { if ( v_consputc ) { (*v_consputc) (c); if ( c == '\n' ) (*v_consputc)( '\r' ); return; } } scc_putc(3, c); if ( c == '\n') scc_putc(3, '\r');}/* * polled-mode DMA: need to do this because SCC can not be touched in * scc_putc. */scc_putc(unit, c) int unit; register int c;{ register struct scc_softc *sc = sccsc; register int s; register struct scc_reg *rsp; char *ptr; int intr_pending = 0, save_word; u_int sir, save_SSR, save_xmt_ptr; if (unit == 2 || unit == 3) { /* set pointer to be the word before the end of the page */ ptr = sc->tbuf[unit] + SCC_PAGE_SIZE - SCC_WORD; /* rpbfix : do we need to be at extreme ??? */ s = splextreme(); IOC_RD(IOC_SSR, save_SSR); /* save copy of SSR */ IOC_WR(IOC_SSR, (save_SSR & ~(scc_xdma_en[unit]))); /* disable XMT DMA */ IOC_RD(IOC_SIR, sir); if (sir & scc_xint[unit]) { intr_pending = 1; IOC_WR(IOC_SIR, ~(scc_xint[unit])); } else { save_xmt_ptr = sc->ioc_regs[unit]->XDMA_REG; save_word = *(int *)ptr; } *(u_short *)ptr = ((u_short)c) << 8; sc->ioc_regs[unit]->XDMA_REG = (u_long)(svtophy(ptr) << 3); IOC_SET(IOC_SSR, scc_xdma_en[unit]); IOC_RD(IOC_SIR, sir); while ((sir & scc_xint[unit]) == 0) IOC_RD(IOC_SIR, sir); if (intr_pending == 0) { IOC_CLR(IOC_SSR, scc_xdma_en[unit]); IOC_WR(IOC_SIR, ~(scc_xint[unit])); sc->ioc_regs[unit]->XDMA_REG = save_xmt_ptr; *(long *)ptr = save_word; IOC_WR(IOC_SSR, save_SSR); } splx(s); } else { s = splhigh(); rsp = sc->sc_regs[unit]; while ((((rsp->SCC_CMD)>>8) & SCC_RR0_TBUF_EMPTY) == 0) ; rsp->SCC_DATA = (c&0xff)<<8; /* output char */ while ((((rsp->SCC_CMD)>>8) & SCC_RR0_TBUF_EMPTY) == 0) ; splx(s); }}/* pgt - new sccgetc() */sccgetc(){ register u_char c; register int line; /* * Line number we expect input from. */ if (consDev == GRAPHIC_DEV) line = 0x0; else line = 0x3; c = scc_getc(line); if (v_consgetc) return ((*v_consgetc)(c & 0xff)); else return (c & 0xff);}scc_getc(unit) int unit;{ register struct scc_softc *sc = sccsc; register u_char c, status; register int timo; register struct scc_reg *rsp; rsp = sc->sc_regs[unit]; SCC_WRITE(rsp, SCC_WR9, 0x00); /* disable MIE ? */ if (unit == 2 || unit == 3) IOC_CLR(IOC_SSR, scc_rdma_en[unit]); /* disable rdma ? */ for(timo=1000000; timo > 0; --timo) { if (((rsp->SCC_CMD)>>8) & SCC_RR0_RCHAR_AVAIL) { SCC_READ(rsp, SCC_RR1, status); c = ((rsp->SCC_DATA)>>8)&0xff; /* read data */ DELAY(50000); if (status & (SCC_RR1_PE | SCC_RR1_DO | SCC_RR1_FE)) continue; break; } } SCC_WRITE(rsp, SCC_WR9, SCC_WR9_MIE); /* enable MIE ? */ if (unit == 2 || unit == 3) IOC_SET(IOC_SSR, scc_rdma_en[unit]); /* enable rdma ? */ if (timo == 0) return(-1); else return(c & 0xff);}scc_mouse_init(){ register struct scc_softc *sc = sccsc; register struct scc_reg *rsp; register struct scc_saved_reg *ssp; register int unit = 1; rsp = sc->sc_regs[unit]; ssp = &sc->sc_saved_regs[unit]; scc_init(unit); /* * enable functions ? */ ssp->wr14 |= SCC_WR14_BRGEN_EN; SCC_WRITE(rsp, SCC_WR14, ssp->wr14); /* WR14 BRG enable */ 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 */}scc_mouse_putc(c)int c;{ scc_putc(1, c);}scc_mouse_getc(){ return (scc_getc(1));}scc_kbd_init(){ register struct scc_softc *sc = sccsc; register struct scc_reg *rsp; register struct scc_saved_reg *ssp; register int unit = 0; rsp = sc->sc_regs[unit]; ssp = &sc->sc_saved_regs[unit]; scc_init(unit); /* * enable functions ? */ ssp->wr14 |= SCC_WR14_BRGEN_EN; SCC_WRITE(rsp, SCC_WR14, ssp->wr14); /* WR14 BRG enable */ 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 */}scc_kbd_putc(c)int c;{ scc_putc(0, c);}scc_kbd_getc(){ return (scc_getc(0));}/* * Modem Control Routines *//* * * Function: * * scc_cd_drop * * Functional description: * * Determine if carrier has dropped. If so call scc_tty_drop to terminate * the connection. * * Arguments: * * register struct tty *tp - terminal pointer ( for terminal attributes ) * * Return value: * * none * */scc_cd_drop(tp) register struct tty *tp;{ register struct scc_softc *sc = sccsc; register int unit; unit = minor(tp->t_dev); if ((tp->t_state & TS_CARR_ON) && (!(SCC_DCD(unit)))) { scc_tty_drop(tp); return; } sccmodem[unit] |= MODEM_CD;}/* * * Function: * * scc_dsr_check * * Functional description: * * DSR must be asserted for a connection to be established. Here we * either start or terminate a connection on the basis of DSR. * * Arguments: * * register struct tty *tp - terminal pointer (for terminal attributes) * * Return value: * * none * */scc_dsr_check(tp) register struct tty *tp;{ register struct scc_softc *sc = sccsc; register int unit; unit = minor(tp->t_dev); if (sccmodem[unit] & MODEM_DSR_START) { sccmodem[unit] &= ~MODEM_DSR_START; /* * since dc7085 chip on PMAX only provides DSR then assume that CD * has come up after 1 sec and start tty. If CD has not * come up the modem should deassert DSR thus closing the line * * On 3max, we look for DSR|CTS|CD before establishing a * connection. */ if (SCC_XMIT(unit)) { scc_start_tty(tp); } return; } if ((tp->t_state&TS_CARR_ON)==0) scc_tty_drop(tp);}/* * * Function: * * scc_cd_down * * Functional description: * * Determine whether or not carrier has been down
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -