📄 dmz.c
字号:
s = spl5(); oaddr->dmzcsr = (unit&07) | DMZIR_LCR | DMZ_IE; /* * Disconnect modem line if baudrate is zero. POSIX checks the output * baud rate, while non-POSIX checks the input baud rate. */ 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; (void) dmzmctl(unit, DMZ_OFF, DMSET); splx(s); return; } lpar = (dmz_speeds[tp->t_cflag_ext&CBAUD]<<12) | /* ospeed */ (dmz_speeds[tp->t_cflag&CBAUD]<<8); /* ispeed */ lcr = DMZLCR_ENA; /* * Berkeley-only dinosaurs */ if (tp->t_line != TERMIODISC) { if ((tp->t_cflag & CBAUD) == B134){ lpar |= BITS6|PENABLE; tp->t_cflag |= CS6|PARENB; } else if ((tp->t_cflag_ext & CBAUD) == B110){ lpar |= 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) lcr |= DMZ_RE; else lcr &= ~DMZ_RE; if (tp->t_cflag & CSTOPB) lpar |= TWOSB; else lpar &= ~TWOSB; /* parity is enable */ if (tp->t_cflag & PARENB) { if ((tp->t_cflag & PARODD) == 0) /* set even */ lpar |= PENABLE|EPAR; else /* else set odd */ lpar = (lpar | PENABLE)&~EPAR; } /* * character size. * clear bits and check for 6,7,and 8, else its 5 bits. */ lpar &= ~BITS8; switch(tp->t_cflag&CSIZE) { case CS6: lpar |= BITS6; break; case CS7: lpar |= BITS7; break; case CS8: lpar |= BITS8; break; } /* * Outgoing Auto flow control. * No auto flow control allowed if startc != ^q and startc != * ^s. Most drivers do not allow this to be changed. */ if ((tp->t_cflag_ext & PAUTOFLOW) && (tp->t_cc[VSTOP] == CTRL('s')) && (tp->t_cc[VSTART] == CTRL('q'))) lcr |= DMZ_AUTOX; lpar |= (unit&07); oaddr->dmzlpr = lpar; SETLCR(oaddr, lcr);#ifdef DMZDEBUG if (dmzdebug) mprintf("dmzparam: lpr=%x, lcr=%x, oaddr=%x\n", oaddr->dmzlpr, oaddr->dmzun.dmzirw, oaddr);#endif splx(s);}/* * DMZ32 transmitter interrupt. * Restart the idle line. */dmzxint(dmz, octetnum) int dmz, octetnum; /* dmz is the module that interrupted */ /* octetnum is the octet within the module */{ struct tty *tp0; register struct tty *tp; register struct octet *addr; register struct uba_device *ui; register int t; short cntr; /* * Index to propper tty structure by dmz number and octet. Later move * pointer up for the respective line number. */ int unit0 = (dmz * NUMLINES) + (octetnum<<3); ui = dmzinfo[dmz]; addr = &((struct dmzdevice *)ui->ui_addr)->octets[octetnum]; tp0 = &dmz_tty[unit0]; while ((t = addr->dmzcsr) & DMZ_TI) { if (t & DMZ_NXM) /* SHOULD RESTART OR SOMETHING... */ printf("dmz%d: NXM line %d\n", dmz, t >> 8 & 7); t = t >> 8 & 7; tp = tp0 + t; tp->t_state &= ~TS_BUSY; if (tp->t_state&TS_FLUSH) tp->t_state &= ~TS_FLUSH; else if (dmz_dma[unit0 + t]) { /* * Do arithmetic in a short to make up * for lost 16&17 bits. */ addr->dmzcsr = DMZIR_TBA | DMZ_IE | t; cntr = addr->dmztba - UBACVT(tp->t_outq.c_cf, ui->ui_ubanum); ndflush(&tp->t_outq, (int)cntr); } if (tp->t_line) (*linesw[tp->t_line].l_start)(tp); else dmzstart(tp); }}/* * Start (restart) transmission on the given DMZ32 line. */dmzstart(tp) register struct tty *tp;{ register struct octet *addr; register int unit, nch, line; int s; register int dmz; unit = minor(tp->t_dev); dmz = unit / NUMLINES; line = unit & 07; /* specific line on octetnum */ addr = (struct octet *)tp->t_addr; /* * Must hold interrupts in following code to prevent * state of the tp from changing. */ s = spl5(); /* * If it's currently active, or delaying, no need to do anything. * Also dont transmit if not CTS. */ if ((tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) || ((tp->t_state & TS_CARR_ON) && (dmzmodem[unit]&MODEM_CTS)==0)) goto out; /* * If there are still characters in the silo, * just reenable the transmitter. */ addr->dmzcsr = DMZ_IE | DMZIR_TBUF | line; if (addr->dmztsc) { addr->dmzcsr = DMZ_IE | DMZIR_LCR | line; /* * If outgoing auto flow control is enabled, the hardware will * control the transmit enable bit. */ if ((tp->t_cflag_ext & PAUTOFLOW) == 0) SETLCR(addr, addr->dmzlcr|DMZ_TE); tp->t_state |= TS_BUSY; goto out; } /* * If there are sleepers, and output has drained below low * water mark, wake up the sleepers. */ 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; } } /* * Now restart transmission unless the output queue is * empty. */ 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)) nch = ndqb(&tp->t_outq, 0); else { if ((nch = ndqb(&tp->t_outq, DELAY_FLAG)) == 0) { /* * If first thing on queue is a delay process it. */ nch = getc(&tp->t_outq); timeout(ttrstrt, (caddr_t)tp, (nch&0x7f)+6); tp->t_state |= TS_TIMEOUT; goto out; } } /* * If characters to transmit, restart transmission. */ if (nch >= dmz_mindma) { register car; dmz_dma[minor(tp->t_dev)] = 1; addr->dmzcsr = DMZ_IE | DMZIR_LCR | line; /* * If outgoing auto flow control is enabled, the hardware will * control the transmit enable bit. */ if ((tp->t_cflag_ext & PAUTOFLOW) == 0) SETLCR(addr, addr->dmzlcr|DMZ_TE); car = UBACVT(tp->t_outq.c_cf, dmzinfo[dmz]->ui_ubanum); addr->dmzcsr = DMZ_IE | DMZIR_TBA | line; /* * Give the device the starting address of a DMA transfer. * Translate the system virtual address into a physical * address. */ addr->dmztba = svtophy(car); addr->dmztcc = ((car >> 2) & 0xc000) | nch; tp->t_state |= TS_BUSY; } else if (nch) { register char *cp = tp->t_outq.c_cf; register int i; dmz_dma[minor(tp->t_dev)] = 0; nch = MIN(nch, DMZ_SILOCNT); addr->dmzcsr = DMZ_IE | DMZIR_LCR | line; /* * If outgoing auto flow control is enabled, the hardware will * control the transmit enable bit. */ if ((tp->t_cflag_ext & PAUTOFLOW) == 0) SETLCR(addr, addr->dmzlcr|DMZ_TE); addr->dmzcsr = DMZ_IE | DMZIR_TBUF | line; for (i = 0; i < nch; i++) addr->dmztbuf = *cp++; ndflush(&tp->t_outq, nch); tp->t_state |= TS_BUSY; }out: splx(s);}/* * Stop output on a line, e.g. for ^S/^Q or output flush. *//*ARGSUSED*/dmzstop(tp, flag) register struct tty *tp;{ register struct octet *oaddr; register int unit, s; unit = minor(tp->t_dev); unit &= 07; /* line number on octet */ oaddr = (struct octet *)tp->t_addr; /* * Block input/output interrupts while messing with state. */ s = spl5(); if (tp->t_state & TS_BUSY) { /* * Device is transmitting; stop output * by selecting the line and disabling * the transmitter. If this is a flush * request then flush the output silo, * otherwise we will pick up where we * left off by enabling the transmitter. */ oaddr->dmzcsr = DMZIR_LCR | unit | DMZ_IE; /* * If this test isn't done, the hardware will need to see a * start character to get it going again if DMZ_AUTOX is set. */ if ((tp->t_cflag_ext & PAUTOFLOW) == 0) SETLCR(oaddr, oaddr->dmzlcr &~ DMZ_TE); if ((tp->t_state&TS_TTSTOP)==0) { tp->t_state |= TS_FLUSH; SETLCR(oaddr, oaddr->dmzlcr|DMZ_FLUSH); } else tp->t_state &= ~TS_BUSY; } splx(s);}/* * DMZ32 modem control */dmzmctl(dev, bits, how) dev_t dev; int bits, how;{ register struct octet *dmzaddr; register int line, mbits, lcr; int unit; int s; unit = minor(dev); dmzaddr = (struct octet *)(dmz_tty[unit].t_addr); line = unit & 07; /* line number */ s = spl5(); dmzaddr->dmzcsr = DMZ_IE | DMZIR_TBUF | line; mbits = dmzaddr->dmzrms << 8; dmzaddr->dmzcsr = DMZ_IE | DMZIR_LCR | line; mbits |= dmzaddr->dmztms; lcr = dmzaddr->dmzlcr; switch (how) { case DMSET: mbits = (mbits &0xff00) | bits; break; case DMBIS: mbits |= bits; break; case DMBIC: mbits &= ~bits; break; case DMGET: (void) splx(s); return(mbits); } if (mbits & DMZ_BRK) lcr |= DMZ_RBRK; else lcr &= ~DMZ_RBRK; lcr = ((mbits & 037) << 8) | (lcr & 0xff); dmzaddr->dmzun.dmzirw = lcr; (void) splx(s);#ifdef DMZDEBUG if (dmzdebug) mprintf("dmzmctl: unit=%d, l#=%d, lcr=%x, oaddr=%x\n", unit, line, dmzaddr->dmzun.dmzirw, dmzaddr);#endif return(mbits);}/* * Reset state of driver if UBA reset was necessary. * Reset the csr, lpr, and lcr registers on open lines, and * restart transmitters. */dmzreset(uban) int uban;{ register int dmz, unit; register struct tty *tp; register struct uba_device *ui; register struct octet *oaddr; int i, o; if (tty_ubinfo[uban] == 0) return; cbase[uban] = tty_ubinfo[uban]&0x3ffff; for (dmz = 0; dmz < nNDMZ; dmz++) { /* for each dmz module */ ui = dmzinfo[dmz]; if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) continue; printf(" dmz%d", dmz); unit = (dmz << 5); for (o = 0; o < 3; o++) { /* for each octet */ oaddr = &((struct dmzdevice *)ui->ui_addr)->octets[o]; oaddr->dmzcsr = DMZ_IE; oaddr->dmzrsp = dmz_timeout; /* receive timer should be higher */ for (i = 0; i < 8; i++) { /* for each line */ tp = &dmz_tty[unit]; if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) { dmzparam(unit); (void) dmzmctl(unit, DMZ_ON, DMSET); tp->t_state &= ~TS_BUSY; dmzstart(tp); } unit++; } } }}/* octet interrupt handlers *//* In version 1.2 these are not used - dmzr/xint is called with the octet number */dmzrinta(dmz) int dmz;{ dmzrint(dmz, 0);}dmzxinta(dmz) int dmz;{ dmzxint(dmz, 0);}dmzrintb(dmz) int dmz;{ dmzrint(dmz, 1);}dmzxintb(dmz) int dmz;{ dmzxint(dmz, 1);}dmzrintc(dmz) int dmz;{ dmzrint(dmz, 2);}dmzxintc(dmz) int dmz;{ dmzxint(dmz, 2);}dmz_cd_drop(tp)register struct tty *tp;{ register struct octet *addr = (struct octet *)tp->t_addr; register unit = minor(tp->t_dev); addr->dmzcsr = DMZ_IE | DMZIR_TBUF | (unit&07); if ((tp->t_state&TS_CARR_ON) && ((addr->dmzrms&DMZ_CAR) == 0)) {#ifdef DMZDEBUG if (dmzdebug) mprintf("dmz_cd: no CD, tp=%x, unit=%x, addr=%x\n", tp, unit, addr);#endif dmz_tty_drop(tp); return; } dmzmodem[unit] |= MODEM_CD;#ifdef DMZDEBUG if (dmzdebug) mprintf("dmz_cd: CD is up, tp=%x\n", tp);#endif}dmz_dsr_check(tp)register struct tty *tp;{ int unit = minor(tp->t_dev); register struct octet *addr = (struct octet *)tp->t_addr; if (dmzmodem[unit]&MODEM_DSR_START) {#ifdef DMZDEBUG if (dmzdebug) mprintf("dmz_dsr_check0: tp=%x\n", tp);#endif dmzmodem[unit] &= ~MODEM_DSR_START; addr->dmzcsr = DMZ_IE | DMZIR_TBUF | (unit&07); /* * If dmzdsr is set look for DSR|CTS|CD, otherwise look * for CD|CTS only. */ if (dmzdsr) { if ((addr->dmzrms&DMZ_XMIT)==DMZ_XMIT) dmz_start_tty(tp); } else { if ((addr->dmzrms&DMZ_NODSR)==DMZ_NODSR) dmz_start_tty(tp); } return; } if ((tp->t_state&TS_CARR_ON)==0) { dmz_tty_drop(tp);#ifdef DMZDEBUG if (dmzdebug) mprintf("dmz_dsr_check: no carrier, tp=%x\n", tp);#endif }#ifdef DMZDEBUG else if (dmzdebug) mprintf("dmz_dsr_check: carrier is up, tp=%x\n", tp);#endif}/* * cd_down return 1 if carrier has been down for at least 2 secs. */dmz_cd_down(tp)struct tty *tp;{ int msecs; register int unit = minor(tp->t_dev); msecs = 1000000 * (time.tv_sec - dmztimestamp[unit].tv_sec) + (time.tv_usec - dmztimestamp[unit].tv_usec); if (msecs > 2000000) return(1); else return(0);}dmz_tty_drop(tp)struct tty *tp;{ register struct octet *addr = (struct octet *)tp->t_addr; register int line; register int unit;#ifdef DMZDEBUG if (dmzdebug) mprintf("dmz_start_tty: drop tty , tp=%x, flags=%x\n", tp, tp->t_flags);#endif if (tp->t_flags&NOHANG) return; unit = minor(tp->t_dev); line = unit & 07; dmzmodem[unit] = MODEM_BADCALL; tp->t_state &= ~(TS_CARR_ON|TS_TTSTOP|TS_BUSY|TS_ISUSP); wakeup((caddr_t)&tp->t_rawq); gsignal(tp->t_pgrp, SIGHUP); gsignal(tp->t_pgrp, SIGCONT); addr->dmzcsr=DMZ_IE | DMZIR_LCR | line; addr->dmztms = 0;}dmz_start_tty(tp) register struct tty *tp;{ register int unit = minor(tp->t_dev); if (tp->t_state&TS_CARR_ON) {#ifdef DMZDEBUG if (dmzdebug) mprintf("dmz_start_tty: carr on, tp=%x\n", tp);#endif return; } tp->t_state &= ~TS_ONDELAY; tp->t_state |= TS_CARR_ON; if (dmzmodem[unit]&MODEM_DSR) untimeout(dmz_dsr_check, tp); dmzmodem[unit] |= MODEM_CD|MODEM_CTS|MODEM_DSR; dmztimestamp[unit] = dmzzerotime; wakeup((caddr_t)&tp->t_rawq);}dmzbaudrate(speed)register int speed;{ if (dmz_valid_speeds & (1 << speed)) return (1); else return (0);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -