📄 dca.c
字号:
tp = &dca_tty[unit]; c = dca->dca_data; if ((tp->t_state & TS_ISOPEN) == 0) {#ifdef KGDB /* we don't care about parity errors */ if (((stat & (LSR_BI|LSR_FE|LSR_PE)) == LSR_PE) && kgdb_dev == makedev(dcamajor, unit) && c == FRAME_END) kgdb_connect(0); /* trap into kgdb */#endif return; } if (stat & (LSR_BI | LSR_FE)) c |= TTY_FE; else if (stat & LSR_PE) c |= TTY_PE; else if (stat & LSR_OE) dcaoflows[unit]++; (*linesw[tp->t_line].l_rint)(c, tp);}dcamint(unit, dca) register int unit; register struct dcadevice *dca;{ register struct tty *tp; register u_char stat; tp = &dca_tty[unit]; stat = dca->dca_msr;#ifdef DEBUG dcamintcount[stat & 0xf]++;#endif if ((stat & MSR_DDCD) && (dcasoftCAR & (1 << unit)) == 0) { if (stat & MSR_DCD) (void)(*linesw[tp->t_line].l_modem)(tp, 1); else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) dca->dca_mcr &= ~(MCR_DTR | MCR_RTS); } /* * CTS change. * If doing HW output flow control start/stop output as appropriate. */ if ((stat & MSR_DCTS) && (tp->t_state & TS_ISOPEN) && (tp->t_cflag & CCTS_OFLOW)) { if (stat & MSR_CTS) { tp->t_state &=~ TS_TTSTOP; dcastart(tp); } else { tp->t_state |= TS_TTSTOP; } }}dcaioctl(dev, cmd, data, flag, p) dev_t dev; int cmd; caddr_t data; int flag; struct proc *p;{ register struct tty *tp; register int unit = UNIT(dev); register struct dcadevice *dca; register int error; tp = &dca_tty[unit]; error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); if (error >= 0) return (error); error = ttioctl(tp, cmd, data, flag); if (error >= 0) return (error); dca = dca_addr[unit]; switch (cmd) { case TIOCSBRK: dca->dca_cfcr |= CFCR_SBREAK; break; case TIOCCBRK: dca->dca_cfcr &= ~CFCR_SBREAK; break; case TIOCSDTR: (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMBIS); break; case TIOCCDTR: (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMBIC); break; case TIOCMSET: (void) dcamctl(dev, *(int *)data, DMSET); break; case TIOCMBIS: (void) dcamctl(dev, *(int *)data, DMBIS); break; case TIOCMBIC: (void) dcamctl(dev, *(int *)data, DMBIC); break; case TIOCMGET: *(int *)data = dcamctl(dev, 0, DMGET); break; default: return (ENOTTY); } return (0);}dcaparam(tp, t) register struct tty *tp; register struct termios *t;{ register struct dcadevice *dca; register int cfcr, cflag = t->c_cflag; int unit = UNIT(tp->t_dev); int ospeed = ttspeedtab(t->c_ospeed, dcaspeedtab); /* check requested parameters */ if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed)) return (EINVAL); /* and copy to tty */ tp->t_ispeed = t->c_ispeed; tp->t_ospeed = t->c_ospeed; tp->t_cflag = cflag; dca = dca_addr[unit]; dca->dca_ier = IER_ERXRDY | IER_ETXRDY | IER_ERLS | IER_EMSC;#ifdef hp700 dca->dca_mcr |= MCR_IEN;#endif if (ospeed == 0) { (void) dcamctl(unit, 0, DMSET); /* hang up line */ return (0); } dca->dca_cfcr |= CFCR_DLAB; dca->dca_data = ospeed & 0xFF; dca->dca_ier = ospeed >> 8; switch (cflag&CSIZE) { case CS5: cfcr = CFCR_5BITS; break; case CS6: cfcr = CFCR_6BITS; break; case CS7: cfcr = CFCR_7BITS; break; case CS8: cfcr = CFCR_8BITS; break; } if (cflag&PARENB) { cfcr |= CFCR_PENAB; if ((cflag&PARODD) == 0) cfcr |= CFCR_PEVEN; } if (cflag&CSTOPB) cfcr |= CFCR_STOPB; dca->dca_cfcr = cfcr; if (dca_hasfifo & (1 << unit)) dca->dca_fifo = FIFO_ENABLE | FIFO_TRIGGER_14; return (0);} voiddcastart(tp) register struct tty *tp;{ register struct dcadevice *dca; int s, unit, c; unit = UNIT(tp->t_dev); dca = dca_addr[unit]; s = spltty(); if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP)) goto out; if (tp->t_outq.c_cc <= tp->t_lowat) { if (tp->t_state&TS_ASLEEP) { tp->t_state &= ~TS_ASLEEP; wakeup((caddr_t)&tp->t_outq); } selwakeup(&tp->t_wsel); } if (tp->t_outq.c_cc == 0) goto out; if (dca->dca_lsr & LSR_TXRDY) { c = getc(&tp->t_outq); tp->t_state |= TS_BUSY; dca->dca_data = c; if (dca_hasfifo & (1 << unit)) { for (c = 1; c < 16 && tp->t_outq.c_cc; ++c) dca->dca_data = getc(&tp->t_outq);#ifdef DEBUG if (c > 16) fifoout[0]++; else fifoout[c]++;#endif } }out: splx(s);} /* * Stop output on a line. *//*ARGSUSED*/dcastop(tp, flag) register struct tty *tp; int flag;{ register int s; s = spltty(); if (tp->t_state & TS_BUSY) { if ((tp->t_state&TS_TTSTOP)==0) tp->t_state |= TS_FLUSH; } splx(s);} dcamctl(dev, bits, how) dev_t dev; int bits, how;{ register struct dcadevice *dca; register int unit; int s; unit = UNIT(dev); dca = dca_addr[unit];#ifdef hp700 /* * Always make sure MCR_IEN is set (unless setting to 0) */#ifdef KGDB if (how == DMSET && kgdb_dev == makedev(dcamajor, unit)) bits |= MCR_IEN; else#endif if (how == DMBIS || (how == DMSET && bits)) bits |= MCR_IEN; else if (how == DMBIC) bits &= ~MCR_IEN;#endif s = spltty(); switch (how) { case DMSET: dca->dca_mcr = bits; break; case DMBIS: dca->dca_mcr |= bits; break; case DMBIC: dca->dca_mcr &= ~bits; break; case DMGET: bits = dca->dca_msr; break; } (void) splx(s); return (bits);}/* * Following are all routines needed for DCA to act as console */#include <hp/dev/cons.h>dcacnprobe(cp) struct consdev *cp;{ int unit; /* locate the major number */ for (dcamajor = 0; dcamajor < nchrdev; dcamajor++) if (cdevsw[dcamajor].d_open == dcaopen) break; /* XXX: ick */ unit = CONUNIT;#ifdef hp300 dca_addr[CONUNIT] = (struct dcadevice *) sctova(CONSCODE); /* make sure hardware exists */ if (badaddr((short *)dca_addr[unit])) { cp->cn_pri = CN_DEAD; return; }#endif#ifdef hp700 dca_addr[CONUNIT] = CONPORT;#endif /* initialize required fields */ cp->cn_dev = makedev(dcamajor, unit); cp->cn_tp = &dca_tty[unit];#ifdef hp300 switch (dca_addr[unit]->dca_id) { case DCAID0: case DCAID1: cp->cn_pri = CN_NORMAL; break; case DCAREMID0: case DCAREMID1: cp->cn_pri = CN_REMOTE; break; default: cp->cn_pri = CN_DEAD; break; }#endif#ifdef hp700 cp->cn_pri = CN_NORMAL;#endif /* * If dcaconsole is initialized, raise our priority. */ if (dcaconsole == unit) cp->cn_pri = CN_REMOTE;#ifdef KGDB if (major(kgdb_dev) == 1) /* XXX */ kgdb_dev = makedev(dcamajor, minor(kgdb_dev));#endif}dcacninit(cp) struct consdev *cp;{ int unit = UNIT(cp->cn_dev); dcainit(unit, dcadefaultrate); dcaconsole = unit; dcaconsinit = 1;}dcainit(unit, rate) int unit, rate;{ register struct dcadevice *dca; int s; short stat;#ifdef lint stat = unit; if (stat) return;#endif dca = dca_addr[unit]; s = splhigh();#ifdef hp300 dca->dca_reset = 0xFF; DELAY(100); dca->dca_ic = IC_IE;#endif dca->dca_cfcr = CFCR_DLAB; rate = ttspeedtab(rate, dcaspeedtab); dca->dca_data = rate & 0xFF; dca->dca_ier = rate >> 8; dca->dca_cfcr = CFCR_8BITS; dca->dca_ier = IER_ERXRDY | IER_ETXRDY;#ifdef hp700 dca->dca_mcr |= MCR_IEN;#endif dca->dca_fifo = FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_14; DELAY(100); stat = dca->dca_iir; splx(s);}dcacngetc(dev) dev_t dev;{ register struct dcadevice *dca = dca_addr[UNIT(dev)]; register u_char stat; int c, s;#ifdef lint stat = dev; if (stat) return (0);#endif s = splhigh(); while (((stat = dca->dca_lsr) & LSR_RXRDY) == 0) ; c = dca->dca_data; stat = dca->dca_iir; splx(s); return (c);}/* * Console kernel output character routine. */dcacnputc(dev, c) dev_t dev; register int c;{ register struct dcadevice *dca = dca_addr[UNIT(dev)]; register int timo; register u_char stat; int s = splhigh();#ifdef lint stat = dev; if (stat) return;#endif if (dcaconsinit == 0) { (void) dcainit(UNIT(dev), dcadefaultrate); dcaconsinit = 1; } /* wait for any pending transmission to finish */ timo = 50000; while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo) ; dca->dca_data = c; /* wait for this transmission to complete */ timo = 1500000; while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo) ; /* * If the "normal" interface was busy transfering a character * we must let our interrupt through to keep things moving. * Otherwise, we clear the interrupt that we have caused. */ if ((dca_tty[UNIT(dev)].t_state & TS_BUSY) == 0) stat = dca->dca_iir; splx(s);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -