📄 dmf.c
字号:
timeout(dmfsetbreak, tp, dmf_delay[tp->t_cflag & CBAUD]); TTY_SLEEP(tp, (caddr_t)&tp->t_dev, TTOPRI); (void) dmfmctl(dev, DMF_BRK, DMBIS); break; case TIOCCBRK: (void) dmfmctl(dev, DMF_BRK, DMBIC); break; case TIOCSDTR: (void) dmfmctl(dev, DMF_DTR|DMF_RTS, DMBIS); break; case TIOCCDTR: (void) dmfmctl(dev, DMF_DTR|DMF_RTS, DMBIC); break; case TIOCMSET: (void) dmfmctl(dev, dmtodmf(*(int *)data), DMSET); break; case TIOCMBIS: (void) dmfmctl(dev, dmtodmf(*(int *)data), DMBIS); break; case TIOCMBIC: (void) dmfmctl(dev, dmtodmf(*(int *)data), DMBIC); break; case TIOCMGET: *(int *)data = dmftodm(dmfmctl(dev, 0, DMGET)); break;#ifdef 0 /* * Doesn't work yet ! */ /* Set local loopback mode */ case TIOCSMLB: if (u.u_uid) return(EPERM); s=spl5(); dmfaddr = (struct dmfdevice *)(dmf_tty[unit].t_addr); dmfaddr->dmfcsr = DMF_IE | DMFIR_LCR | (unit & LINEMASK); SETLCR(dmfaddr, dmfaddr->dmflcr|DMF_MAINT); splx(s); break; /* Clear local loopback mode */ case TIOCCMLB: if (u.u_uid) return(EPERM); s=spl5(); dmfaddr = (struct dmfdevice *)(dmf_tty[unit].t_addr); dmfaddr->dmfcsr = DMF_IE | DMFIR_LCR | (unit & LINEMASK); SETLCR(dmfaddr, dmfaddr->dmflcr&~DMF_MAINT); splx(s); break;#endif 0 case TIOCNMODEM: /* ignore modem status */ s = spl5(); dmfsoftCAR[dmf] |= (1<<(unit&LINEMASK)); if (*(int *)data) /* make mode permanent */ dmfdefaultCAR[dmf] |= (1<<(unit&LINEMASK)); dmfmodem[unit] = MODEM_CTS|MODEM_CD|MODEM_DSR; tp->t_state |= TS_CARR_ON; tp->t_cflag |= CLOCAL; /* Map to termio */ splx(s); break; case TIOCMODEM: /* look at modem status - sleep if no carrier */ s = spl5(); dmfsoftCAR[dmf] &= ~(1<<(unit&LINEMASK)); if (*(int *)data) /* make mode permanent */ dmfdefaultCAR[dmf] &= ~(1<<(unit&LINEMASK)); dmfaddr = (struct dmfdevice *)(dmf_tty[unit].t_addr); dmfaddr->dmfcsr = DMF_IE | DMFIR_TBUF | (unit&LINEMASK); /* * If dmfdsr is set look for DSR|CTS|CD, otherwise look * for CD|CTS only. */ if ((dmfdsr && ((dmfaddr->dmfrms & DMF_XMIT)==DMF_XMIT)) || ((dmfdsr == 0) && ((dmfaddr->dmfrms & DMF_NODSR)==DMF_NODSR))){ tp->t_state |= TS_CARR_ON; tp->t_state &= ~TS_ONDELAY; dmfmodem[unit] = MODEM_CTS|MODEM_CD|MODEM_DSR; } else { tp->t_state &= ~(TS_CARR_ON); dmfmodem[unit] &= ~(MODEM_CTS|MODEM_CD|MODEM_DSR); } tp->t_cflag &= ~CLOCAL; /* Map to termio */ splx(s); break; case TIOCWONLINE: s = spl5();#ifdef DMFDEBUG if (dmfdebug) mprintf("dmfioctl: WONLINE, tp=%x, state=%x\n", tp, tp->t_state);#endif dmfaddr = (struct dmfdevice *)(dmf_tty[unit].t_addr); dmfaddr->dmfcsr = DMF_IE | DMFIR_TBUF | (unit&LINEMASK); /* * If dmfdsr is set look for DSR|CTS|CD, otherwise look * for CD|CTS only. */ if ((dmfdsr && ((dmfaddr->dmfrms & DMF_XMIT)==DMF_XMIT)) || ((dmfdsr == 0) && ((dmfaddr->dmfrms & DMF_NODSR)==DMF_NODSR))){ tp->t_state |= TS_CARR_ON; tp->t_state &= ~TS_ONDELAY; dmfmodem[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)); if (tp->t_cflag & CLOCAL) { sc->sc_category_flags[unit&LINEMASK] |= DEV_MODEM; sc->sc_category_flags[unit&LINEMASK] &= ~DEV_MODEM_ON; } else sc->sc_category_flags[unit&LINEMASK] |= (DEV_MODEM|DEV_MODEM_ON); devget->category = DEV_TERMINAL; devget->bus = DEV_UB; bcopy(DEV_DMF32,devget->interface, strlen(DEV_DMF32)); bcopy(DEV_UNKNOWN,devget->device, strlen(DEV_UNKNOWN)); /* terminal */ devget->adpt_num = ui->ui_adpt; /* which adapter*/ devget->nexus_num = ui->ui_nexus; /* which nexus */ devget->bus_num = ui->ui_ubanum; /* which UBA */ devget->ctlr_num = dmf; /* which interf.*/ devget->slave_num = unit&LINEMASK; /* which line */ bcopy(ui->ui_driver->ud_dname, devget->dev_name, strlen(ui->ui_driver->ud_dname)); /* Ultrix "dmf" */ devget->unit_num = unit&LINEMASK; /* which dmf line ? */ devget->soft_count = sc->sc_softcnt[unit&LINEMASK]; /* soft er. cnt.*/ devget->hard_count = sc->sc_hardcnt[unit&LINEMASK]; /* hard er 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; dmfparam(unit); break; default: if (u.u_procp->p_progenv == A_POSIX) return (EINVAL); return (ENOTTY); } return (0);}dmtodmf(bits) register int bits;{ register int b; b = bits & 012; if (bits & DML_ST) b |= DMF_RATE; if (bits & DML_RTS) b |= DMF_RTS; if (bits & DML_USR) b |= DMF_USRW; return(b);}dmftodm(bits) register int bits;{ register int b; b = (bits & 012) | ((bits >> 7) & 0760) | DML_LE; if (bits & DMF_USRR) b |= DML_USR; if (bits & DMF_RTS) b |= DML_RTS; return(b);}/* * Set parameters from open or stty into the DMF hardware * registers. */dmfparam(unit) register int unit;{ register struct tty *tp; register struct dmfdevice *addr; register int lpar, lcr; int s; tp = &dmf_tty[unit]; addr = (struct dmfdevice *)tp->t_addr; /* * Block interrupts so parameters will be set * before the line interrupts. */ s = spl5(); addr->dmfcsr = (unit&LINEMASK) | DMFIR_LCR | DMF_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) dmfmctl(unit, DMF_OFF, DMSET); splx(s); return; } lpar = (dmf_speeds[tp->t_cflag_ext&CBAUD]<<12) | /* ospeed */ (dmf_speeds[tp->t_cflag&CBAUD]<<8); /* ispeed */ lcr = DMFLCR_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; } } /* * Set device registers according to the specifications of the termio * structure. */ if (tp->t_cflag & CREAD) lcr |= DMF_RE; else lcr &= ~DMF_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 |= DMF_AUTOX; lpar |= (unit&LINEMASK); addr->dmflpr = lpar; SETLCR(addr, lcr);#ifdef DMFDEBUG if (dmfdebug) mprintf("dmfparam: tp=%x, lpr=%x, lcr=%o\n", tp, addr->dmflpr, addr->dmfun.dmfirw);#endif splx(s);}/* * DMF32 transmitter interrupt. * Restart the idle line. */dmfxint(dmf) int dmf;{ int u = dmf * 8; struct tty *tp0 = &dmf_tty[u]; register struct tty *tp; register struct dmfdevice *addr; register struct uba_device *ui; register int t; short cntr; ui = dmfinfo[dmf]; addr = (struct dmfdevice *)ui->ui_addr; while ((t = addr->dmfcsr) & DMF_TI) { if (t & DMF_NXM) /* SHOULD RESTART OR SOMETHING... */ printf("dmf%d: NXM line %d\n", dmf, 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 (dmf_dma[u + t]) { /* * Do arithmetic in a short to make up * for lost 16&17 bits. */ addr->dmfcsr = DMFIR_TBA | DMF_IE | t; cntr = addr->dmftba - 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 dmfstart(tp); }}/* * Start (restart) transmission on the given DMF32 line. */dmfstart(tp) register struct tty *tp;{ register struct dmfdevice *addr; register int unit, nch, line; int s; register int dmf; unit = minor(tp->t_dev); dmf = unit >> 3; line = unit & LINEMASK; addr = (struct dmfdevice *)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 do not transmit if not CTS. */ if ((tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) || ((tp->t_state & TS_CARR_ON) && (dmfmodem[unit]&MODEM_CTS)==0)) goto out; /* * If there are still characters in the silo, * just reenable the transmitter. */ addr->dmfcsr = DMF_IE | DMFIR_TBUF | line; if (addr->dmftsc) { addr->dmfcsr = DMF_IE | DMFIR_LCR | line; SETLCR(addr, addr->dmflcr|DMF_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 >= dmf_mindma) { register car; dmf_dma[unit] = 1; addr->dmfcsr = DMF_IE | DMFIR_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->dmflcr|DMF_TE); car = UBACVT(tp->t_outq.c_cf, dmfinfo[dmf]->ui_ubanum); addr->dmfcsr = DMF_IE | DMFIR_TBA | line; /* * Give the device the starting address of a DMA transfer. * Translate the system virtual address into a physical * address. */ addr->dmftba = svtophy(car); addr->dmftcc = ((car >> 2) & 0xc000) | nch; tp->t_state |= TS_BUSY; } else if (nch) { register char *cp = tp->t_outq.c_cf; register int i; dmf_dma[unit] = 0; nch = MIN(nch, DMF_SILOCNT); addr->dmfcsr = DMF_IE | DMFIR_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->dmflcr|DMF_TE); addr->dmfcsr = DMF_IE | DMFIR_TBUF | line; for (i = 0; i < nch; i++)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -