1098ca2bdSWarner Losh /*- 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/tty.h> 4327d5dc18SMarcel Moolenaar #include <machine/resource.h> 4427d5dc18SMarcel Moolenaar #include <machine/stdarg.h> 4527d5dc18SMarcel Moolenaar 4627d5dc18SMarcel Moolenaar #include <dev/uart/uart.h> 4727d5dc18SMarcel Moolenaar #include <dev/uart/uart_bus.h> 4827d5dc18SMarcel Moolenaar #include <dev/uart/uart_cpu.h> 4927d5dc18SMarcel Moolenaar 5027d5dc18SMarcel Moolenaar #include "uart_if.h" 5127d5dc18SMarcel Moolenaar 5227d5dc18SMarcel Moolenaar static cn_probe_t uart_cnprobe; 5327d5dc18SMarcel Moolenaar static cn_init_t uart_cninit; 5427d5dc18SMarcel Moolenaar static cn_term_t uart_cnterm; 5527d5dc18SMarcel Moolenaar static cn_getc_t uart_cngetc; 5627d5dc18SMarcel Moolenaar static cn_putc_t uart_cnputc; 57*9976156fSAndriy Gapon static cn_grab_t uart_cngrab; 58*9976156fSAndriy Gapon static cn_ungrab_t uart_cnungrab; 5927d5dc18SMarcel Moolenaar 607672c959SPoul-Henning Kamp CONSOLE_DRIVER(uart); 6127d5dc18SMarcel Moolenaar 6227d5dc18SMarcel Moolenaar static struct uart_devinfo uart_console; 6327d5dc18SMarcel Moolenaar 6427d5dc18SMarcel Moolenaar static void 6527d5dc18SMarcel Moolenaar uart_cnprobe(struct consdev *cp) 6627d5dc18SMarcel Moolenaar { 6727d5dc18SMarcel Moolenaar 6827d5dc18SMarcel Moolenaar cp->cn_pri = CN_DEAD; 6927d5dc18SMarcel Moolenaar 7027d5dc18SMarcel Moolenaar KASSERT(uart_console.cookie == NULL, ("foo")); 7127d5dc18SMarcel Moolenaar 7227d5dc18SMarcel Moolenaar if (uart_cpu_getdev(UART_DEV_CONSOLE, &uart_console)) 7327d5dc18SMarcel Moolenaar return; 7427d5dc18SMarcel Moolenaar 7527d5dc18SMarcel Moolenaar if (uart_probe(&uart_console)) 7627d5dc18SMarcel Moolenaar return; 7727d5dc18SMarcel Moolenaar 789f0974f9SMarcel Moolenaar strlcpy(cp->cn_name, uart_driver_name, sizeof(cp->cn_name)); 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 113*9976156fSAndriy Gapon uart_cngrab(struct consdev *cp) 114*9976156fSAndriy Gapon { 115*9976156fSAndriy Gapon } 116*9976156fSAndriy Gapon 117*9976156fSAndriy Gapon static void 118*9976156fSAndriy Gapon uart_cnungrab(struct consdev *cp) 119*9976156fSAndriy Gapon { 120*9976156fSAndriy Gapon } 121*9976156fSAndriy Gapon 122*9976156fSAndriy Gapon static void 12327d5dc18SMarcel Moolenaar uart_cnputc(struct consdev *cp, int c) 12427d5dc18SMarcel Moolenaar { 12527d5dc18SMarcel Moolenaar 12627d5dc18SMarcel Moolenaar uart_putc(cp->cn_arg, c); 12727d5dc18SMarcel Moolenaar } 12827d5dc18SMarcel Moolenaar 12927d5dc18SMarcel Moolenaar static int 13027d5dc18SMarcel Moolenaar uart_cngetc(struct consdev *cp) 13127d5dc18SMarcel Moolenaar { 13227d5dc18SMarcel Moolenaar 1337672c959SPoul-Henning Kamp return (uart_poll(cp->cn_arg)); 13427d5dc18SMarcel Moolenaar } 13527d5dc18SMarcel Moolenaar 13679a8d927SPoul-Henning Kamp static int 137bc093719SEd Schouten uart_tty_open(struct tty *tp) 13879a8d927SPoul-Henning Kamp { 13979a8d927SPoul-Henning Kamp struct uart_softc *sc; 14079a8d927SPoul-Henning Kamp 141bc093719SEd Schouten sc = tty_softc(tp); 142793bcd17SMarcel Moolenaar 143793bcd17SMarcel Moolenaar if (sc == NULL || sc->sc_leaving) 144793bcd17SMarcel Moolenaar return (ENXIO); 145793bcd17SMarcel Moolenaar 14679a8d927SPoul-Henning Kamp sc->sc_opened = 1; 14779a8d927SPoul-Henning Kamp return (0); 14879a8d927SPoul-Henning Kamp } 14979a8d927SPoul-Henning Kamp 15079a8d927SPoul-Henning Kamp static void 15179a8d927SPoul-Henning Kamp uart_tty_close(struct tty *tp) 15279a8d927SPoul-Henning Kamp { 15379a8d927SPoul-Henning Kamp struct uart_softc *sc; 15479a8d927SPoul-Henning Kamp 155bc093719SEd Schouten sc = tty_softc(tp); 156fbbec42fSPoul-Henning Kamp if (sc == NULL || sc->sc_leaving || !sc->sc_opened) 15779a8d927SPoul-Henning Kamp return; 15879a8d927SPoul-Henning Kamp 15979a8d927SPoul-Henning Kamp if (sc->sc_hwiflow) 16079a8d927SPoul-Henning Kamp UART_IOCTL(sc, UART_IOCTL_IFLOW, 0); 16179a8d927SPoul-Henning Kamp if (sc->sc_hwoflow) 16279a8d927SPoul-Henning Kamp UART_IOCTL(sc, UART_IOCTL_OFLOW, 0); 16379a8d927SPoul-Henning Kamp if (sc->sc_sysdev == NULL) 16479a8d927SPoul-Henning Kamp UART_SETSIG(sc, SER_DDTR | SER_DRTS); 16579a8d927SPoul-Henning Kamp 16679a8d927SPoul-Henning Kamp wakeup(sc); 16779a8d927SPoul-Henning Kamp sc->sc_opened = 0; 16879a8d927SPoul-Henning Kamp return; 16979a8d927SPoul-Henning Kamp } 17079a8d927SPoul-Henning Kamp 17127d5dc18SMarcel Moolenaar static void 172bc093719SEd Schouten uart_tty_outwakeup(struct tty *tp) 17327d5dc18SMarcel Moolenaar { 17427d5dc18SMarcel Moolenaar struct uart_softc *sc; 17527d5dc18SMarcel Moolenaar 176bc093719SEd Schouten sc = tty_softc(tp); 17727d5dc18SMarcel Moolenaar if (sc == NULL || sc->sc_leaving) 17827d5dc18SMarcel Moolenaar return; 17927d5dc18SMarcel Moolenaar 180bc093719SEd Schouten if (sc->sc_txbusy) 18127d5dc18SMarcel Moolenaar return; 18227d5dc18SMarcel Moolenaar 183f1fb9647SMarcel Moolenaar /* 184f1fb9647SMarcel Moolenaar * Respect RTS/CTS (output) flow control if enabled and not already 185f1fb9647SMarcel Moolenaar * handled by hardware. 186f1fb9647SMarcel Moolenaar */ 187f1fb9647SMarcel Moolenaar if ((tp->t_termios.c_cflag & CCTS_OFLOW) && !sc->sc_hwoflow && 188f1fb9647SMarcel Moolenaar !(sc->sc_hwsig & SER_CTS)) 189f1fb9647SMarcel Moolenaar return; 190f1fb9647SMarcel Moolenaar 191bc093719SEd Schouten sc->sc_txdatasz = ttydisc_getc(tp, sc->sc_txbuf, sc->sc_txfifosz); 192bc093719SEd Schouten if (sc->sc_txdatasz != 0) 193bc093719SEd Schouten UART_TRANSMIT(sc); 19427d5dc18SMarcel Moolenaar } 19527d5dc18SMarcel Moolenaar 1960acb3c4aSMarcel Moolenaar static void 1970acb3c4aSMarcel Moolenaar uart_tty_inwakeup(struct tty *tp) 1980acb3c4aSMarcel Moolenaar { 1990acb3c4aSMarcel Moolenaar struct uart_softc *sc; 2000acb3c4aSMarcel Moolenaar 2010acb3c4aSMarcel Moolenaar sc = tty_softc(tp); 2020acb3c4aSMarcel Moolenaar if (sc == NULL || sc->sc_leaving) 2030acb3c4aSMarcel Moolenaar return; 2040acb3c4aSMarcel Moolenaar 2050acb3c4aSMarcel Moolenaar if (sc->sc_isquelch) { 2060acb3c4aSMarcel Moolenaar if ((tp->t_termios.c_cflag & CRTS_IFLOW) && !sc->sc_hwiflow) 2070acb3c4aSMarcel Moolenaar UART_SETSIG(sc, SER_DRTS|SER_RTS); 2080acb3c4aSMarcel Moolenaar sc->sc_isquelch = 0; 2090acb3c4aSMarcel Moolenaar uart_sched_softih(sc, SER_INT_RXREADY); 2100acb3c4aSMarcel Moolenaar } 2110acb3c4aSMarcel Moolenaar } 2120acb3c4aSMarcel Moolenaar 213bc093719SEd Schouten static int 214bc093719SEd Schouten uart_tty_ioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td) 215bc093719SEd Schouten { 216bc093719SEd Schouten struct uart_softc *sc; 217bc093719SEd Schouten 218bc093719SEd Schouten sc = tty_softc(tp); 219bc093719SEd Schouten 220bc093719SEd Schouten switch (cmd) { 221bc093719SEd Schouten case TIOCSBRK: 222bc093719SEd Schouten UART_IOCTL(sc, UART_IOCTL_BREAK, 1); 223bc093719SEd Schouten return (0); 224bc093719SEd Schouten case TIOCCBRK: 225bc093719SEd Schouten UART_IOCTL(sc, UART_IOCTL_BREAK, 0); 226bc093719SEd Schouten return (0); 227bc093719SEd Schouten default: 228bc093719SEd Schouten return pps_ioctl(cmd, data, &sc->sc_pps); 229bc093719SEd Schouten } 23027d5dc18SMarcel Moolenaar } 23127d5dc18SMarcel Moolenaar 23227d5dc18SMarcel Moolenaar static int 23327d5dc18SMarcel Moolenaar uart_tty_param(struct tty *tp, struct termios *t) 23427d5dc18SMarcel Moolenaar { 23527d5dc18SMarcel Moolenaar struct uart_softc *sc; 23627d5dc18SMarcel Moolenaar int databits, parity, stopbits; 23727d5dc18SMarcel Moolenaar 238bc093719SEd Schouten sc = tty_softc(tp); 23927d5dc18SMarcel Moolenaar if (sc == NULL || sc->sc_leaving) 24027d5dc18SMarcel Moolenaar return (ENODEV); 24127d5dc18SMarcel Moolenaar if (t->c_ispeed != t->c_ospeed && t->c_ospeed != 0) 24227d5dc18SMarcel Moolenaar return (EINVAL); 24327d5dc18SMarcel Moolenaar /* Fixate certain parameters for system devices. */ 24427d5dc18SMarcel Moolenaar if (sc->sc_sysdev != NULL) { 24527d5dc18SMarcel Moolenaar t->c_ispeed = t->c_ospeed = sc->sc_sysdev->baudrate; 24627d5dc18SMarcel Moolenaar t->c_cflag |= CLOCAL; 24727d5dc18SMarcel Moolenaar t->c_cflag &= ~HUPCL; 24827d5dc18SMarcel Moolenaar } 24927d5dc18SMarcel Moolenaar if (t->c_ospeed == 0) { 25028710806SPoul-Henning Kamp UART_SETSIG(sc, SER_DDTR | SER_DRTS); 25127d5dc18SMarcel Moolenaar return (0); 25227d5dc18SMarcel Moolenaar } 25327d5dc18SMarcel Moolenaar switch (t->c_cflag & CSIZE) { 25427d5dc18SMarcel Moolenaar case CS5: databits = 5; break; 25527d5dc18SMarcel Moolenaar case CS6: databits = 6; break; 25627d5dc18SMarcel Moolenaar case CS7: databits = 7; break; 25727d5dc18SMarcel Moolenaar default: databits = 8; break; 25827d5dc18SMarcel Moolenaar } 25927d5dc18SMarcel Moolenaar stopbits = (t->c_cflag & CSTOPB) ? 2 : 1; 26027d5dc18SMarcel Moolenaar if (t->c_cflag & PARENB) 26127d5dc18SMarcel Moolenaar parity = (t->c_cflag & PARODD) ? UART_PARITY_ODD 26227d5dc18SMarcel Moolenaar : UART_PARITY_EVEN; 26327d5dc18SMarcel Moolenaar else 26427d5dc18SMarcel Moolenaar parity = UART_PARITY_NONE; 265b662bdc2SMarcel Moolenaar if (UART_PARAM(sc, t->c_ospeed, databits, stopbits, parity) != 0) 266b662bdc2SMarcel Moolenaar return (EINVAL); 26728710806SPoul-Henning Kamp UART_SETSIG(sc, SER_DDTR | SER_DTR); 26827d5dc18SMarcel Moolenaar /* Set input flow control state. */ 26927d5dc18SMarcel Moolenaar if (!sc->sc_hwiflow) { 2700acb3c4aSMarcel Moolenaar if ((t->c_cflag & CRTS_IFLOW) && sc->sc_isquelch) 27128710806SPoul-Henning Kamp UART_SETSIG(sc, SER_DRTS); 2720acb3c4aSMarcel Moolenaar else 27328710806SPoul-Henning Kamp UART_SETSIG(sc, SER_DRTS | SER_RTS); 27427d5dc18SMarcel Moolenaar } else 27527d5dc18SMarcel Moolenaar UART_IOCTL(sc, UART_IOCTL_IFLOW, (t->c_cflag & CRTS_IFLOW)); 27627d5dc18SMarcel Moolenaar /* Set output flow control state. */ 27727d5dc18SMarcel Moolenaar if (sc->sc_hwoflow) 27827d5dc18SMarcel Moolenaar UART_IOCTL(sc, UART_IOCTL_OFLOW, (t->c_cflag & CCTS_OFLOW)); 279bc093719SEd Schouten 28027d5dc18SMarcel Moolenaar return (0); 28127d5dc18SMarcel Moolenaar } 28227d5dc18SMarcel Moolenaar 28396df2b0bSPoul-Henning Kamp static int 28496df2b0bSPoul-Henning Kamp uart_tty_modem(struct tty *tp, int biton, int bitoff) 28596df2b0bSPoul-Henning Kamp { 28696df2b0bSPoul-Henning Kamp struct uart_softc *sc; 28796df2b0bSPoul-Henning Kamp 288bc093719SEd Schouten sc = tty_softc(tp); 28996df2b0bSPoul-Henning Kamp if (biton != 0 || bitoff != 0) 29096df2b0bSPoul-Henning Kamp UART_SETSIG(sc, SER_DELTA(bitoff|biton) | biton); 29196df2b0bSPoul-Henning Kamp return (sc->sc_hwsig); 29296df2b0bSPoul-Henning Kamp } 29396df2b0bSPoul-Henning Kamp 29427d5dc18SMarcel Moolenaar void 29527d5dc18SMarcel Moolenaar uart_tty_intr(void *arg) 29627d5dc18SMarcel Moolenaar { 29727d5dc18SMarcel Moolenaar struct uart_softc *sc = arg; 29827d5dc18SMarcel Moolenaar struct tty *tp; 299bc093719SEd Schouten int c, err = 0, pend, sig, xc; 30027d5dc18SMarcel Moolenaar 30127d5dc18SMarcel Moolenaar if (sc->sc_leaving) 30227d5dc18SMarcel Moolenaar return; 30327d5dc18SMarcel Moolenaar 30427d5dc18SMarcel Moolenaar pend = atomic_readandclear_32(&sc->sc_ttypend); 3052d511805SMarcel Moolenaar if (!(pend & SER_INT_MASK)) 30627d5dc18SMarcel Moolenaar return; 30727d5dc18SMarcel Moolenaar 30827d5dc18SMarcel Moolenaar tp = sc->sc_u.u_tty.tp; 309bc093719SEd Schouten tty_lock(tp); 31027d5dc18SMarcel Moolenaar 3112d511805SMarcel Moolenaar if (pend & SER_INT_RXREADY) { 3120acb3c4aSMarcel Moolenaar while (!uart_rx_empty(sc) && !sc->sc_isquelch) { 3130acb3c4aSMarcel Moolenaar xc = uart_rx_peek(sc); 31427d5dc18SMarcel Moolenaar c = xc & 0xff; 31527d5dc18SMarcel Moolenaar if (xc & UART_STAT_FRAMERR) 316bc093719SEd Schouten err |= TRE_FRAMING; 317dd5b096fSMarcel Moolenaar if (xc & UART_STAT_OVERRUN) 318bc093719SEd Schouten err |= TRE_OVERRUN; 31927d5dc18SMarcel Moolenaar if (xc & UART_STAT_PARERR) 320bc093719SEd Schouten err |= TRE_PARITY; 3210acb3c4aSMarcel Moolenaar if (ttydisc_rint(tp, c, err) != 0) { 3220acb3c4aSMarcel Moolenaar sc->sc_isquelch = 1; 3230acb3c4aSMarcel Moolenaar if ((tp->t_termios.c_cflag & CRTS_IFLOW) && 3240acb3c4aSMarcel Moolenaar !sc->sc_hwiflow) 3250acb3c4aSMarcel Moolenaar UART_SETSIG(sc, SER_DRTS); 3260acb3c4aSMarcel Moolenaar } else 3270acb3c4aSMarcel Moolenaar uart_rx_next(sc); 32827d5dc18SMarcel Moolenaar } 32927d5dc18SMarcel Moolenaar } 33027d5dc18SMarcel Moolenaar 331bc093719SEd Schouten if (pend & SER_INT_BREAK) 332bc093719SEd Schouten ttydisc_rint(tp, 0, TRE_BREAK); 33327d5dc18SMarcel Moolenaar 3342d511805SMarcel Moolenaar if (pend & SER_INT_SIGCHG) { 3352d511805SMarcel Moolenaar sig = pend & SER_INT_SIGMASK; 33628710806SPoul-Henning Kamp if (sig & SER_DDCD) 337bc093719SEd Schouten ttydisc_modem(tp, sig & SER_DCD); 338f1fb9647SMarcel Moolenaar if (sig & SER_DCTS) 339bc093719SEd Schouten uart_tty_outwakeup(tp); 34027d5dc18SMarcel Moolenaar } 34127d5dc18SMarcel Moolenaar 342bc093719SEd Schouten if (pend & SER_INT_TXIDLE) 343bc093719SEd Schouten uart_tty_outwakeup(tp); 344bc093719SEd Schouten ttydisc_rint_done(tp); 345bc093719SEd Schouten tty_unlock(tp); 34627d5dc18SMarcel Moolenaar } 347bc093719SEd Schouten 3489b866e4eSEd Schouten static void 3499b866e4eSEd Schouten uart_tty_free(void *arg) 3509b866e4eSEd Schouten { 3519b866e4eSEd Schouten 3529b866e4eSEd Schouten /* 3539b866e4eSEd Schouten * XXX: uart(4) could reuse the device unit number before it is 3549b866e4eSEd Schouten * being freed by the TTY layer. We should use this hook to free 3559b866e4eSEd Schouten * the device unit number, but unfortunately newbus does not 3569b866e4eSEd Schouten * seem to support such a construct. 3579b866e4eSEd Schouten */ 3589b866e4eSEd Schouten } 3599b866e4eSEd Schouten 360bc093719SEd Schouten static struct ttydevsw uart_tty_class = { 361bc093719SEd Schouten .tsw_flags = TF_INITLOCK|TF_CALLOUT, 362bc093719SEd Schouten .tsw_open = uart_tty_open, 363bc093719SEd Schouten .tsw_close = uart_tty_close, 364bc093719SEd Schouten .tsw_outwakeup = uart_tty_outwakeup, 3650acb3c4aSMarcel Moolenaar .tsw_inwakeup = uart_tty_inwakeup, 366bc093719SEd Schouten .tsw_ioctl = uart_tty_ioctl, 367bc093719SEd Schouten .tsw_param = uart_tty_param, 368bc093719SEd Schouten .tsw_modem = uart_tty_modem, 3699b866e4eSEd Schouten .tsw_free = uart_tty_free, 370bc093719SEd Schouten }; 37127d5dc18SMarcel Moolenaar 37227d5dc18SMarcel Moolenaar int 37327d5dc18SMarcel Moolenaar uart_tty_attach(struct uart_softc *sc) 37427d5dc18SMarcel Moolenaar { 37527d5dc18SMarcel Moolenaar struct tty *tp; 37679a8d927SPoul-Henning Kamp int unit; 37727d5dc18SMarcel Moolenaar 378c5e30cc0SEd Schouten sc->sc_u.u_tty.tp = tp = tty_alloc(&uart_tty_class, sc); 37927d5dc18SMarcel Moolenaar 38079a8d927SPoul-Henning Kamp unit = device_get_unit(sc->sc_dev); 38127d5dc18SMarcel Moolenaar 38227d5dc18SMarcel Moolenaar if (sc->sc_sysdev != NULL && sc->sc_sysdev->type == UART_DEV_CONSOLE) { 38312d984b6SMarcel Moolenaar sprintf(((struct consdev *)sc->sc_sysdev->cookie)->cn_name, 38479a8d927SPoul-Henning Kamp "ttyu%r", unit); 385bc093719SEd Schouten tty_init_console(tp, 0); 38627d5dc18SMarcel Moolenaar } 38727d5dc18SMarcel Moolenaar 388e0f66ef8SJohn Baldwin swi_add(&tty_intr_event, uart_driver_name, uart_tty_intr, sc, SWI_TTY, 38927d5dc18SMarcel Moolenaar INTR_TYPE_TTY, &sc->sc_softih); 39027d5dc18SMarcel Moolenaar 391bc093719SEd Schouten tty_makedev(tp, NULL, "u%r", unit); 39279a8d927SPoul-Henning Kamp 39327d5dc18SMarcel Moolenaar return (0); 39427d5dc18SMarcel Moolenaar } 39527d5dc18SMarcel Moolenaar 3967d376cbcSAlexander Kabaev int 3977d376cbcSAlexander Kabaev uart_tty_detach(struct uart_softc *sc) 39827d5dc18SMarcel Moolenaar { 39979a8d927SPoul-Henning Kamp struct tty *tp; 40027d5dc18SMarcel Moolenaar 40179a8d927SPoul-Henning Kamp tp = sc->sc_u.u_tty.tp; 402bc093719SEd Schouten 403bc093719SEd Schouten tty_lock(tp); 404284b6708SJohn Baldwin swi_remove(sc->sc_softih); 405bc093719SEd Schouten tty_rel_gone(tp); 40627d5dc18SMarcel Moolenaar 40727d5dc18SMarcel Moolenaar return (0); 40827d5dc18SMarcel Moolenaar } 409