📄 dc.c
字号:
voiddcintr(unit) register int unit;{ register dcregs *dcaddr; register unsigned csr; unit <<= 2; dcaddr = (dcregs *)dcpdma[unit].p_addr; while ((csr = dcaddr->dc_csr) & (CSR_RDONE | CSR_TRDY)) { if (csr & CSR_RDONE) dcrint(unit); if (csr & CSR_TRDY) dcxint(&dc_tty[unit + ((csr >> 8) & 03)]); }}dcrint(unit) register int unit;{ register dcregs *dcaddr; register struct tty *tp; register int c, cc; register struct tty *tp0; int overrun = 0; dcaddr = (dcregs *)dcpdma[unit].p_addr; tp0 = &dc_tty[unit]; while ((c = dcaddr->dc_rbuf) < 0) { /* char present */ cc = c & 0xff; tp = tp0 + ((c >> 8) & 03); if ((c & RBUF_OERR) && overrun == 0) { log(LOG_WARNING, "dc%d,%d: silo overflow\n", unit >> 2, (c >> 8) & 03); overrun = 1; } /* the keyboard requires special translation */ if (tp == &dc_tty[DCKBD_PORT] && cn_tab.cn_screen) {#ifdef KADB if (cc == LK_DO) { spl0(); kdbpanic(); return; }#endif#ifdef DEBUG debugChar = cc;#endif if (dcDivertXInput) { (*dcDivertXInput)(cc); return; } if ((cc = kbdMapChar(cc)) < 0) return; } else if (tp == &dc_tty[DCMOUSE_PORT] && dcMouseButtons) { register MouseReport *mrp; static MouseReport currentRep; mrp = ¤tRep; mrp->byteCount++; if (cc & MOUSE_START_FRAME) { /* * The first mouse report byte (button state). */ mrp->state = cc; if (mrp->byteCount > 1) mrp->byteCount = 1; } else if (mrp->byteCount == 2) { /* * The second mouse report byte (delta x). */ mrp->dx = cc; } else if (mrp->byteCount == 3) { /* * The final mouse report byte (delta y). */ mrp->dy = cc; mrp->byteCount = 0; if (mrp->dx != 0 || mrp->dy != 0) { /* * If the mouse moved, * post a motion event. */ (*dcMouseEvent)(mrp); } (*dcMouseButtons)(mrp); } return; } if (!(tp->t_state & TS_ISOPEN)) { wakeup((caddr_t)&tp->t_rawq);#ifdef PORTSELECTOR if (!(tp->t_state & TS_WOPEN))#endif return; } if (c & RBUF_FERR) cc |= TTY_FE; if (c & RBUF_PERR) cc |= TTY_PE; (*linesw[tp->t_line].l_rint)(cc, tp); } DELAY(10);}voiddcxint(tp) register struct tty *tp;{ register struct pdma *dp; register dcregs *dcaddr; dp = &dcpdma[minor(tp->t_dev)]; if (dp->p_mem < dp->p_end) { dcaddr = (dcregs *)dp->p_addr; dcaddr->dc_tdr = dc_brk[(tp - dc_tty) >> 2] | *dp->p_mem++; MachEmptyWriteBuffer(); DELAY(10); return; } tp->t_state &= ~TS_BUSY; if (tp->t_state & TS_FLUSH) tp->t_state &= ~TS_FLUSH; else { 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 dcstart(tp); if (tp->t_outq.c_cc == 0 || !(tp->t_state & TS_BUSY)) { dcaddr = (dcregs *)dp->p_addr; dcaddr->dc_tcr &= ~(1 << (minor(tp->t_dev) & 03)); MachEmptyWriteBuffer(); DELAY(10); }}voiddcstart(tp) register struct tty *tp;{ register struct pdma *dp; register dcregs *dcaddr; register int cc; int s; dp = &dcpdma[minor(tp->t_dev)]; dcaddr = (dcregs *)dp->p_addr; s = spltty(); if (tp->t_state & (TS_TIMEOUT|TS_BUSY|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; /* handle console specially */ if (tp == &dc_tty[DCKBD_PORT] && cn_tab.cn_screen) { while (tp->t_outq.c_cc > 0) { cc = getc(&tp->t_outq) & 0x7f; cnputc(cc); } /* * After we flush the output queue we may need to wake * up the process that made the output. */ 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); } goto out; } if (tp->t_flags & (RAW|LITOUT)) cc = ndqb(&tp->t_outq, 0); else { cc = ndqb(&tp->t_outq, 0200); if (cc == 0) { cc = getc(&tp->t_outq); timeout(ttrstrt, (void *)tp, (cc & 0x7f) + 6); tp->t_state |= TS_TIMEOUT; goto out; } } tp->t_state |= TS_BUSY; dp->p_end = dp->p_mem = tp->t_outq.c_cf; dp->p_end += cc; dcaddr->dc_tcr |= 1 << (minor(tp->t_dev) & 03); MachEmptyWriteBuffer();out: splx(s);}/* * Stop output on a line. *//*ARGSUSED*/dcstop(tp, flag) register struct tty *tp;{ register struct pdma *dp; register int s; dp = &dcpdma[minor(tp->t_dev)]; s = spltty(); if (tp->t_state & TS_BUSY) { dp->p_end = dp->p_mem; if (!(tp->t_state & TS_TTSTOP)) tp->t_state |= TS_FLUSH; } splx(s);}dcmctl(dev, bits, how) dev_t dev; int bits, how;{ register dcregs *dcaddr; register int unit, mbits; int b, s; register int msr; unit = minor(dev); b = 1 << (unit & 03); dcaddr = (dcregs *)dcpdma[unit].p_addr; s = spltty(); /* only channel 2 has modem control (what about line 3?) */ mbits = DML_DTR | DML_DSR | DML_CAR; switch (unit & 03) { case 2: mbits = 0; if (dcaddr->dc_tcr & TCR_DTR2) mbits |= DML_DTR; msr = dcaddr->dc_msr; if (msr & MSR_CD2) mbits |= DML_CAR; if (msr & MSR_DSR2) { if (pmax_boardtype == DS_PMAX) mbits |= DML_CAR | DML_DSR; else mbits |= DML_DSR; } break; case 3: if (pmax_boardtype != DS_PMAX) { mbits = 0; if (dcaddr->dc_tcr & TCR_DTR3) mbits |= DML_DTR; msr = dcaddr->dc_msr; if (msr & MSR_CD3) mbits |= DML_CAR; if (msr & MSR_DSR3) mbits |= DML_DSR; } } switch (how) { case DMSET: mbits = bits; break; case DMBIS: mbits |= bits; break; case DMBIC: mbits &= ~bits; break; case DMGET: (void) splx(s); return (mbits); } switch (unit & 03) { case 2: if (mbits & DML_DTR) dcaddr->dc_tcr |= TCR_DTR2; else dcaddr->dc_tcr &= ~TCR_DTR2; break; case 3: if (pmax_boardtype != DS_PMAX) { if (mbits & DML_DTR) dcaddr->dc_tcr |= TCR_DTR3; else dcaddr->dc_tcr &= ~TCR_DTR3; } } if ((mbits & DML_DTR) && (dcsoftCAR[unit >> 2] & b)) dc_tty[unit].t_state |= TS_CARR_ON; (void) splx(s); return (mbits);}/* * This is called by timeout() periodically. * Check to see if modem status bits have changed. */voiddcscan(arg) void *arg;{ register dcregs *dcaddr; register struct tty *tp; register int i, bit, car; int s; s = spltty(); /* only channel 2 has modem control (what about line 3?) */ dcaddr = (dcregs *)dcpdma[i = 2].p_addr; tp = &dc_tty[i]; bit = TCR_DTR2; if (dcsoftCAR[i >> 2] & bit) car = 1; else car = dcaddr->dc_msr & MSR_DSR2; if (car) { /* carrier present */ if (!(tp->t_state & TS_CARR_ON)) (void)(*linesw[tp->t_line].l_modem)(tp, 1); } else if ((tp->t_state & TS_CARR_ON) && (*linesw[tp->t_line].l_modem)(tp, 0) == 0) dcaddr->dc_tcr &= ~bit; splx(s); timeout(dcscan, (void *)0, hz);}/* * ---------------------------------------------------------------------------- * * dcGetc -- * * Read a character from a serial line. * * Results: * A character read from the serial port. * * Side effects: * None. * * ---------------------------------------------------------------------------- */intdcGetc(dev) dev_t dev;{ register dcregs *dcaddr; register int c; int s; dcaddr = (dcregs *)dcpdma[minor(dev)].p_addr; if (!dcaddr) return (0); s = spltty(); for (;;) { if (!(dcaddr->dc_csr & CSR_RDONE)) continue; c = dcaddr->dc_rbuf; DELAY(10); if (((c >> 8) & 03) == (minor(dev) & 03)) break; } splx(s); return (c & 0xff);}/* * Send a char on a port, non interrupt driven. */voiddcPutc(dev, c) dev_t dev; int c;{ register dcregs *dcaddr; register u_short tcr; register int timeout; int s, line; s = spltty(); dcaddr = (dcregs *)dcpdma[minor(dev)].p_addr; tcr = dcaddr->dc_tcr; dcaddr->dc_tcr = tcr | (1 << minor(dev)); MachEmptyWriteBuffer(); DELAY(10); while (1) { /* * Wait for transmitter to be not busy. */ timeout = 1000000; while (!(dcaddr->dc_csr & CSR_TRDY) && timeout > 0) timeout--; if (timeout == 0) { printf("dcPutc: timeout waiting for CSR_TRDY\n"); break; } line = (dcaddr->dc_csr >> 8) & 3; /* * Check to be sure its the right port. */ if (line != minor(dev)) { tcr |= 1 << line; dcaddr->dc_tcr &= ~(1 << line); MachEmptyWriteBuffer(); DELAY(10); continue; } /* * Start sending the character. */ dcaddr->dc_tdr = dc_brk[0] | (c & 0xff); MachEmptyWriteBuffer(); DELAY(10); /* * Wait for character to be sent. */ while (1) { /* * cc -O bug: this code produces and infinite loop! * while (!(dcaddr->dc_csr & CSR_TRDY)) * ; */ timeout = 1000000; while (!(dcaddr->dc_csr & CSR_TRDY) && timeout > 0) timeout--; line = (dcaddr->dc_csr >> 8) & 3; if (line != minor(dev)) { tcr |= 1 << line; dcaddr->dc_tcr &= ~(1 << line); MachEmptyWriteBuffer(); DELAY(10); continue; } dcaddr->dc_tcr &= ~(1 << minor(dev)); MachEmptyWriteBuffer(); DELAY(10); break; } break; } /* * Enable interrupts for other lines which became ready. */ if (tcr & 0xF) { dcaddr->dc_tcr = tcr; MachEmptyWriteBuffer(); DELAY(10); } splx(s);}#endif /* NDC */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -