diff options
Diffstat (limited to 'sys/dev/uart/uart_tty.c')
-rw-r--r-- | sys/dev/uart/uart_tty.c | 165 |
1 files changed, 72 insertions, 93 deletions
diff --git a/sys/dev/uart/uart_tty.c b/sys/dev/uart/uart_tty.c index 1971049..9b37bb3 100644 --- a/sys/dev/uart/uart_tty.c +++ b/sys/dev/uart/uart_tty.c @@ -123,11 +123,11 @@ uart_cngetc(struct consdev *cp) } static int -uart_tty_open(struct tty *tp, struct cdev *dev) +uart_tty_open(struct tty *tp) { struct uart_softc *sc; - sc = tp->t_sc; + sc = tty_softc(tp); if (sc == NULL || sc->sc_leaving) return (ENXIO); @@ -141,7 +141,7 @@ uart_tty_close(struct tty *tp) { struct uart_softc *sc; - sc = tp->t_sc; + sc = tty_softc(tp); if (sc == NULL || sc->sc_leaving || !sc->sc_opened) return; @@ -158,11 +158,11 @@ uart_tty_close(struct tty *tp) } static void -uart_tty_oproc(struct tty *tp) +uart_tty_outwakeup(struct tty *tp) { struct uart_softc *sc; - sc = tp->t_sc; + sc = tty_softc(tp); if (sc == NULL || sc->sc_leaving) return; @@ -173,30 +173,45 @@ uart_tty_oproc(struct tty *tp) * de-assert RTS for us. In that situation we're completely stuffed. * Without hardware support, we need to toggle RTS ourselves. */ - if ((tp->t_cflag & CRTS_IFLOW) && !sc->sc_hwiflow) { - if ((tp->t_state & TS_TBLOCK) && + if ((tp->t_termios.c_cflag & CRTS_IFLOW) && !sc->sc_hwiflow) { +#if 0 + /*if ((tp->t_state & TS_TBLOCK) && (sc->sc_hwsig & SER_RTS)) UART_SETSIG(sc, SER_DRTS); - else if (!(tp->t_state & TS_TBLOCK) && + else */ if (/*!(tp->t_state & TS_TBLOCK) &&*/ !(sc->sc_hwsig & SER_RTS)) UART_SETSIG(sc, SER_DRTS|SER_RTS); +#endif + /* XXX: we should use inwakeup to implement this! */ + if (!(sc->sc_hwsig & SER_RTS)) + UART_SETSIG(sc, SER_DRTS|SER_RTS); } - if (tp->t_state & TS_TTSTOP) + if (sc->sc_txbusy) return; - if ((tp->t_state & TS_BUSY) || sc->sc_txbusy) - return; + sc->sc_txdatasz = ttydisc_getc(tp, sc->sc_txbuf, sc->sc_txfifosz); + if (sc->sc_txdatasz != 0) + UART_TRANSMIT(sc); +} - if (tp->t_outq.c_cc == 0) { - ttwwakeup(tp); - return; - } +static int +uart_tty_ioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td) +{ + struct uart_softc *sc; + + sc = tty_softc(tp); - sc->sc_txdatasz = q_to_b(&tp->t_outq, sc->sc_txbuf, sc->sc_txfifosz); - tp->t_state |= TS_BUSY; - UART_TRANSMIT(sc); - ttwwakeup(tp); + switch (cmd) { + case TIOCSBRK: + UART_IOCTL(sc, UART_IOCTL_BREAK, 1); + return (0); + case TIOCCBRK: + UART_IOCTL(sc, UART_IOCTL_BREAK, 0); + return (0); + default: + return pps_ioctl(cmd, data, &sc->sc_pps); + } } static int @@ -205,7 +220,7 @@ uart_tty_param(struct tty *tp, struct termios *t) struct uart_softc *sc; int databits, parity, stopbits; - sc = tp->t_sc; + sc = tty_softc(tp); if (sc == NULL || sc->sc_leaving) return (ENODEV); if (t->c_ispeed != t->c_ospeed && t->c_ospeed != 0) @@ -237,16 +252,16 @@ uart_tty_param(struct tty *tp, struct termios *t) UART_SETSIG(sc, SER_DDTR | SER_DTR); /* Set input flow control state. */ if (!sc->sc_hwiflow) { - if ((t->c_cflag & CRTS_IFLOW) && (tp->t_state & TS_TBLOCK)) + /* if ((t->c_cflag & CRTS_IFLOW) && (tp->t_state & TS_TBLOCK)) UART_SETSIG(sc, SER_DRTS); - else + else */ UART_SETSIG(sc, SER_DRTS | SER_RTS); } else UART_IOCTL(sc, UART_IOCTL_IFLOW, (t->c_cflag & CRTS_IFLOW)); /* Set output flow control state. */ if (sc->sc_hwoflow) UART_IOCTL(sc, UART_IOCTL_OFLOW, (t->c_cflag & CCTS_OFLOW)); - ttsetwater(tp); + return (0); } @@ -255,48 +270,18 @@ uart_tty_modem(struct tty *tp, int biton, int bitoff) { struct uart_softc *sc; - sc = tp->t_sc; + sc = tty_softc(tp); if (biton != 0 || bitoff != 0) UART_SETSIG(sc, SER_DELTA(bitoff|biton) | biton); return (sc->sc_hwsig); } -static void -uart_tty_break(struct tty *tp, int state) -{ - struct uart_softc *sc; - - sc = tp->t_sc; - UART_IOCTL(sc, UART_IOCTL_BREAK, state); -} - -static void -uart_tty_stop(struct tty *tp, int rw) -{ - struct uart_softc *sc; - - sc = tp->t_sc; - if (sc == NULL || sc->sc_leaving) - return; - if (rw & FWRITE) { - if (sc->sc_txbusy) { - sc->sc_txbusy = 0; - UART_FLUSH(sc, UART_FLUSH_TRANSMITTER); - } - tp->t_state &= ~TS_BUSY; - } - if (rw & FREAD) { - UART_FLUSH(sc, UART_FLUSH_RECEIVER); - sc->sc_rxget = sc->sc_rxput = 0; - } -} - void uart_tty_intr(void *arg) { struct uart_softc *sc = arg; struct tty *tp; - int c, pend, sig, xc; + int c, err = 0, pend, sig, xc; if (sc->sc_leaving) return; @@ -306,78 +291,72 @@ uart_tty_intr(void *arg) return; tp = sc->sc_u.u_tty.tp; + tty_lock(tp); if (pend & SER_INT_RXREADY) { - while (!uart_rx_empty(sc) && !(tp->t_state & TS_TBLOCK)) { + while (!uart_rx_empty(sc) /* && !(tp->t_state & TS_TBLOCK)*/) { xc = uart_rx_get(sc); c = xc & 0xff; if (xc & UART_STAT_FRAMERR) - c |= TTY_FE; + err |= TRE_FRAMING; if (xc & UART_STAT_OVERRUN) - c |= TTY_OE; + err |= TRE_OVERRUN; if (xc & UART_STAT_PARERR) - c |= TTY_PE; - ttyld_rint(tp, c); + err |= TRE_PARITY; + ttydisc_rint(tp, c, err); } } - if (pend & SER_INT_BREAK) { - if (tp != NULL && !(tp->t_iflag & IGNBRK)) - ttyld_rint(tp, 0); - } + if (pend & SER_INT_BREAK) + ttydisc_rint(tp, 0, TRE_BREAK); if (pend & SER_INT_SIGCHG) { sig = pend & SER_INT_SIGMASK; if (sig & SER_DDCD) - ttyld_modem(tp, sig & SER_DCD); - if ((sig & SER_DCTS) && (tp->t_cflag & CCTS_OFLOW) && + ttydisc_modem(tp, sig & SER_DCD); + if ((sig & SER_DCTS) && (tp->t_termios.c_cflag & CCTS_OFLOW) && !sc->sc_hwoflow) { - if (sig & SER_CTS) { - tp->t_state &= ~TS_TTSTOP; - ttyld_start(tp); - } else - tp->t_state |= TS_TTSTOP; + if (sig & SER_CTS) + uart_tty_outwakeup(tp); } } - if (pend & SER_INT_TXIDLE) { - tp->t_state &= ~TS_BUSY; - ttyld_start(tp); - } + if (pend & SER_INT_TXIDLE) + uart_tty_outwakeup(tp); + ttydisc_rint_done(tp); + tty_unlock(tp); } +static struct ttydevsw uart_tty_class = { + .tsw_flags = TF_INITLOCK|TF_CALLOUT, + .tsw_open = uart_tty_open, + .tsw_close = uart_tty_close, + .tsw_outwakeup = uart_tty_outwakeup, + .tsw_ioctl = uart_tty_ioctl, + .tsw_param = uart_tty_param, + .tsw_modem = uart_tty_modem, +}; + int uart_tty_attach(struct uart_softc *sc) { struct tty *tp; int unit; - tp = ttyalloc(); - sc->sc_u.u_tty.tp = tp; - tp->t_sc = sc; + sc->sc_u.u_tty.tp = tp = tty_alloc(&uart_tty_class, sc, NULL); unit = device_get_unit(sc->sc_dev); - tp->t_oproc = uart_tty_oproc; - tp->t_param = uart_tty_param; - tp->t_stop = uart_tty_stop; - tp->t_modem = uart_tty_modem; - tp->t_break = uart_tty_break; - tp->t_open = uart_tty_open; - tp->t_close = uart_tty_close; - - tp->t_pps = &sc->sc_pps; - if (sc->sc_sysdev != NULL && sc->sc_sysdev->type == UART_DEV_CONSOLE) { sprintf(((struct consdev *)sc->sc_sysdev->cookie)->cn_name, "ttyu%r", unit); - ttyconsolemode(tp, 0); + tty_init_console(tp, 0); } swi_add(&tty_intr_event, uart_driver_name, uart_tty_intr, sc, SWI_TTY, INTR_TYPE_TTY, &sc->sc_softih); - ttycreate(tp, TS_CALLOUT, "u%r", unit); + tty_makedev(tp, NULL, "u%r", unit); return (0); } @@ -387,10 +366,10 @@ int uart_tty_detach(struct uart_softc *sc) struct tty *tp; tp = sc->sc_u.u_tty.tp; - tp->t_pps = NULL; - ttygone(tp); + + tty_lock(tp); swi_remove(sc->sc_softih); - ttyfree(tp); + tty_rel_gone(tp); return (0); } |