📄 mdc.c
字号:
if ((dcaddr->dcmsr & DC_XMIT) == DC_XMIT) { tp->t_state &= ~(TS_ONDELAY); tp->t_state |= TS_CARR_ON; mdcmodem[unit] = MODEM_CTS|MODEM_CD|MODEM_DSR; } else { tp->t_state &= ~(TS_CARR_ON); mdcmodem[unit] &= ~(MODEM_CTS|MODEM_CD|MODEM_DSR); } tp->t_cflag &= ~CLOCAL; /* Map to termio */ splx(s); break; case TIOCWONLINE: s = spltty(); /* * See if signals necessary for modem connection are present * * dc7085 chip on PMAX only provides DSR * */ if ((dcaddr->dcmsr & DC_XMIT) == DC_XMIT) { tp->t_state |= TS_CARR_ON; tp->t_state &= ~(TS_ONDELAY); mdcmodem[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; case DEVIOCGET: /* device status */ devget = (struct devget *)data; bzero(devget,sizeof(struct devget)); devget->category = DEV_TERMINAL; /* terminal cat.*/ devget->bus = DEV_NB; /* NO bus */ bcopy(DEV_MF_SLU,devget->interface, strlen(DEV_MF_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 = unit; /* cntlr number */ devget->slave_num = linenum; /* line number */ bcopy("mdc", devget->dev_name, 4); /* Ultrix "mdc" */ devget->unit_num = linenum; /* dc line? */ devget->soft_count = mdc_softc[unit].sc_softcnt[linenum]; /* overrun errs */ devget->hard_count = 0; /* hard err cnt */ devget->stat = 0; devget->category_stat = (DEV_MODEM|DEV_MODEM_ON); if ((unit == NOMODEM_UNIT) || (linenum != MODEM_LINE)) { devget->category_stat &= DEV_MODEM; } if (tp->t_cflag & CLOCAL) { devget->category_stat &= ~DEV_MODEM_ON; } break; default: if (u.u_procp->p_progenv == A_POSIX) return (EINVAL); return (ENOTTY); } return (0);}/* * Part of a worthless generic modem lead handling mechanism. The only 2 bits * here that are of any use are DC_RRTS and DC_RDTR. */dmtomdc(bits) register int bits;{ register int b; b = (bits >>1) & 0370; if (bits & SML_RTS) b |= DC_RRTS; if (bits & SML_DTR) b |= DC_RDTR; return(b);}/* * Part of a worthless generic modem lead handling mechanism. The only 2 bits * here that are of any use are DC_RRTS and DC_RDTR. */mdctodm(bits) register int bits;{ register int b; b = (bits << 1) & 0360; if (bits & DC_DSR) b |= SML_DSR; if (bits & DC_RDTR) b |= SML_DTR; if (bits & DC_RRTS) b |= SML_RTS; return(b);}/* * Set device line parameters. */mdcparam(minor_num) register int minor_num;{ register volatile struct mdz_reg *dcaddr; register struct tty *tp; register u_short lpr; register int unit; register int linenum; unit = minor_num >> LINEBITS; linenum = minor_num & LINEMASK; dcaddr = mdz_regs[unit]; tp = &mdc_tty[minor_num]; /* * Set master scan enable for this line. This also clears out the * receive and transmit interrupt enables which will be conditionally * applied later. Preserve maintenance loopback mode if specified. */ if (dcaddr->dccsr & DC_MAINT) { dcaddr->dccsr = (DC_MSE | DC_MAINT); } else { dcaddr->dccsr = DC_MSE; } /* * Setting a baud rate of 0 closes down a line (environment dependent). * Deassert DTR and RTS to drop the modem connection. */ 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))) { mdcmodem_active &= ~(1 << minor_num); /* * We only have control for DTR and RTS on the modem line. */ if ((unit != NOMODEM_UNIT) && (linenum == MODEM_LINE)) { dcaddr->dctcr &= ~(DC_RDTR | DC_RRTS | DC_RSS); } return; } /* * The console line must be set to 8 bits no parity. The baud * rate may be changed from its default value of 1200 by an * environment variable. May want to make sure the tty struct * gets modified to specify these attributes as well. */ if ((unit == CONSOLE_UNIT) && (linenum == CONSOLE_LINE)) { tp->t_cflag &= ~(CBAUD); tp->t_cflag_ext &= ~(CBAUD); tp->t_cflag |= (console_baud & CBAUD); tp->t_cflag_ext |= (console_baud & CBAUD); dcaddr->dclpr = (linenum | mdc_speeds[console_baud].baud_param | BITS8 | DC_RE); } /* * Set parameters in accordance with user specification. */ else { lpr = (mdc_speeds[tp->t_cflag&CBAUD].baud_param) | (linenum); /* * Berkeley-only dinosaur */ if (tp->t_line != TERMIODISC) { if ((tp->t_cflag_ext&CBAUD) == B110) { lpr |= TWOSB; tp->t_cflag |= CSTOPB; } } /* * Set device registers according to the specifications of the * termio structure. */ if (tp->t_cflag & CREAD) { lpr |= DC_RE; } else { lpr &= ~DC_RE; } if (tp->t_cflag & CSTOPB) { lpr |= TWOSB; } else { lpr &= ~TWOSB; } if (tp->t_cflag & PARENB) { if ((tp->t_cflag & PARODD) == 0) /* set even */ lpr = (lpr | PENABLE)&~OPAR; else /* else set odd */ lpr |= PENABLE|OPAR; } /* * character size. * clear bits and check for 6,7,and 8, else its 5 bits. */ lpr &= ~BITS8; switch(tp->t_cflag&CSIZE) { case CS6: lpr |= BITS6; break; case CS7: lpr |= BITS7; break; case CS8: lpr |= BITS8; break; } dcaddr->dclpr = lpr; } dcaddr->dccsr |= (DC_TIE | DC_RIE); wbflush();}/* * A transmitter ready interrupt has been generated on this unit. This means * that the transmitter buffer for a line is empty and now ready to transmit * a new character. If there are already characters stacked up in the pdma * structure then just stuff the tbuf with the character. Otherwise the * present list of characters is empty so call the xint routine to setup a * new pdma chain if there are any new characters to be transmitted. */_mdcpdma(unit) register int unit;{ register volatile struct mdz_reg *dcaddr; register struct dcpdma *dp; register int linenum; dcaddr = mdz_regs[unit]; linenum = (dcaddr->dccsr >> 8) & LINEMASK; dp = &mdc_pdma[unit][linenum]; if (dp->p_mem == dp->p_end) { mdcxint(unit, linenum); } else { dcaddr->dctbuf = (unsigned char)(*dp->p_mem++); wbflush(); }}/* * A transmitter interrupt has been generated for a line that does not have * a pdma chain setup. Setup the pdma chain and call the start routine to * initiate output. */mdcxint(unit, linenum) register int unit; register int linenum;{ register volatile struct mdz_reg *dcaddr; register struct dcpdma *dp; register struct tty *tp; dcaddr = mdz_regs[unit]; tp = &mdc_tty[linenum + (unit * NDCLINE)];#ifdef DEBUG if (mdcdebug > 4) mprintf("mdcxint: linenum = %d, tp = %x, c_cc = %d\n", linenum, tp, tp->t_outq.c_cc);#endif DEBUG tp->t_state &= ~TS_BUSY; dp = &mdc_pdma[unit][linenum]; if (tp->t_state & TS_FLUSH) { tp->t_state &= ~TS_FLUSH; } else { /* * Remove characters that have already been transmitted from * the tty output queue. Set the p_end and p_mem pointers to * be the same to signify an empty pdma chain. */ ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf); dp->p_end = dp->p_mem = tp->t_outq.c_cf; } if (tp->t_line) { (*linesw[tp->t_line].l_start)(tp); } else { mdcstart(tp); } /* * The BUSY flag will not be set in two cases: * 1. if there are no more chars in the outq OR * 2. there are chars in the outq but tty is in * stopped state. * * Turn off line enable. */ if ((tp->t_state&TS_BUSY) == 0) { dcaddr->dctcr &= ~(1<<linenum); }}/* * Begin transmission on a line. Obtain a count of the number of characters * to be sent. If there are characters to send, update the pdma struct to * point to the beginning of these characters followed by a count. Then set * the transmitter interrupt enable for this line. This will cause an * interrupt when the line is ready to accept a character. The interrupt will * call the mdcxint routine to stuff the character in the transmitter buffer. */mdcstart(tp) register struct tty *tp;{ register volatile struct mdz_reg *dcaddr; register struct dcpdma *dp; register int cc; register int unit, linenum; int s; s = spltty(); linenum = minor(tp->t_dev) & LINEMASK; unit = minor(tp->t_dev) >> LINEBITS; dcaddr = mdz_regs[unit]; /* * Do not do anything if currently delaying, or active. Also only * transmit when CTS is up. */ if ((tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) || (((tp->t_cflag & CLOCAL) == 0) && ((tp->t_state&TS_CARR_ON) && (mdcmodem[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;#ifdef DEBUG if (mdcdebug > 7) { mprintf("mdcstart: linenum = %d, tp = %x, c_cc = %d\n", linenum, tp, tp->t_outq.c_cc); }#endif DEBUG 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; dp = &mdc_pdma[unit][linenum]; dp->p_end = dp->p_mem = tp->t_outq.c_cf; dp->p_end += cc; dcaddr->dccsr |= DC_TIE; dcaddr->dctcr |= (1<<linenum); wbflush();out: splx(s);}mdcstop(tp, flag) register struct tty *tp;{ register struct dcpdma *dp; register int s; register int unit, linenum; unit = minor(tp->t_dev) >> LINEBITS; linenum = minor(tp->t_dev) & LINEMASK; dp = &mdc_pdma[unit][linenum]; s = spltty(); if (tp->t_state & TS_BUSY) { dp->p_end = dp->p_mem; if ((tp->t_state&TS_TTSTOP)==0) tp->t_state |= TS_FLUSH; } splx(s);}/* * This routine is part of a scheme to provide a generic modem control * interface. Strictly speaking it is not supported and is more bother than * it is worth. This routine reads the status of the present modem control * leads and represents them generically in the mbits return value. */mdcmctl(dev, bits, how) dev_t dev; int bits, how;{ register volatile struct mdz_reg *dcaddr; register int unit, linenum, mbits; register int b, s; unit = minor(dev) >> LINEBITS; dcaddr = mdz_regs[unit]; linenum = minor(dev) & LINEMASK; if ((unit == NOMODEM_UNIT) || (linenum != MODEM_LINE)) return(0); s = spltty(); mbits = (dcaddr->dctcr & DC_RDTR) ? SML_DTR : 0; mbits |= (dcaddr->dctcr & DC_RRTS) ? SML_RTS : 0; mbits |= (dcaddr->dcmsr & DC_CD) ? SML_CAR : 0; mbits |= (dcaddr->dcmsr & DC_DSR) ? SML_DSR : 0; mbits |= (dcaddr->dcmsr & DC_CTS) ? SML_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 & SML_DTR) { dcaddr->dctcr |= (DC_RDTR | DC_RRTS); } else { dcaddr->dctcr &= ~(DC_RDTR | DC_RRTS | DC_RSS); } wbflush(); (void) splx(s); return(mbits);}#ifdef DEBUGint mdcscan_ctr = 1;#endif DEBUG/* * The DC chip does not interrupt on modem transitions. For this reason a * scanner routine is needed to be called frequently to check the status of * the modem control leads and to react to changes of these leads. */mdcscan(){ register volatile struct mdz_reg *dcaddr; register struct tty *tp; register int unit; register int linenum; register u_short dcscan_modem; for (unit = 0; unit < nMDC; unit++) { if (unit != NOMODEM_UNIT) { /* * Obtain a copy of the modem status register. If the value has not * changed since the last iteration then there is no work to be done * here. */ dcaddr = mdz_regs[unit];#ifdef DEBUG if (mdcdebug > 5) { if (mdcscan_ctr++ == 45) { cprintf("dcscan: "); PRINT_SIGNALS(dcaddr); mdcscan_ctr = 1; } }#endif DEBUG dcscan_modem = dcaddr->dcmsr; if (dcscan_modem != mdcscan_previous[unit]) { tp = &mdc_tty[MODEM_LINE + (unit * NDCLINE)]; if ((tp->t_cflag & CLOCAL) == 0) { /* * Drop DTR immediately if DSR has gone away. * If really an active close then do not * send signals. */ if (!(dcscan_modem & DC_DSR)) { if (tp->t_state&TS_CLOSING) { untimeout(wakeup, (caddr_t) &tp->t_dev); wakeup((caddr_t) &tp->t_dev); } if (tp->t_state&TS_CARR_ON) { mdc_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 ((mdcmodem[unit] & MODEM_DSR)==0) { mdcmodem[unit] |= (MODEM_DSR_START|MODEM_DSR); /* * we should not look for CTS|CD for about * 500 ms. */ timeout(mdc_dsr_check, tp, hz*30); mdc_dsr_check(tp); } } /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -