📄 com.c
字号:
if (ISSET(sc->sc_mcr, MCR_DTR)) { if (!ISSET(sc->sc_mcr, MCR_RTS)) { SET(sc->sc_mcr, MCR_RTS); bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr); } } else { if (ISSET(sc->sc_mcr, MCR_RTS)) { CLR(sc->sc_mcr, MCR_RTS); bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr); } } sc->sc_dtr = MCR_DTR | MCR_RTS; } else sc->sc_dtr = MCR_DTR; /* and copy to tty */ tp->t_ispeed = t->c_ispeed; tp->t_ospeed = t->c_ospeed; oldcflag = tp->t_cflag; tp->t_cflag = t->c_cflag; /* * If DCD is off and MDMBUF is changed, ask the tty layer if we should * stop the device. */ if (!ISSET(sc->sc_msr, MSR_DCD) && !ISSET(sc->sc_swflags, COM_SW_SOFTCAR) && ISSET(oldcflag, MDMBUF) != ISSET(tp->t_cflag, MDMBUF) && (*linesw[tp->t_line].l_modem)(tp, 0) == 0) { CLR(sc->sc_mcr, sc->sc_dtr); bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr); } /* Just to be sure... */ splx(s); comstart(tp); return 0;}voidcomstart(tp) struct tty *tp;{ struct com_softc *sc = com_cd.cd_devs[DEVUNIT(tp->t_dev)]; bus_space_tag_t iot = sc->sc_iot; bus_space_handle_t ioh = sc->sc_ioh; int s; s = spltty(); if (ISSET(tp->t_state, TS_BUSY)) goto out; if (ISSET(tp->t_state, TS_TIMEOUT | TS_TTSTOP) || sc->sc_halt > 0) goto stopped; if (ISSET(tp->t_cflag, CRTSCTS) && !ISSET(sc->sc_msr, MSR_CTS)) goto stopped; if (tp->t_outq.c_cc <= tp->t_lowat) { if (ISSET(tp->t_state, TS_ASLEEP)) { CLR(tp->t_state, TS_ASLEEP); wakeup(&tp->t_outq); } if (tp->t_outq.c_cc == 0) goto stopped; selwakeup(&tp->t_wsel); } SET(tp->t_state, TS_BUSY); if (!ISSET(sc->sc_ier, IER_ETXRDY)) { SET(sc->sc_ier, IER_ETXRDY); bus_space_write_1(iot, ioh, com_ier, sc->sc_ier); } if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) { u_char buffer[64]; /* XXX: largest fifo */ u_char *cp = buffer; int n = q_to_b(&tp->t_outq, cp, sc->sc_fifolen); do { bus_space_write_1(iot, ioh, com_data, *cp++); } while (--n); } else bus_space_write_1(iot, ioh, com_data, getc(&tp->t_outq));out: splx(s); return;stopped: if (ISSET(sc->sc_ier, IER_ETXRDY)) { CLR(sc->sc_ier, IER_ETXRDY); bus_space_write_1(iot, ioh, com_ier, sc->sc_ier); } splx(s);}/* * Stop output on a line. */intcomstop(tp, flag) struct tty *tp; int flag;{ int s; s = spltty(); if (ISSET(tp->t_state, TS_BUSY)) if (!ISSET(tp->t_state, TS_TTSTOP)) SET(tp->t_state, TS_FLUSH); splx(s); return 0;}voidcomdiag(arg) void *arg;{ struct com_softc *sc = arg; int overflows, floods; int s; s = spltty(); sc->sc_errors = 0; overflows = sc->sc_overflows; sc->sc_overflows = 0; floods = sc->sc_floods; sc->sc_floods = 0; splx(s); log(LOG_WARNING, "%s: %d silo overflow%s, %d ibuf overflow%s\n", sc->sc_dev.dv_xname, overflows, overflows == 1 ? "" : "s", floods, floods == 1 ? "" : "s");}voidcompoll(arg) void *arg;{ int unit; struct com_softc *sc; struct tty *tp; register u_char *ibufp; u_char *ibufend; register int c; int s; static int lsrmap[8] = { 0, TTY_PE, TTY_FE, TTY_PE|TTY_FE, TTY_FE, TTY_PE|TTY_FE, TTY_FE, TTY_PE|TTY_FE }; s = spltty(); if (comevents == 0) { splx(s); goto out; } comevents = 0; splx(s); for (unit = 0; unit < com_cd.cd_ndevs; unit++) { sc = com_cd.cd_devs[unit]; if (sc == 0 || sc->sc_ibufp == sc->sc_ibuf) continue; tp = sc->sc_tty; s = spltty(); ibufp = sc->sc_ibuf; ibufend = sc->sc_ibufp; if (ibufp == ibufend) { splx(s); continue; } sc->sc_ibufp = sc->sc_ibuf = (ibufp == sc->sc_ibufs[0]) ? sc->sc_ibufs[1] : sc->sc_ibufs[0]; sc->sc_ibufhigh = sc->sc_ibuf + COM_IHIGHWATER; sc->sc_ibufend = sc->sc_ibuf + COM_IBUFSIZE; if (tp == 0 || !ISSET(tp->t_state, TS_ISOPEN)) { splx(s); continue; } if (ISSET(tp->t_cflag, CRTSCTS) && !ISSET(sc->sc_mcr, MCR_RTS)) { /* XXX */ SET(sc->sc_mcr, MCR_RTS); bus_space_write_1(sc->sc_iot, sc->sc_ioh, com_mcr, sc->sc_mcr); } splx(s); while (ibufp < ibufend) { c = *ibufp++; if (*ibufp & LSR_OE) { sc->sc_overflows++; if (sc->sc_errors++ == 0) timeout(comdiag, sc, 60 * hz); } /* This is ugly, but fast. */ c |= lsrmap[(*ibufp++ & (LSR_BI|LSR_FE|LSR_PE)) >> 2]; (*linesw[tp->t_line].l_rint)(c, tp); } }out: timeout(compoll, NULL, 1);}intcomintr(arg) void *arg;{ struct com_softc *sc = arg; bus_space_tag_t iot = sc->sc_iot; bus_space_handle_t ioh = sc->sc_ioh; struct tty *tp; u_char lsr, data, msr, delta;#ifdef PPS_SYNC struct timeval tv; long usec;#endif /* PPS_SYNC */#ifdef COM_DEBUG int n; struct { u_char iir, lsr, msr; } iter[32];#endif if (!sc->sc_tty) return (0); /* can't do squat. */#ifdef COM_DEBUG n = 0; if (ISSET(iter[n].iir = bus_space_read_1(iot, ioh, com_iir), IIR_NOPEND)) return (0);#else if (ISSET(bus_space_read_1(iot, ioh, com_iir), IIR_NOPEND)) return (0);#endif tp = sc->sc_tty; for (;;) {#ifdef COM_DEBUG iter[n].lsr =#endif lsr = bus_space_read_1(iot, ioh, com_lsr); if (ISSET(lsr, LSR_RXRDY)) { register u_char *p = sc->sc_ibufp; comevents = 1; do { data = bus_space_read_1(iot, ioh, com_data); if (ISSET(lsr, LSR_BI)) {#ifdef notdef printf("break %02x %02x %02x %02x\n", sc->sc_msr, sc->sc_mcr, sc->sc_lcr, sc->sc_dtr);#endif#ifdef DDB if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) { if (db_console) Debugger(); goto next; }#endif data = 0; } if (p >= sc->sc_ibufend) { sc->sc_floods++; if (sc->sc_errors++ == 0) timeout(comdiag, sc, 60 * hz); } else { *p++ = data; *p++ = lsr; if (p == sc->sc_ibufhigh && ISSET(tp->t_cflag, CRTSCTS)) { /* XXX */ CLR(sc->sc_mcr, MCR_RTS); bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr); } }#ifdef DDB next:#endif#ifdef COM_DEBUG if (++n >= 32) goto ohfudge; iter[n].lsr =#endif lsr = bus_space_read_1(iot, ioh, com_lsr); } while (ISSET(lsr, LSR_RXRDY)); sc->sc_ibufp = p; }#ifdef COM_DEBUG else if (ISSET(lsr, LSR_BI|LSR_FE|LSR_PE|LSR_OE)) printf("weird lsr %02x\n", lsr);#endif#ifdef COM_DEBUG iter[n].msr =#endif msr = bus_space_read_1(iot, ioh, com_msr); if (msr != sc->sc_msr) { delta = msr ^ sc->sc_msr; sc->sc_msr = msr; if (ISSET(delta, MSR_DCD)) {#ifdef PPS_SYNC if (ISSET(sc->sc_swflags, COM_SW_PPS)) { if (ISSET(msr, MSR_DCD)) { usec = time.tv_usec; microtime(&tv); usec = tv.tv_usec - usec; if (usec < 0) usec += 1000000; hardpps(&tv, usec); } } else#endif /* PPS_SYNC */ if (!ISSET(sc->sc_swflags, COM_SW_SOFTCAR) && (*linesw[tp->t_line].l_modem)(tp, ISSET(msr, MSR_DCD)) == 0) { CLR(sc->sc_mcr, sc->sc_dtr); bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr); } } if (ISSET(delta & msr, MSR_CTS) && ISSET(tp->t_cflag, CRTSCTS)) { /* the line is up and we want to do rts/cts flow control */ (*linesw[tp->t_line].l_start)(tp); } } if (ISSET(lsr, LSR_TXRDY) && ISSET(tp->t_state, TS_BUSY)) { CLR(tp->t_state, TS_BUSY | TS_FLUSH); if (sc->sc_halt > 0) wakeup(&tp->t_outq); (*linesw[tp->t_line].l_start)(tp); }#ifdef COM_DEBUG if (++n >= 32) goto ohfudge; if (ISSET(iter[n].iir = bus_space_read_1(iot, ioh, com_iir), IIR_NOPEND)) return (1);#else if (ISSET(bus_space_read_1(iot, ioh, com_iir), IIR_NOPEND)) return (1);#endif }#ifdef COM_DEBUGohfudge: printf("comintr: too many iterations"); for (n = 0; n < 32; n++) { if ((n % 4) == 0) printf("\ncomintr: iter[%02d]", n); printf(" %02x %02x %02x", iter[n].iir, iter[n].lsr, iter[n].msr); } printf("\n"); printf("comintr: msr %02x mcr %02x lcr %02x ier %02x\n", sc->sc_msr, sc->sc_mcr, sc->sc_lcr, sc->sc_ier); printf("comintr: state %08x cc %d\n", sc->sc_tty->t_state, sc->sc_tty->t_outq.c_cc);#endif}/* * Following are all routines needed for COM to act as console */#include <dev/cons.h>#ifdef arc#undef CONADDR extern int CONADDR;#endifvoidcomcnprobe(cp) struct consdev *cp;{ /* XXX NEEDS TO BE FIXED XXX */#ifdef arc bus_space_tag_t iot = &arc_bus_io;#else#ifdef powerpc bus_space_tag_t iot = &p4e_isa_io;#else bus_space_tag_t iot = 0;#endif #endif bus_space_handle_t ioh; int found; if(CONADDR == 0) { cp->cn_pri = CN_DEAD; return; } comconsiot = iot; if (bus_space_map(iot, CONADDR, COM_NPORTS, 0, &ioh)) { cp->cn_pri = CN_DEAD; return; } found = comprobe1(iot, ioh); bus_space_unmap(iot, ioh, COM_NPORTS); if (!found) { cp->cn_pri = CN_DEAD; return; } /* locate the major number */ for (commajor = 0; commajor < nchrdev; commajor++) if (cdevsw[commajor].d_open == comopen) break; /* initialize required fields */ cp->cn_dev = makedev(commajor, CONUNIT);#ifdef COMCONSOLE cp->cn_pri = CN_REMOTE; /* Force a serial port console */#else cp->cn_pri = CN_NORMAL;#endif}voidcomcninit(cp) struct consdev *cp;{ if (bus_space_map(comconsiot, CONADDR, COM_NPORTS, 0, &comconsioh)) panic("comcninit: mapping failed"); cominit(comconsiot, comconsioh, comdefaultrate); comconsaddr = CONADDR; comconsinit = 0;}voidcominit(iot, ioh, rate) bus_space_tag_t iot; bus_space_handle_t ioh; int rate;{ int s = splhigh(); u_char stat; bus_space_write_1(iot, ioh, com_lcr, LCR_DLAB); rate = comspeed(comdefaultrate); bus_space_write_1(iot, ioh, com_dlbl, rate); bus_space_write_1(iot, ioh, com_dlbh, rate >> 8); bus_space_write_1(iot, ioh, com_lcr, LCR_8BITS); bus_space_write_1(iot, ioh, com_ier, IER_ERXRDY | IER_ETXRDY); bus_space_write_1(iot, ioh, com_fifo, FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_4); stat = bus_space_read_1(iot, ioh, com_iir); splx(s);}intcomcngetc(dev) dev_t dev;{ int s = splhigh(); bus_space_tag_t iot = comconsiot; bus_space_handle_t ioh = comconsioh; u_char stat, c; while (!ISSET(stat = bus_space_read_1(iot, ioh, com_lsr), LSR_RXRDY)) ; c = bus_space_read_1(iot, ioh, com_data); stat = bus_space_read_1(iot, ioh, com_iir); splx(s); return c;}/* * Console kernel output character routine. */voidcomcnputc(dev, c) dev_t dev; int c;{ int s = splhigh(); bus_space_tag_t iot = comconsiot; bus_space_handle_t ioh = comconsioh; u_char stat; register int timo;#ifdef KGDB if (dev != kgdb_dev)#endif if (comconsinit == 0) { cominit(iot, ioh, comdefaultrate); comconsinit = 1; } /* wait for any pending transmission to finish */ timo = 50000; while (!ISSET(stat = bus_space_read_1(iot, ioh, com_lsr), LSR_TXRDY) && --timo) ; bus_space_write_1(iot, ioh, com_data, c); /* wait for this transmission to complete */ timo = 1500000; while (!ISSET(stat = bus_space_read_1(iot, ioh, com_lsr), LSR_TXRDY) && --timo) ;#if 0 /* I don't think sooooo (pefo) */ /* clear any interrupts generated by this transmission */ stat = bus_space_read_1(iot, ioh, com_iir);#endif splx(s);}voidcomcnpollc(dev, on) dev_t dev; int on;{}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -