int at91usart_close(dev_t dev, int flag, int mode, struct lwp *l) { struct at91usart_softc *sc = device_lookup_private(&at91usart_cd, COMUNIT(dev)); struct tty *tp = sc->sc_tty; /* XXX This is for cons.c. */ if (!ISSET(tp->t_state, TS_ISOPEN)) return (0); (*tp->t_linesw->l_close)(tp, flag); ttyclose(tp); if (COM_ISALIVE(sc) == 0) return (0); if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { /* * Although we got a last close, the device may still be in * use; e.g. if this was the dialout node, and there are still * processes waiting for carrier on the non-dialout node. */ at91usart_shutdown(sc); } return (0); }
int comclose(dev_t dev, int flag, int mode, struct lwp *l) { struct com_softc *sc = device_lookup_private(&xcom_cd, COMUNIT(dev)); struct tty *tp = sc->sc_tty; int iobase = sc->sc_iobase; int s; /* XXX This is for cons.c. */ if (!ISSET(tp->t_state, TS_ISOPEN)) return 0; (*tp->t_linesw->l_close)(tp, flag); s = spltty(); CLR(sc->sc_lcr, LCR_SBREAK); outb(pio(iobase , com_lcr), sc->sc_lcr); outb(pio(iobase , com_ier), 0); if (ISSET(tp->t_cflag, HUPCL) && !ISSET(sc->sc_swflags, COM_SW_SOFTCAR)) { /* XXX perhaps only clear DTR */ outb(pio(iobase , com_mcr), 0); } CLR(tp->t_state, TS_BUSY | TS_FLUSH); if (--comsopen == 0) callout_stop(&com_poll_ch); splx(s); ttyclose(tp); #ifdef notyet /* XXXX */ if (unit != comconsole) { ttyfree(tp); sc->sc_tty = 0; } #endif return 0; }
struct tty * comtty(dev_t dev) { struct com_softc *sc = device_lookup_private(&xcom_cd, COMUNIT(dev)); struct tty *tp = sc->sc_tty; return (tp); }
int compoll(dev_t dev, int events, struct lwp *l) { struct com_softc *sc = device_lookup_private(&xcom_cd, COMUNIT(dev)); struct tty *tp = sc->sc_tty; return ((*tp->t_linesw->l_poll)(tp, events, l)); }
int comwrite(dev_t dev, struct uio *uio, int flag) { struct com_softc *sc = device_lookup_private(&xcom_cd, COMUNIT(dev)); struct tty *tp = sc->sc_tty; return ((*tp->t_linesw->l_write)(tp, uio, flag)); }
struct tty * at91usart_tty(dev_t dev) { struct at91usart_softc *sc = device_lookup_private(&at91usart_cd, COMUNIT(dev)); struct tty *tp = sc->sc_tty; return (tp); }
struct tty * sacomtty(dev_t dev) { struct sacom_softc *sc = device_lookup_private(&sacom_cd, COMUNIT(dev)); struct tty *tp = sc->sc_tty; return tp; }
int at91usart_poll(dev_t dev, int events, struct lwp *l) { struct at91usart_softc *sc = device_lookup_private(&at91usart_cd, COMUNIT(dev)); struct tty *tp = sc->sc_tty; if (COM_ISALIVE(sc) == 0) return (EIO); return ((*tp->t_linesw->l_poll)(tp, events, l)); }
int at91usart_write(dev_t dev, struct uio *uio, int flag) { struct at91usart_softc *sc = device_lookup_private(&at91usart_cd, COMUNIT(dev)); struct tty *tp = sc->sc_tty; if (COM_ISALIVE(sc) == 0) return (EIO); return ((*tp->t_linesw->l_write)(tp, uio, flag)); }
int at91usart_ioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) { struct at91usart_softc *sc = device_lookup_private(&at91usart_cd, COMUNIT(dev)); struct tty *tp = sc->sc_tty; int error; int s; if (COM_ISALIVE(sc) == 0) return (EIO); error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l); if (error != EPASSTHROUGH) return (error); error = ttioctl(tp, cmd, data, flag, l); if (error != EPASSTHROUGH) return (error); error = 0; s = spltty(); switch (cmd) { case TIOCSBRK: at91usart_break(sc, 1); break; case TIOCCBRK: at91usart_break(sc, 0); break; case TIOCGFLAGS: *(int *)data = sc->sc_swflags; break; case TIOCSFLAGS: error = kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_PRIVSET, tp); if (error) break; sc->sc_swflags = *(int *)data; break; default: error = EPASSTHROUGH; break; } splx(s); return (error); }
int sacompoll(dev_t dev, int events, struct lwp *l) { struct sacom_softc *sc = device_lookup_private(&sacom_cd, COMUNIT(dev)); struct tty *tp = sc->sc_tty; if (COM_ISALIVE(sc) == 0) return EIO; return (*tp->t_linesw->l_poll)(tp, events, l); }
int sacomwrite(dev_t dev, struct uio *uio, int flag) { struct sacom_softc *sc = device_lookup_private(&sacom_cd, COMUNIT(dev)); struct tty *tp = sc->sc_tty; if (COM_ISALIVE(sc) == 0) return EIO; return (*tp->t_linesw->l_write)(tp, uio, flag); }
void sacomstart(struct tty *tp) { struct sacom_softc *sc = device_lookup_private(&sacom_cd, COMUNIT(tp->t_dev)); bus_space_tag_t iot = sc->sc_iot; bus_space_handle_t ioh = sc->sc_ioh; int s; if (COM_ISALIVE(sc) == 0) return; s = spltty(); if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP)) goto out; if (!ttypull(tp)) goto out; /* Grab the first contiguous region of buffer space. */ { u_char *tba; int tbc; tba = tp->t_outq.c_cf; tbc = ndqb(&tp->t_outq, 0); (void)splserial(); COM_LOCK(sc); sc->sc_tba = tba; sc->sc_tbc = tbc; } SET(tp->t_state, TS_BUSY); sc->sc_tx_busy = 1; /* Enable transmit completion interrupts if necessary. */ if (!ISSET(sc->sc_cr3, CR3_TIE)) { SET(sc->sc_cr3, CR3_TIE); bus_space_write_4(iot, ioh, SACOM_CR3, sc->sc_cr3); } /* Output the first chunk of the contiguous buffer. */ sacom_filltx(sc); COM_UNLOCK(sc); out: splx(s); return; }
/* * Stop output on a line. */ void at91usart_stop(struct tty *tp, int flag) { struct at91usart_softc *sc = device_lookup_private(&at91usart_cd, COMUNIT(tp->t_dev)); int s; s = spltty(); if (ISSET(tp->t_state, TS_BUSY)) { /* Stop transmitting at the next chunk. */ sc->sc_tbc = 0; if (!ISSET(tp->t_state, TS_TTSTOP)) SET(tp->t_state, TS_FLUSH); } splx(s); }
static void at91usart_start(struct tty *tp) { struct at91usart_softc *sc = device_lookup_private(&at91usart_cd, COMUNIT(tp->t_dev)); int s; if (COM_ISALIVE(sc) == 0) { DPRINTFN(5, ("%s: %s / COM_ISALIVE == 0\n", device_xname(sc->sc_dev), __FUNCTION__)); return; } s = spltty(); if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP)) { DPRINTFN(5, ("%s: %s: TS_BUSY || TS_TIMEOUT || TS_TTSTOP\n", device_xname(sc->sc_dev), __FUNCTION__)); goto out; } if (!ttypull(tp)) goto out; /* Grab the first contiguous region of buffer space. */ { u_char *tba; int tbc; tba = tp->t_outq.c_cf; tbc = ndqb(&tp->t_outq, 0); sc->sc_tba = tba; sc->sc_tbc = tbc; } SET(tp->t_state, TS_BUSY); /* Output the first chunk of the contiguous buffer. */ at91usart_filltx(sc); at91usart_writereg(sc, US_IER, sc->sc_ier); DPRINTFN(5, ("%s: %s, ier=%08x (csr=%08x)\n", device_xname(sc->sc_dev), __FUNCTION__, sc->sc_ier, at91usart_readreg(sc, US_CSR))); out: splx(s); return; }
static void at91dbgu_start(struct tty *tp) { struct at91dbgu_softc *sc = device_lookup_private(&at91dbgu_cd, COMUNIT(tp->t_dev)); int s; if (COM_ISALIVE(sc) == 0) return; s = spltty(); if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP)) goto out; if (sc->sc_tx_stopped) goto out; if (!ttypull(tp)) goto out; /* Grab the first contiguous region of buffer space. */ { u_char *tba; int tbc; tba = tp->t_outq.c_cf; tbc = ndqb(&tp->t_outq, 0); (void)splserial(); sc->sc_tba = tba; sc->sc_tbc = tbc; } SET(tp->t_state, TS_BUSY); sc->sc_tx_busy = 1; /* Output the first chunk of the contiguous buffer. */ at91dbgu_filltx(sc); SET(sc->sc_ier, DBGU_INT_TXRDY); DBGUREG(DBGU_IER) = DBGU_INT_TXRDY; out: splx(s); return; }
/* * Stop output on a line. */ void sacomstop(struct tty *tp, int flag) { struct sacom_softc *sc = device_lookup_private(&sacom_cd, COMUNIT(tp->t_dev)); int s; s = splserial(); COM_LOCK(sc); if (ISSET(tp->t_state, TS_BUSY)) { /* Stop transmitting at the next chunk. */ sc->sc_tbc = 0; sc->sc_heldtbc = 0; if (!ISSET(tp->t_state, TS_TTSTOP)) SET(tp->t_state, TS_FLUSH); } COM_UNLOCK(sc); splx(s); }
int sacomhwiflow(struct tty *tp, int block) { #if 0 struct sacom_softc *sc = device_lookup_private(&sacom_cd, COMUNIT(tp->t_dev)); int s; if (COM_ISALIVE(sc) == 0) return 0; if (sc->sc_mcr_rts == 0) return 0; s = splserial(); COM_LOCK(sc); if (block) { if (!ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED)) { SET(sc->sc_rx_flags, RX_TTY_BLOCKED); sacom_hwiflow(sc); } } else { if (ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED)) { CLR(sc->sc_rx_flags, RX_TTY_OVERFLOWED); sacom_schedrx(sc); } if (ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED)) { CLR(sc->sc_rx_flags, RX_TTY_BLOCKED); sacom_hwiflow(sc); } } COM_UNLOCK(sc); splx(s); #endif return 1; }
int sacomopen(dev_t dev, int flag, int mode, struct lwp *l) { struct sacom_softc *sc; struct tty *tp; int s, s2; int error; sc = device_lookup_private(&sacom_cd, COMUNIT(dev)); if (sc == NULL || !ISSET(sc->sc_hwflags, COM_HW_DEV_OK) || sc->sc_rbuf == NULL) return ENXIO; if (!device_is_active(&sc->sc_dev)) return ENXIO; tp = sc->sc_tty; if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp)) return (EBUSY); s = spltty(); /* * Do the following iff this is a first open. */ if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { struct termios t; tp->t_dev = dev; s2 = splserial(); COM_LOCK(sc); if (sc->enable) { if ((*sc->enable)(sc)) { COM_UNLOCK(sc); splx(s2); splx(s); printf("%s: device enable failed\n", sc->sc_dev.dv_xname); return EIO; } sc->enabled = 1; sacom_config(sc); } /* Turn on interrupts. */ sc->sc_cr3 = CR3_RXE | CR3_TXE | CR3_RIE | CR3_TIE; bus_space_write_4(sc->sc_iot, sc->sc_ioh, SACOM_CR3, sc->sc_cr3); COM_UNLOCK(sc); splx(s2); /* * Initialize the termios status to the defaults. Add in the * sticky bits from TIOCSFLAGS. */ t.c_ispeed = 0; if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) { t.c_ospeed = sacomconsrate; t.c_cflag = sacomconscflag; } else { t.c_ospeed = TTYDEF_SPEED; t.c_cflag = TTYDEF_CFLAG; } if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL)) SET(t.c_cflag, CLOCAL); if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS)) SET(t.c_cflag, CRTSCTS); if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF)) SET(t.c_cflag, MDMBUF); /* Make sure sacomparam() will do something. */ tp->t_ospeed = 0; (void) sacomparam(tp, &t); tp->t_iflag = TTYDEF_IFLAG; tp->t_oflag = TTYDEF_OFLAG; tp->t_lflag = TTYDEF_LFLAG; ttychars(tp); ttsetwater(tp); s2 = splserial(); COM_LOCK(sc); /* * Turn on DTR. We must always do this, even if carrier is not * present, because otherwise we'd have to use TIOCSDTR * immediately after setting CLOCAL, which applications do not * expect. We always assert DTR while the device is open * unless explicitly requested to deassert it. */ sacom_modem(sc, 1); /* Clear the input ring, and unblock. */ sc->sc_rbput = sc->sc_rbget = sc->sc_rbuf; sc->sc_rbavail = SACOM_RING_SIZE; sacom_iflush(sc); CLR(sc->sc_rx_flags, RX_ANY_BLOCK); sacom_hwiflow(sc); #ifdef COM_DEBUG if (sacom_debug) comstatus(sc, "sacomopen "); #endif COM_UNLOCK(sc); splx(s2); } splx(s); error = ttyopen(tp, COMDIALOUT(dev), ISSET(flag, O_NONBLOCK)); if (error) goto bad; error = (*tp->t_linesw->l_open)(dev, tp); if (error) goto bad; return 0; bad: if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { /* * We failed to open the device, and nobody else had it opened. * Clean up the state as appropriate. */ sacom_shutdown(sc); } return error; }
static int comparam(struct tty *tp, struct termios *t) { struct com_softc *sc = device_lookup_private(&xcom_cd, COMUNIT(tp->t_dev)); int iobase = sc->sc_iobase; int ospeed = comspeed(t->c_ospeed); u_char lcr; tcflag_t oldcflag; int s; /* check requested parameters */ if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed)) return EINVAL; lcr = ISSET(sc->sc_lcr, LCR_SBREAK); switch (ISSET(t->c_cflag, CSIZE)) { case CS5: SET(lcr, LCR_5BITS); break; case CS6: SET(lcr, LCR_6BITS); break; case CS7: SET(lcr, LCR_7BITS); break; case CS8: SET(lcr, LCR_8BITS); break; } if (ISSET(t->c_cflag, PARENB)) { SET(lcr, LCR_PENAB); if (!ISSET(t->c_cflag, PARODD)) SET(lcr, LCR_PEVEN); } if (ISSET(t->c_cflag, CSTOPB)) SET(lcr, LCR_STOPB); sc->sc_lcr = lcr; s = spltty(); if (ospeed == 0) { CLR(sc->sc_mcr, MCR_DTR); outb(pio(iobase , com_mcr), sc->sc_mcr); } /* * Set the FIFO threshold based on the receive speed, if we are * changing it. */ if (tp->t_ispeed != t->c_ispeed) { if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) outb(pio(iobase , com_fifo), FIFO_ENABLE | (t->c_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8)); } if (ospeed != 0) { outb(pio(iobase , com_lcr), lcr | LCR_DLAB); outb(pio(iobase , com_dlbl), ospeed); outb(pio(iobase , com_dlbh), ospeed >> 8); outb(pio(iobase , com_lcr), lcr); SET(sc->sc_mcr, MCR_DTR); outb(pio(iobase , com_mcr), sc->sc_mcr); } else
int comioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) { struct com_softc *sc = device_lookup_private(&xcom_cd, COMUNIT(dev)); struct tty *tp = sc->sc_tty; int iobase = sc->sc_iobase; int error; error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l); if (error != EPASSTHROUGH) return error; error = ttioctl(tp, cmd, data, flag, l); if (error != EPASSTHROUGH) return error; switch (cmd) { case TIOCSBRK: SET(sc->sc_lcr, LCR_SBREAK); outb(pio(iobase , com_lcr), sc->sc_lcr); break; case TIOCCBRK: CLR(sc->sc_lcr, LCR_SBREAK); outb(pio(iobase , com_lcr), sc->sc_lcr); break; case TIOCSDTR: SET(sc->sc_mcr, sc->sc_dtr); outb(pio(iobase , com_mcr), sc->sc_mcr); break; case TIOCCDTR: CLR(sc->sc_mcr, sc->sc_dtr); outb(pio(iobase , com_mcr), sc->sc_mcr); break; case TIOCMSET: CLR(sc->sc_mcr, MCR_DTR | MCR_RTS); case TIOCMBIS: SET(sc->sc_mcr, tiocm_xxx2mcr(*(int *)data)); outb(pio(iobase , com_mcr), sc->sc_mcr); break; case TIOCMBIC: CLR(sc->sc_mcr, tiocm_xxx2mcr(*(int *)data)); outb(pio(iobase , com_mcr), sc->sc_mcr); break; case TIOCMGET: { u_char m; int bits = 0; m = sc->sc_mcr; if (ISSET(m, MCR_DTR)) SET(bits, TIOCM_DTR); if (ISSET(m, MCR_RTS)) SET(bits, TIOCM_RTS); m = sc->sc_msr; if (ISSET(m, MSR_DCD)) SET(bits, TIOCM_CD); if (ISSET(m, MSR_CTS)) SET(bits, TIOCM_CTS); if (ISSET(m, MSR_DSR)) SET(bits, TIOCM_DSR); if (ISSET(m, MSR_RI | MSR_TERI)) SET(bits, TIOCM_RI); if (inb(pio(iobase , com_ier))) SET(bits, TIOCM_LE); *(int *)data = bits; break; } case TIOCGFLAGS: { int driverbits, userbits = 0; driverbits = sc->sc_swflags; if (ISSET(driverbits, COM_SW_SOFTCAR)) SET(userbits, TIOCFLAG_SOFTCAR); if (ISSET(driverbits, COM_SW_CLOCAL)) SET(userbits, TIOCFLAG_CLOCAL); if (ISSET(driverbits, COM_SW_CRTSCTS)) SET(userbits, TIOCFLAG_CRTSCTS); if (ISSET(driverbits, COM_SW_MDMBUF)) SET(userbits, TIOCFLAG_MDMBUF); *(int *)data = userbits; break; } case TIOCSFLAGS: { int userbits, driverbits = 0; error = kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_PRIVSET, tp); if (error != 0) return(EPERM); userbits = *(int *)data; if (ISSET(userbits, TIOCFLAG_SOFTCAR) || ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) SET(driverbits, COM_SW_SOFTCAR); if (ISSET(userbits, TIOCFLAG_CLOCAL)) SET(driverbits, COM_SW_CLOCAL); if (ISSET(userbits, TIOCFLAG_CRTSCTS)) SET(driverbits, COM_SW_CRTSCTS); if (ISSET(userbits, TIOCFLAG_MDMBUF)) SET(driverbits, COM_SW_MDMBUF); sc->sc_swflags = driverbits; break; } default: return EPASSTHROUGH; } return 0; }
int at91usart_open(dev_t dev, int flag, int mode, struct lwp *l) { struct at91usart_softc *sc; struct tty *tp; int s; int error; sc = device_lookup_private(&at91usart_cd, COMUNIT(dev)); if (sc == NULL || !ISSET(sc->sc_hwflags, COM_HW_DEV_OK)) return (ENXIO); if (!device_is_active(sc->sc_dev)) return (ENXIO); #ifdef KGDB /* * If this is the kgdb port, no other use is permitted. */ if (ISSET(sc->sc_hwflags, COM_HW_KGDB)) return (EBUSY); #endif tp = sc->sc_tty; if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp)) return (EBUSY); s = spltty(); /* * Do the following iff this is a first open. */ if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { struct termios t; tp->t_dev = dev; if (sc->enable) { if ((*sc->enable)(sc)) { splx(s); printf("%s: device enable failed\n", device_xname(sc->sc_dev)); return (EIO); } sc->enabled = 1; #if 0 /* XXXXXXXXXXXXXXX */ com_config(sc); #endif } /* reset fifos: */ AT91PDC_RESET_FIFO(sc->sc_iot, sc->sc_ioh, sc->sc_dmat, US_PDC, &sc->sc_rx_fifo, 0); AT91PDC_RESET_FIFO(sc->sc_iot, sc->sc_ioh, sc->sc_dmat, US_PDC, &sc->sc_tx_fifo, 1); /* reset receive */ at91usart_writereg(sc, US_CR, US_CR_RSTSTA | US_CR_STTTO); /* Turn on interrupts. */ sc->sc_ier = US_CSR_ENDRX|US_CSR_RXBUFF|US_CSR_TIMEOUT|US_CSR_RXBRK; at91usart_writereg(sc, US_IER, sc->sc_ier); /* enable DMA: */ at91usart_writereg(sc, US_PDC + PDC_PTCR, PDC_PTCR_RXTEN); /* * Initialize the termios status to the defaults. Add in the * sticky bits from TIOCSFLAGS. */ t.c_ispeed = 0; /* if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) { t.c_ospeed = usart_cn_sc.sc_ospeed; t.c_cflag = usart_cn_sc.sc_cflag; } else*/ { t.c_ospeed = TTYDEF_SPEED; t.c_cflag = TTYDEF_CFLAG; } if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL)) SET(t.c_cflag, CLOCAL); if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS)) SET(t.c_cflag, CRTSCTS); if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF)) SET(t.c_cflag, MDMBUF); /* Make sure at91usart_param() will do something. */ tp->t_ospeed = 0; (void) at91usart_param(tp, &t); tp->t_iflag = TTYDEF_IFLAG; tp->t_oflag = TTYDEF_OFLAG; tp->t_lflag = TTYDEF_LFLAG; ttychars(tp); ttsetwater(tp); /* and unblock. */ CLR(sc->sc_rx_flags, RX_ANY_BLOCK); #ifdef COM_DEBUG if (at91usart_debug) comstatus(sc, "at91usart_open "); #endif } splx(s); error = ttyopen(tp, COMDIALOUT(dev), ISSET(flag, O_NONBLOCK)); if (error) goto bad; error = (*tp->t_linesw->l_open)(dev, tp); if (error) goto bad; return (0); bad: if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { /* * We failed to open the device, and nobody else had it opened. * Clean up the state as appropriate. */ at91usart_shutdown(sc); } return (error); }
static int at91usart_param(struct tty *tp, struct termios *t) { struct at91usart_softc *sc = device_lookup_private(&at91usart_cd, COMUNIT(tp->t_dev)); int s; if (COM_ISALIVE(sc) == 0) return (EIO); if (t->c_ispeed && t->c_ispeed != t->c_ospeed) return (EINVAL); /* * For the console, always force CLOCAL and !HUPCL, so that the port * is always active. */ if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR) || ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) { SET(t->c_cflag, CLOCAL); CLR(t->c_cflag, HUPCL); } /* * If there were no changes, don't do anything. This avoids dropping * input and improves performance when all we did was frob things like * VMIN and VTIME. */ if (tp->t_ospeed == t->c_ospeed && tp->t_cflag == t->c_cflag) return (0); s = spltty(); sc->sc_brgr = (AT91_MSTCLK / 16 + t->c_ospeed / 2) / t->c_ospeed; /* And copy to tty. */ tp->t_ispeed = 0; tp->t_ospeed = t->c_ospeed; tp->t_cflag = t->c_cflag; at91usart_set(sc); splx(s); /* * Update the tty layer's idea of the carrier bit. * We tell tty the carrier is always on. */ (void) (*tp->t_linesw->l_modem)(tp, 1); #ifdef COM_DEBUG if (com_debug) comstatus(sc, "comparam "); #endif /* tell the upper layer about hwflow.. */ if (sc->hwflow) (*sc->hwflow)(sc, t->c_cflag); return (0); }
int at91dbgu_open(dev_t dev, int flag, int mode, struct lwp *l) { struct at91dbgu_softc *sc; struct tty *tp; int s, s2; int error; sc = device_lookup_private(&at91dbgu_cd, COMUNIT(dev)); if (sc == NULL || !ISSET(sc->sc_hwflags, COM_HW_DEV_OK) || sc->sc_rbuf == NULL) return (ENXIO); if (!device_is_active(sc->sc_dev)) return (ENXIO); #ifdef KGDB /* * If this is the kgdb port, no other use is permitted. */ if (ISSET(sc->sc_hwflags, COM_HW_KGDB)) return (EBUSY); #endif tp = sc->sc_tty; if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp)) return (EBUSY); s = spltty(); /* * Do the following iff this is a first open. */ if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { struct termios t; tp->t_dev = dev; s2 = splserial(); if (sc->enable) { if ((*sc->enable)(sc)) { splx(s2); splx(s); printf("%s: device enable failed\n", device_xname(sc->sc_dev)); return (EIO); } sc->enabled = 1; #if 0 /* XXXXXXXXXXXXXXX */ com_config(sc); #endif } /* Turn on interrupts. */ sc->sc_ier |= DBGU_INT_RXRDY; DBGUREG(DBGU_IER) = DBGU_INT_RXRDY; #if 0 /* Fetch the current modem control status, needed later. */ sc->sc_msr = bus_space_read_1(sc->sc_iot, sc->sc_ioh, com_msr); /* Clear PPS capture state on first open. */ sc->sc_ppsmask = 0; sc->ppsparam.mode = 0; #endif splx(s2); /* * Initialize the termios status to the defaults. Add in the * sticky bits from TIOCSFLAGS. */ t.c_ispeed = 0; if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) { t.c_ospeed = dbgu_cn_sc.sc_ospeed; t.c_cflag = dbgu_cn_sc.sc_cflag; } else { t.c_ospeed = TTYDEF_SPEED; t.c_cflag = TTYDEF_CFLAG; } if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL)) SET(t.c_cflag, CLOCAL); if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS)) SET(t.c_cflag, CRTSCTS); if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF)) SET(t.c_cflag, MDMBUF); /* Make sure at91dbgu_param() will do something. */ tp->t_ospeed = 0; (void) at91dbgu_param(tp, &t); tp->t_iflag = TTYDEF_IFLAG; tp->t_oflag = TTYDEF_OFLAG; tp->t_lflag = TTYDEF_LFLAG; ttychars(tp); ttsetwater(tp); s2 = splserial(); /* Clear the input ring, and unblock. */ sc->sc_rbput = sc->sc_rbget = sc->sc_rbuf; sc->sc_rbavail = AT91DBGU_RING_SIZE; at91dbgu_iflush(sc); CLR(sc->sc_rx_flags, RX_ANY_BLOCK); #ifdef COM_DEBUG if (at91dbgu_debug) comstatus(sc, "at91dbgu_open "); #endif splx(s2); } splx(s); error = ttyopen(tp, COMDIALOUT(dev), ISSET(flag, O_NONBLOCK)); if (error) goto bad; error = (*tp->t_linesw->l_open)(dev, tp); if (error) goto bad; return (0); bad: if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { /* * We failed to open the device, and nobody else had it opened. * Clean up the state as appropriate. */ at91dbgu_shutdown(sc); } return (error); }
int sacomparam(struct tty *tp, struct termios *t) { struct sacom_softc *sc = device_lookup_private(&sacom_cd, COMUNIT(tp->t_dev)); int ospeed = SACOMSPEED(t->c_ospeed); u_int cr0; int s; if (COM_ISALIVE(sc) == 0) return EIO; /* Check requested parameters. */ if (ospeed < 0) return EINVAL; if (t->c_ispeed && t->c_ispeed != t->c_ospeed) return EINVAL; /* * For the console, always force CLOCAL and !HUPCL, so that the port * is always active. */ if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR) || ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) { SET(t->c_cflag, CLOCAL); CLR(t->c_cflag, HUPCL); } /* * If there were no changes, don't do anything. This avoids dropping * input and improves performance when all we did was frob things like * VMIN and VTIME. */ if (tp->t_ospeed == t->c_ospeed && tp->t_cflag == t->c_cflag) return 0; cr0 = cflag2cr0(t->c_cflag); s = splserial(); COM_LOCK(sc); sc->sc_cr0 = cr0; sc->sc_speed = ospeed; /* And copy to tty. */ tp->t_ispeed = 0; tp->t_ospeed = t->c_ospeed; tp->t_cflag = t->c_cflag; if (!sc->sc_heldchange) { if (sc->sc_tx_busy) { sc->sc_heldtbc = sc->sc_tbc; sc->sc_tbc = 0; sc->sc_heldchange = 1; } else sacom_loadchannelregs(sc); } if (!ISSET(t->c_cflag, CHWFLOW)) { /* Disable the high water mark. */ if (ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED)) { CLR(sc->sc_rx_flags, RX_TTY_OVERFLOWED); sacom_schedrx(sc); } if (ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED|RX_IBUF_BLOCKED)) { CLR(sc->sc_rx_flags, RX_TTY_BLOCKED|RX_IBUF_BLOCKED); sacom_hwiflow(sc); } } COM_UNLOCK(sc); splx(s); (void) (*tp->t_linesw->l_modem)(tp, 1); #ifdef COM_DEBUG if (sacom_debug) comstatus(sc, "comparam "); #endif return 0; }
int sacomioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) { struct sacom_softc *sc = device_lookup_private(&sacom_cd, COMUNIT(dev)); struct tty *tp = sc->sc_tty; int error; int s; if (COM_ISALIVE(sc) == 0) return EIO; error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l); if (error != EPASSTHROUGH) return error; error = ttioctl(tp, cmd, data, flag, l); if (error != EPASSTHROUGH) return error; error = 0; s = splserial(); COM_LOCK(sc); switch (cmd) { case TIOCSBRK: sacom_break(sc, 1); break; case TIOCCBRK: sacom_break(sc, 0); break; case TIOCSDTR: sacom_modem(sc, 1); break; case TIOCCDTR: sacom_modem(sc, 0); break; case TIOCGFLAGS: *(int *)data = sc->sc_swflags; break; case TIOCSFLAGS: error = kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_PRIVSET, tp); if (error) break; sc->sc_swflags = *(int *)data; break; case TIOCMSET: case TIOCMBIS: case TIOCMBIC: tiocm_to_sacom(sc, cmd, *(int *)data); break; case TIOCMGET: *(int *)data = sacom_to_tiocm(sc); break; default: error = EPASSTHROUGH; break; } COM_UNLOCK(sc); splx(s); #ifdef COM_DEBUG if (sacom_debug) comstatus(sc, "comioctl "); #endif return error; }
int comopen(dev_t dev, int flag, int mode, struct lwp *l) { struct com_softc *sc; int iobase; struct tty *tp; int s; int error = 0; sc = device_lookup_private(&xcom_cd, COMUNIT(dev)); if (!sc) return ENXIO; if (!sc->sc_tty) { tp = sc->sc_tty = ttymalloc(); tty_attach(tp); } else tp = sc->sc_tty; tp->t_oproc = comstart; tp->t_param = comparam; tp->t_dev = dev; if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp)) return (EBUSY); s = spltty(); if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { ttychars(tp); tp->t_iflag = TTYDEF_IFLAG; tp->t_oflag = TTYDEF_OFLAG; tp->t_cflag = TTYDEF_CFLAG; if (ISSET(sc->sc_swflags, COM_SW_CLOCAL)) SET(tp->t_cflag, CLOCAL); if (ISSET(sc->sc_swflags, COM_SW_CRTSCTS)) SET(tp->t_cflag, CRTSCTS); if (ISSET(sc->sc_swflags, COM_SW_MDMBUF)) SET(tp->t_cflag, MDMBUF); tp->t_lflag = TTYDEF_LFLAG; tp->t_ispeed = tp->t_ospeed = comdefaultrate; comparam(tp, &tp->t_termios); ttsetwater(tp); if (comsopen++ == 0) callout_reset(&com_poll_ch, 1, compollin, NULL); sc->sc_ibufp = sc->sc_ibuf = sc->sc_ibufs[0]; sc->sc_ibufhigh = sc->sc_ibuf + COM_IHIGHWATER; sc->sc_ibufend = sc->sc_ibuf + COM_IBUFSIZE; iobase = sc->sc_iobase; #ifdef COM_HAYESP /* Setup the ESP board */ if (ISSET(sc->sc_hwflags, COM_HW_HAYESP)) { int hayespbase = sc->sc_hayespbase; outb(iobase + com_fifo, FIFO_DMA_MODE|FIFO_ENABLE| FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_8); /* Set 16550 compatibility mode */ outb(hayespbase + HAYESP_CMD1, HAYESP_SETMODE); outb(hayespbase + HAYESP_CMD2, HAYESP_MODE_FIFO|HAYESP_MODE_RTS| HAYESP_MODE_SCALE); /* Set RTS/CTS flow control */ outb(hayespbase + HAYESP_CMD1, HAYESP_SETFLOWTYPE); outb(hayespbase + HAYESP_CMD2, HAYESP_FLOW_RTS); outb(hayespbase + HAYESP_CMD2, HAYESP_FLOW_CTS); /* Set flow control levels */ outb(hayespbase + HAYESP_CMD1, HAYESP_SETRXFLOW); outb(hayespbase + HAYESP_CMD2, HAYESP_HIBYTE(HAYESP_RXHIWMARK)); outb(hayespbase + HAYESP_CMD2, HAYESP_LOBYTE(HAYESP_RXHIWMARK)); outb(hayespbase + HAYESP_CMD2, HAYESP_HIBYTE(HAYESP_RXLOWMARK)); outb(hayespbase + HAYESP_CMD2, HAYESP_LOBYTE(HAYESP_RXLOWMARK)); } else #endif if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) /* Set the FIFO threshold based on the receive speed. */ outb(pio(iobase , com_fifo), FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | (tp->t_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8)); /* flush any pending I/O */ while (ISSET(inb(pio(iobase , com_lsr)), LSR_RXRDY)) (void) inb(pio(iobase , com_data)); /* you turn me on, baby */ sc->sc_mcr = MCR_DTR | MCR_RTS; if (!ISSET(sc->sc_hwflags, COM_HW_NOIEN)) SET(sc->sc_mcr, MCR_IENABLE | MCR_DRS); /* */ outb(pio(iobase , com_mcr), sc->sc_mcr); sc->sc_ier = IER_ERXRDY | IER_ERLS | IER_EMSC; outb(pio(iobase , com_ier), sc->sc_ier); sc->sc_msr = inb(pio(iobase , com_msr)); if (ISSET(sc->sc_swflags, COM_SW_SOFTCAR) || ISSET(sc->sc_msr, MSR_DCD) || ISSET(tp->t_cflag, MDMBUF)) SET(tp->t_state, TS_CARR_ON); else CLR(tp->t_state, TS_CARR_ON); } splx(s); error = ttyopen(tp, COMDIALOUT(dev), ISSET(flag, O_NONBLOCK)); if (!error) error = (*tp->t_linesw->l_open)(dev, tp); /* XXX cleanup on error */ return error; }