127d5dc18SMarcel Moolenaar /* 227d5dc18SMarcel Moolenaar * Copyright (c) 2003 Marcel Moolenaar 327d5dc18SMarcel Moolenaar * All rights reserved. 427d5dc18SMarcel Moolenaar * 527d5dc18SMarcel Moolenaar * Redistribution and use in source and binary forms, with or without 627d5dc18SMarcel Moolenaar * modification, are permitted provided that the following conditions 727d5dc18SMarcel Moolenaar * are met: 827d5dc18SMarcel Moolenaar * 927d5dc18SMarcel Moolenaar * 1. Redistributions of source code must retain the above copyright 1027d5dc18SMarcel Moolenaar * notice, this list of conditions and the following disclaimer. 1127d5dc18SMarcel Moolenaar * 2. Redistributions in binary form must reproduce the above copyright 1227d5dc18SMarcel Moolenaar * notice, this list of conditions and the following disclaimer in the 1327d5dc18SMarcel Moolenaar * documentation and/or other materials provided with the distribution. 1427d5dc18SMarcel Moolenaar * 1527d5dc18SMarcel Moolenaar * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1627d5dc18SMarcel Moolenaar * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1727d5dc18SMarcel Moolenaar * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1827d5dc18SMarcel Moolenaar * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1927d5dc18SMarcel Moolenaar * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2027d5dc18SMarcel Moolenaar * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2127d5dc18SMarcel Moolenaar * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2227d5dc18SMarcel Moolenaar * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2327d5dc18SMarcel Moolenaar * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2427d5dc18SMarcel Moolenaar * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2527d5dc18SMarcel Moolenaar */ 2627d5dc18SMarcel Moolenaar 2727d5dc18SMarcel Moolenaar #include <sys/cdefs.h> 2827d5dc18SMarcel Moolenaar __FBSDID("$FreeBSD$"); 2927d5dc18SMarcel Moolenaar 3027d5dc18SMarcel Moolenaar #include <sys/param.h> 3127d5dc18SMarcel Moolenaar #include <sys/systm.h> 3227d5dc18SMarcel Moolenaar #include <sys/bus.h> 3327d5dc18SMarcel Moolenaar #include <sys/conf.h> 3427d5dc18SMarcel Moolenaar #include <sys/cons.h> 3527d5dc18SMarcel Moolenaar #include <sys/fcntl.h> 3627d5dc18SMarcel Moolenaar #include <sys/interrupt.h> 3727d5dc18SMarcel Moolenaar #include <sys/kernel.h> 3827d5dc18SMarcel Moolenaar #include <sys/malloc.h> 3927d5dc18SMarcel Moolenaar #include <sys/reboot.h> 4027d5dc18SMarcel Moolenaar #include <machine/bus.h> 4127d5dc18SMarcel Moolenaar #include <sys/rman.h> 4227d5dc18SMarcel Moolenaar #include <sys/termios.h> 4327d5dc18SMarcel Moolenaar #include <sys/tty.h> 4427d5dc18SMarcel Moolenaar #include <machine/resource.h> 4527d5dc18SMarcel Moolenaar #include <machine/stdarg.h> 4627d5dc18SMarcel Moolenaar 4727d5dc18SMarcel Moolenaar #include <dev/uart/uart.h> 4827d5dc18SMarcel Moolenaar #include <dev/uart/uart_bus.h> 4927d5dc18SMarcel Moolenaar #include <dev/uart/uart_cpu.h> 5027d5dc18SMarcel Moolenaar 5127d5dc18SMarcel Moolenaar #include "uart_if.h" 5227d5dc18SMarcel Moolenaar 5327d5dc18SMarcel Moolenaar static cn_probe_t uart_cnprobe; 5427d5dc18SMarcel Moolenaar static cn_init_t uart_cninit; 5527d5dc18SMarcel Moolenaar static cn_term_t uart_cnterm; 5627d5dc18SMarcel Moolenaar static cn_getc_t uart_cngetc; 5727d5dc18SMarcel Moolenaar static cn_checkc_t uart_cncheckc; 5827d5dc18SMarcel Moolenaar static cn_putc_t uart_cnputc; 5927d5dc18SMarcel Moolenaar 6027d5dc18SMarcel Moolenaar CONS_DRIVER(uart, uart_cnprobe, uart_cninit, uart_cnterm, uart_cngetc, 6127d5dc18SMarcel Moolenaar uart_cncheckc, uart_cnputc, NULL); 6227d5dc18SMarcel Moolenaar 6327d5dc18SMarcel Moolenaar static struct uart_devinfo uart_console; 6427d5dc18SMarcel Moolenaar 6527d5dc18SMarcel Moolenaar static void 6627d5dc18SMarcel Moolenaar uart_cnprobe(struct consdev *cp) 6727d5dc18SMarcel Moolenaar { 6827d5dc18SMarcel Moolenaar 6927d5dc18SMarcel Moolenaar cp->cn_pri = CN_DEAD; 7027d5dc18SMarcel Moolenaar 7127d5dc18SMarcel Moolenaar KASSERT(uart_console.cookie == NULL, ("foo")); 7227d5dc18SMarcel Moolenaar 7327d5dc18SMarcel Moolenaar if (uart_cpu_getdev(UART_DEV_CONSOLE, &uart_console)) 7427d5dc18SMarcel Moolenaar return; 7527d5dc18SMarcel Moolenaar 7627d5dc18SMarcel Moolenaar if (uart_probe(&uart_console)) 7727d5dc18SMarcel Moolenaar return; 7827d5dc18SMarcel Moolenaar 7927d5dc18SMarcel Moolenaar cp->cn_pri = (boothowto & RB_SERIAL) ? CN_REMOTE : CN_NORMAL; 8027d5dc18SMarcel Moolenaar cp->cn_arg = &uart_console; 8127d5dc18SMarcel Moolenaar } 8227d5dc18SMarcel Moolenaar 8327d5dc18SMarcel Moolenaar static void 8427d5dc18SMarcel Moolenaar uart_cninit(struct consdev *cp) 8527d5dc18SMarcel Moolenaar { 8627d5dc18SMarcel Moolenaar struct uart_devinfo *di; 8727d5dc18SMarcel Moolenaar 8827d5dc18SMarcel Moolenaar /* 8927d5dc18SMarcel Moolenaar * Yedi trick: we need to be able to define cn_dev before we go 9027d5dc18SMarcel Moolenaar * single- or multi-user. The problem is that we don't know at 9127d5dc18SMarcel Moolenaar * this time what the device will be. Hence, we need to link from 9227d5dc18SMarcel Moolenaar * the uart_devinfo to the consdev that corresponds to it so that 9327d5dc18SMarcel Moolenaar * we can define cn_dev in uart_bus_attach() when we find the 9427d5dc18SMarcel Moolenaar * device during bus enumeration. That's when we'll know what the 9527d5dc18SMarcel Moolenaar * the unit number will be. 9627d5dc18SMarcel Moolenaar */ 9727d5dc18SMarcel Moolenaar di = cp->cn_arg; 9827d5dc18SMarcel Moolenaar KASSERT(di->cookie == NULL, ("foo")); 9927d5dc18SMarcel Moolenaar di->cookie = cp; 10027d5dc18SMarcel Moolenaar di->type = UART_DEV_CONSOLE; 10127d5dc18SMarcel Moolenaar uart_add_sysdev(di); 10227d5dc18SMarcel Moolenaar uart_init(di); 10327d5dc18SMarcel Moolenaar } 10427d5dc18SMarcel Moolenaar 10527d5dc18SMarcel Moolenaar static void 10627d5dc18SMarcel Moolenaar uart_cnterm(struct consdev *cp) 10727d5dc18SMarcel Moolenaar { 10827d5dc18SMarcel Moolenaar 10927d5dc18SMarcel Moolenaar uart_term(cp->cn_arg); 11027d5dc18SMarcel Moolenaar } 11127d5dc18SMarcel Moolenaar 11227d5dc18SMarcel Moolenaar static void 11327d5dc18SMarcel Moolenaar uart_cnputc(struct consdev *cp, int c) 11427d5dc18SMarcel Moolenaar { 11527d5dc18SMarcel Moolenaar 11627d5dc18SMarcel Moolenaar uart_putc(cp->cn_arg, c); 11727d5dc18SMarcel Moolenaar } 11827d5dc18SMarcel Moolenaar 11927d5dc18SMarcel Moolenaar static int 12027d5dc18SMarcel Moolenaar uart_cncheckc(struct consdev *cp) 12127d5dc18SMarcel Moolenaar { 12227d5dc18SMarcel Moolenaar 12327d5dc18SMarcel Moolenaar return (uart_poll(cp->cn_arg)); 12427d5dc18SMarcel Moolenaar } 12527d5dc18SMarcel Moolenaar 12627d5dc18SMarcel Moolenaar static int 12727d5dc18SMarcel Moolenaar uart_cngetc(struct consdev *cp) 12827d5dc18SMarcel Moolenaar { 12927d5dc18SMarcel Moolenaar 13027d5dc18SMarcel Moolenaar return (uart_getc(cp->cn_arg)); 13127d5dc18SMarcel Moolenaar } 13227d5dc18SMarcel Moolenaar 13379a8d927SPoul-Henning Kamp static int 13479a8d927SPoul-Henning Kamp uart_tty_open(struct tty *tp, struct cdev *dev) 13579a8d927SPoul-Henning Kamp { 13679a8d927SPoul-Henning Kamp struct uart_softc *sc; 13779a8d927SPoul-Henning Kamp 13879a8d927SPoul-Henning Kamp sc = tp->t_sc; 13979a8d927SPoul-Henning Kamp sc->sc_opened = 1; 14079a8d927SPoul-Henning Kamp return (0); 14179a8d927SPoul-Henning Kamp } 14279a8d927SPoul-Henning Kamp 14379a8d927SPoul-Henning Kamp static void 14479a8d927SPoul-Henning Kamp uart_tty_close(struct tty *tp) 14579a8d927SPoul-Henning Kamp { 14679a8d927SPoul-Henning Kamp struct uart_softc *sc; 14779a8d927SPoul-Henning Kamp 14879a8d927SPoul-Henning Kamp sc = tp->t_sc; 14979a8d927SPoul-Henning Kamp if (sc == NULL || sc->sc_leaving) 15079a8d927SPoul-Henning Kamp return; 15179a8d927SPoul-Henning Kamp if (!sc->sc_opened) { 15279a8d927SPoul-Henning Kamp KASSERT(!(tp->t_state & TS_ISOPEN), ("foo")); 15379a8d927SPoul-Henning Kamp return; 15479a8d927SPoul-Henning Kamp } 15579a8d927SPoul-Henning Kamp KASSERT(tp->t_state & TS_ISOPEN, ("foo")); 15679a8d927SPoul-Henning Kamp 15779a8d927SPoul-Henning Kamp if (sc->sc_hwiflow) 15879a8d927SPoul-Henning Kamp UART_IOCTL(sc, UART_IOCTL_IFLOW, 0); 15979a8d927SPoul-Henning Kamp if (sc->sc_hwoflow) 16079a8d927SPoul-Henning Kamp UART_IOCTL(sc, UART_IOCTL_OFLOW, 0); 16179a8d927SPoul-Henning Kamp if (sc->sc_sysdev == NULL) 16279a8d927SPoul-Henning Kamp UART_SETSIG(sc, SER_DDTR | SER_DRTS); 16379a8d927SPoul-Henning Kamp 16479a8d927SPoul-Henning Kamp wakeup(sc); 16579a8d927SPoul-Henning Kamp KASSERT(!(tp->t_state & TS_ISOPEN), ("foo")); 16679a8d927SPoul-Henning Kamp sc->sc_opened = 0; 16779a8d927SPoul-Henning Kamp return; 16879a8d927SPoul-Henning Kamp } 16979a8d927SPoul-Henning Kamp 17027d5dc18SMarcel Moolenaar static void 17127d5dc18SMarcel Moolenaar uart_tty_oproc(struct tty *tp) 17227d5dc18SMarcel Moolenaar { 17327d5dc18SMarcel Moolenaar struct uart_softc *sc; 17427d5dc18SMarcel Moolenaar 1759e51d6f1SPoul-Henning Kamp sc = tp->t_sc; 17627d5dc18SMarcel Moolenaar if (sc == NULL || sc->sc_leaving) 17727d5dc18SMarcel Moolenaar return; 17827d5dc18SMarcel Moolenaar 17927d5dc18SMarcel Moolenaar /* 18027d5dc18SMarcel Moolenaar * Handle input flow control. Note that if we have hardware support, 18127d5dc18SMarcel Moolenaar * we don't do anything here. We continue to receive until our buffer 18227d5dc18SMarcel Moolenaar * is full. At that time we cannot empty the UART itself and it will 18327d5dc18SMarcel Moolenaar * de-assert RTS for us. In that situation we're completely stuffed. 18427d5dc18SMarcel Moolenaar * Without hardware support, we need to toggle RTS ourselves. 18527d5dc18SMarcel Moolenaar */ 18627d5dc18SMarcel Moolenaar if ((tp->t_cflag & CRTS_IFLOW) && !sc->sc_hwiflow) { 18727d5dc18SMarcel Moolenaar if ((tp->t_state & TS_TBLOCK) && 18828710806SPoul-Henning Kamp (sc->sc_hwsig & SER_RTS)) 18928710806SPoul-Henning Kamp UART_SETSIG(sc, SER_DRTS); 19027d5dc18SMarcel Moolenaar else if (!(tp->t_state & TS_TBLOCK) && 19128710806SPoul-Henning Kamp !(sc->sc_hwsig & SER_RTS)) 19228710806SPoul-Henning Kamp UART_SETSIG(sc, SER_DRTS|SER_RTS); 19327d5dc18SMarcel Moolenaar } 19427d5dc18SMarcel Moolenaar 19527d5dc18SMarcel Moolenaar if (tp->t_state & TS_TTSTOP) 19627d5dc18SMarcel Moolenaar return; 19727d5dc18SMarcel Moolenaar 19827d5dc18SMarcel Moolenaar if ((tp->t_state & TS_BUSY) || sc->sc_txbusy) 19927d5dc18SMarcel Moolenaar return; 20027d5dc18SMarcel Moolenaar 20127d5dc18SMarcel Moolenaar if (tp->t_outq.c_cc == 0) { 20227d5dc18SMarcel Moolenaar ttwwakeup(tp); 20327d5dc18SMarcel Moolenaar return; 20427d5dc18SMarcel Moolenaar } 20527d5dc18SMarcel Moolenaar 20627d5dc18SMarcel Moolenaar sc->sc_txdatasz = q_to_b(&tp->t_outq, sc->sc_txbuf, sc->sc_txfifosz); 20727d5dc18SMarcel Moolenaar tp->t_state |= TS_BUSY; 20827d5dc18SMarcel Moolenaar UART_TRANSMIT(sc); 20927d5dc18SMarcel Moolenaar ttwwakeup(tp); 21027d5dc18SMarcel Moolenaar } 21127d5dc18SMarcel Moolenaar 21227d5dc18SMarcel Moolenaar static int 21327d5dc18SMarcel Moolenaar uart_tty_param(struct tty *tp, struct termios *t) 21427d5dc18SMarcel Moolenaar { 21527d5dc18SMarcel Moolenaar struct uart_softc *sc; 21627d5dc18SMarcel Moolenaar int databits, parity, stopbits; 21727d5dc18SMarcel Moolenaar 2189e51d6f1SPoul-Henning Kamp sc = tp->t_sc; 21927d5dc18SMarcel Moolenaar if (sc == NULL || sc->sc_leaving) 22027d5dc18SMarcel Moolenaar return (ENODEV); 22127d5dc18SMarcel Moolenaar if (t->c_ispeed != t->c_ospeed && t->c_ospeed != 0) 22227d5dc18SMarcel Moolenaar return (EINVAL); 22327d5dc18SMarcel Moolenaar /* Fixate certain parameters for system devices. */ 22427d5dc18SMarcel Moolenaar if (sc->sc_sysdev != NULL) { 22527d5dc18SMarcel Moolenaar t->c_ispeed = t->c_ospeed = sc->sc_sysdev->baudrate; 22627d5dc18SMarcel Moolenaar t->c_cflag |= CLOCAL; 22727d5dc18SMarcel Moolenaar t->c_cflag &= ~HUPCL; 22827d5dc18SMarcel Moolenaar } 22927d5dc18SMarcel Moolenaar if (t->c_ospeed == 0) { 23028710806SPoul-Henning Kamp UART_SETSIG(sc, SER_DDTR | SER_DRTS); 23127d5dc18SMarcel Moolenaar return (0); 23227d5dc18SMarcel Moolenaar } 23327d5dc18SMarcel Moolenaar switch (t->c_cflag & CSIZE) { 23427d5dc18SMarcel Moolenaar case CS5: databits = 5; break; 23527d5dc18SMarcel Moolenaar case CS6: databits = 6; break; 23627d5dc18SMarcel Moolenaar case CS7: databits = 7; break; 23727d5dc18SMarcel Moolenaar default: databits = 8; break; 23827d5dc18SMarcel Moolenaar } 23927d5dc18SMarcel Moolenaar stopbits = (t->c_cflag & CSTOPB) ? 2 : 1; 24027d5dc18SMarcel Moolenaar if (t->c_cflag & PARENB) 24127d5dc18SMarcel Moolenaar parity = (t->c_cflag & PARODD) ? UART_PARITY_ODD 24227d5dc18SMarcel Moolenaar : UART_PARITY_EVEN; 24327d5dc18SMarcel Moolenaar else 24427d5dc18SMarcel Moolenaar parity = UART_PARITY_NONE; 245b662bdc2SMarcel Moolenaar if (UART_PARAM(sc, t->c_ospeed, databits, stopbits, parity) != 0) 246b662bdc2SMarcel Moolenaar return (EINVAL); 24728710806SPoul-Henning Kamp UART_SETSIG(sc, SER_DDTR | SER_DTR); 24827d5dc18SMarcel Moolenaar /* Set input flow control state. */ 24927d5dc18SMarcel Moolenaar if (!sc->sc_hwiflow) { 25027d5dc18SMarcel Moolenaar if ((t->c_cflag & CRTS_IFLOW) && (tp->t_state & TS_TBLOCK)) 25128710806SPoul-Henning Kamp UART_SETSIG(sc, SER_DRTS); 25227d5dc18SMarcel Moolenaar else 25328710806SPoul-Henning Kamp UART_SETSIG(sc, SER_DRTS | SER_RTS); 25427d5dc18SMarcel Moolenaar } else 25527d5dc18SMarcel Moolenaar UART_IOCTL(sc, UART_IOCTL_IFLOW, (t->c_cflag & CRTS_IFLOW)); 25627d5dc18SMarcel Moolenaar /* Set output flow control state. */ 25727d5dc18SMarcel Moolenaar if (sc->sc_hwoflow) 25827d5dc18SMarcel Moolenaar UART_IOCTL(sc, UART_IOCTL_OFLOW, (t->c_cflag & CCTS_OFLOW)); 25927d5dc18SMarcel Moolenaar ttsetwater(tp); 26027d5dc18SMarcel Moolenaar return (0); 26127d5dc18SMarcel Moolenaar } 26227d5dc18SMarcel Moolenaar 26396df2b0bSPoul-Henning Kamp static int 26496df2b0bSPoul-Henning Kamp uart_tty_modem(struct tty *tp, int biton, int bitoff) 26596df2b0bSPoul-Henning Kamp { 26696df2b0bSPoul-Henning Kamp struct uart_softc *sc; 26796df2b0bSPoul-Henning Kamp 2689e51d6f1SPoul-Henning Kamp sc = tp->t_sc; 26996df2b0bSPoul-Henning Kamp if (biton != 0 || bitoff != 0) 27096df2b0bSPoul-Henning Kamp UART_SETSIG(sc, SER_DELTA(bitoff|biton) | biton); 27196df2b0bSPoul-Henning Kamp return (sc->sc_hwsig); 27296df2b0bSPoul-Henning Kamp } 27396df2b0bSPoul-Henning Kamp 274b4994e31SPoul-Henning Kamp static void 27596df2b0bSPoul-Henning Kamp uart_tty_break(struct tty *tp, int state) 27696df2b0bSPoul-Henning Kamp { 27796df2b0bSPoul-Henning Kamp struct uart_softc *sc; 27896df2b0bSPoul-Henning Kamp 2799e51d6f1SPoul-Henning Kamp sc = tp->t_sc; 28096df2b0bSPoul-Henning Kamp UART_IOCTL(sc, UART_IOCTL_BREAK, state); 28196df2b0bSPoul-Henning Kamp } 28296df2b0bSPoul-Henning Kamp 28327d5dc18SMarcel Moolenaar static void 28427d5dc18SMarcel Moolenaar uart_tty_stop(struct tty *tp, int rw) 28527d5dc18SMarcel Moolenaar { 28627d5dc18SMarcel Moolenaar struct uart_softc *sc; 28727d5dc18SMarcel Moolenaar 2889e51d6f1SPoul-Henning Kamp sc = tp->t_sc; 28927d5dc18SMarcel Moolenaar if (sc == NULL || sc->sc_leaving) 29027d5dc18SMarcel Moolenaar return; 29127d5dc18SMarcel Moolenaar if (rw & FWRITE) { 29227d5dc18SMarcel Moolenaar if (sc->sc_txbusy) { 29327d5dc18SMarcel Moolenaar sc->sc_txbusy = 0; 29427d5dc18SMarcel Moolenaar UART_FLUSH(sc, UART_FLUSH_TRANSMITTER); 29527d5dc18SMarcel Moolenaar } 29627d5dc18SMarcel Moolenaar tp->t_state &= ~TS_BUSY; 29727d5dc18SMarcel Moolenaar } 29827d5dc18SMarcel Moolenaar if (rw & FREAD) { 29927d5dc18SMarcel Moolenaar UART_FLUSH(sc, UART_FLUSH_RECEIVER); 30027d5dc18SMarcel Moolenaar sc->sc_rxget = sc->sc_rxput = 0; 30127d5dc18SMarcel Moolenaar } 30227d5dc18SMarcel Moolenaar } 30327d5dc18SMarcel Moolenaar 30427d5dc18SMarcel Moolenaar void 30527d5dc18SMarcel Moolenaar uart_tty_intr(void *arg) 30627d5dc18SMarcel Moolenaar { 30727d5dc18SMarcel Moolenaar struct uart_softc *sc = arg; 30827d5dc18SMarcel Moolenaar struct tty *tp; 30927d5dc18SMarcel Moolenaar int c, pend, sig, xc; 31027d5dc18SMarcel Moolenaar 31127d5dc18SMarcel Moolenaar if (sc->sc_leaving) 31227d5dc18SMarcel Moolenaar return; 31327d5dc18SMarcel Moolenaar 31427d5dc18SMarcel Moolenaar pend = atomic_readandclear_32(&sc->sc_ttypend); 31527d5dc18SMarcel Moolenaar if (!(pend & UART_IPEND_MASK)) 31627d5dc18SMarcel Moolenaar return; 31727d5dc18SMarcel Moolenaar 31827d5dc18SMarcel Moolenaar tp = sc->sc_u.u_tty.tp; 31927d5dc18SMarcel Moolenaar 32027d5dc18SMarcel Moolenaar if (pend & UART_IPEND_RXREADY) { 32127d5dc18SMarcel Moolenaar while (!uart_rx_empty(sc) && !(tp->t_state & TS_TBLOCK)) { 32227d5dc18SMarcel Moolenaar xc = uart_rx_get(sc); 32327d5dc18SMarcel Moolenaar c = xc & 0xff; 32427d5dc18SMarcel Moolenaar if (xc & UART_STAT_FRAMERR) 32527d5dc18SMarcel Moolenaar c |= TTY_FE; 32627d5dc18SMarcel Moolenaar if (xc & UART_STAT_PARERR) 32727d5dc18SMarcel Moolenaar c |= TTY_PE; 3282140d01bSPoul-Henning Kamp ttyld_rint(tp, c); 32927d5dc18SMarcel Moolenaar } 33027d5dc18SMarcel Moolenaar } 33127d5dc18SMarcel Moolenaar 33227d5dc18SMarcel Moolenaar if (pend & UART_IPEND_BREAK) { 33327d5dc18SMarcel Moolenaar if (tp != NULL && !(tp->t_iflag & IGNBRK)) 3342140d01bSPoul-Henning Kamp ttyld_rint(tp, 0); 33527d5dc18SMarcel Moolenaar } 33627d5dc18SMarcel Moolenaar 33727d5dc18SMarcel Moolenaar if (pend & UART_IPEND_SIGCHG) { 33827d5dc18SMarcel Moolenaar sig = pend & UART_IPEND_SIGMASK; 33928710806SPoul-Henning Kamp if (sig & SER_DDCD) 34028710806SPoul-Henning Kamp ttyld_modem(tp, sig & SER_DCD); 34128710806SPoul-Henning Kamp if ((sig & SER_DCTS) && (tp->t_cflag & CCTS_OFLOW) && 34227d5dc18SMarcel Moolenaar !sc->sc_hwoflow) { 34328710806SPoul-Henning Kamp if (sig & SER_CTS) { 34427d5dc18SMarcel Moolenaar tp->t_state &= ~TS_TTSTOP; 3452140d01bSPoul-Henning Kamp ttyld_start(tp); 34627d5dc18SMarcel Moolenaar } else 34727d5dc18SMarcel Moolenaar tp->t_state |= TS_TTSTOP; 34827d5dc18SMarcel Moolenaar } 34927d5dc18SMarcel Moolenaar } 35027d5dc18SMarcel Moolenaar 35127d5dc18SMarcel Moolenaar if (pend & UART_IPEND_TXIDLE) { 35227d5dc18SMarcel Moolenaar tp->t_state &= ~TS_BUSY; 3532140d01bSPoul-Henning Kamp ttyld_start(tp); 35427d5dc18SMarcel Moolenaar } 35527d5dc18SMarcel Moolenaar } 35627d5dc18SMarcel Moolenaar 35727d5dc18SMarcel Moolenaar int 35827d5dc18SMarcel Moolenaar uart_tty_attach(struct uart_softc *sc) 35927d5dc18SMarcel Moolenaar { 36027d5dc18SMarcel Moolenaar struct tty *tp; 36179a8d927SPoul-Henning Kamp int unit; 36227d5dc18SMarcel Moolenaar 363a45b36adSPoul-Henning Kamp tp = ttyalloc(); 36427d5dc18SMarcel Moolenaar sc->sc_u.u_tty.tp = tp; 3659e51d6f1SPoul-Henning Kamp tp->t_sc = sc; 36627d5dc18SMarcel Moolenaar 36779a8d927SPoul-Henning Kamp unit = device_get_unit(sc->sc_dev); 36827d5dc18SMarcel Moolenaar 36927d5dc18SMarcel Moolenaar tp->t_oproc = uart_tty_oproc; 37027d5dc18SMarcel Moolenaar tp->t_param = uart_tty_param; 37127d5dc18SMarcel Moolenaar tp->t_stop = uart_tty_stop; 37296df2b0bSPoul-Henning Kamp tp->t_modem = uart_tty_modem; 37396df2b0bSPoul-Henning Kamp tp->t_break = uart_tty_break; 37479a8d927SPoul-Henning Kamp tp->t_open = uart_tty_open; 37579a8d927SPoul-Henning Kamp tp->t_close = uart_tty_close; 37679a8d927SPoul-Henning Kamp 37779a8d927SPoul-Henning Kamp tp->t_pps = &sc->sc_pps; 37827d5dc18SMarcel Moolenaar 37927d5dc18SMarcel Moolenaar if (sc->sc_sysdev != NULL && sc->sc_sysdev->type == UART_DEV_CONSOLE) { 38012d984b6SMarcel Moolenaar sprintf(((struct consdev *)sc->sc_sysdev->cookie)->cn_name, 38179a8d927SPoul-Henning Kamp "ttyu%r", unit); 38279a8d927SPoul-Henning Kamp ttyconsolemode(tp, 0); 38327d5dc18SMarcel Moolenaar } 38427d5dc18SMarcel Moolenaar 38527d5dc18SMarcel Moolenaar swi_add(&tty_ithd, uart_driver_name, uart_tty_intr, sc, SWI_TTY, 38627d5dc18SMarcel Moolenaar INTR_TYPE_TTY, &sc->sc_softih); 38727d5dc18SMarcel Moolenaar 38879a8d927SPoul-Henning Kamp ttycreate(tp, NULL, 0, MINOR_CALLOUT, "u%r", unit); 38979a8d927SPoul-Henning Kamp 39027d5dc18SMarcel Moolenaar return (0); 39127d5dc18SMarcel Moolenaar } 39227d5dc18SMarcel Moolenaar 39327d5dc18SMarcel Moolenaar int uart_tty_detach(struct uart_softc *sc) 39427d5dc18SMarcel Moolenaar { 39579a8d927SPoul-Henning Kamp struct tty *tp; 39627d5dc18SMarcel Moolenaar 39779a8d927SPoul-Henning Kamp tp = sc->sc_u.u_tty.tp; 39879a8d927SPoul-Henning Kamp tp->t_pps = NULL; 39979a8d927SPoul-Henning Kamp ttygone(tp); 40027d5dc18SMarcel Moolenaar ithread_remove_handler(sc->sc_softih); 40179a8d927SPoul-Henning Kamp ttyfree(tp); 40227d5dc18SMarcel Moolenaar 40327d5dc18SMarcel Moolenaar return (0); 40427d5dc18SMarcel Moolenaar } 405