int ptsread(dev_t dev, struct uio *uio, int flag) { struct proc *p = curproc; struct process *pr = p->p_p; struct pt_softc *pti = pt_softc[minor(dev)]; struct tty *tp = pti->pt_tty; int error = 0; again: if (pti->pt_flags & PF_REMOTE) { while (isbackground(pr, tp)) { if ((p->p_sigacts->ps_sigignore & sigmask(SIGTTIN)) || (p->p_sigmask & sigmask(SIGTTIN)) || pr->ps_pgrp->pg_jobc == 0 || pr->ps_flags & PS_PPWAIT) return (EIO); pgsignal(pr->ps_pgrp, SIGTTIN, 1); error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, ttybg, 0); if (error) return (error); } if (tp->t_canq.c_cc == 0) { if (flag & IO_NDELAY) return (EWOULDBLOCK); error = ttysleep(tp, &tp->t_canq, TTIPRI | PCATCH, ttyin, 0); if (error) return (error); goto again; } while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0) if (ureadc(getc(&tp->t_canq), uio) < 0) { error = EFAULT; break; } if (tp->t_canq.c_cc == 1) (void) getc(&tp->t_canq); if (tp->t_canq.c_cc) return (error); } else if (tp->t_oproc) error = (*linesw[tp->t_line].l_read)(tp, uio, flag); ptcwakeup(tp, FWRITE); return (error); }
int dzopen(dev_t dev, int flag, int mode, struct lwp *l) { struct tty *tp; int unit, line; struct dz_softc *sc; int s, error = 0; unit = DZ_I2C(minor(dev)); sc = device_lookup_private(&dz_cd, unit); if (sc == NULL) return ENXIO; line = DZ_PORT(minor(dev)); if (line > 0) /* FIXME for more than one line */ return ENXIO; tp = sc->sc_dz.dz_tty; if (tp == NULL) return ENODEV; tp->t_oproc = dzstart; tp->t_param = dzparam; tp->t_dev = dev; if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp)) return (EBUSY); if ((tp->t_state & TS_ISOPEN) == 0) { ttychars(tp); if (tp->t_ispeed == 0) { tp->t_iflag = TTYDEF_IFLAG; tp->t_oflag = TTYDEF_OFLAG; tp->t_cflag = TTYDEF_CFLAG; tp->t_lflag = TTYDEF_LFLAG; tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; } (void)dzparam(tp, &tp->t_termios); ttsetwater(tp); } /* we have no modem control but..*/ if (dzmctl(sc, line, TIOCM_DTR, DMBIS) & TIOCM_CD) tp->t_state |= TS_CARR_ON; s = spltty(); while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) && !(tp->t_state & TS_CARR_ON)) { tp->t_wopen++; error = ttysleep(tp, &tp->t_rawcv, true, 0); tp->t_wopen--; if (error) break; } (void)splx(s); if (error) return error; return (*tp->t_linesw->l_open)(dev, tp); }
/*ARGSUSED*/ int ptsopen(dev_t dev, int flag, int devtype, struct proc *p) { struct pt_softc *pti; struct tty *tp; int error; if ((error = check_pty(minor(dev)))) return (error); pti = pt_softc[minor(dev)]; if (!pti->pt_tty) { tp = pti->pt_tty = ttymalloc(); } else tp = pti->pt_tty; if ((tp->t_state & TS_ISOPEN) == 0) { tp->t_state |= TS_WOPEN; ttychars(tp); /* Set up default chars */ tp->t_iflag = TTYDEF_IFLAG; tp->t_oflag = TTYDEF_OFLAG; tp->t_lflag = TTYDEF_LFLAG; tp->t_cflag = TTYDEF_CFLAG; tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; ttsetwater(tp); /* would be done in xxparam() */ } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0) return (EBUSY); if (tp->t_oproc) /* Ctrlr still around. */ tp->t_state |= TS_CARR_ON; while ((tp->t_state & TS_CARR_ON) == 0) { tp->t_state |= TS_WOPEN; if (flag&FNONBLOCK) break; error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH, ttopen, 0); if (error) return (error); } error = (*linesw[tp->t_line].l_open)(dev, tp); ptcwakeup(tp, FREAD|FWRITE); return (error); }
int sabopen(dev_t dev, int flags, int mode, struct lwp *l) { struct sabtty_softc *sc; struct tty *tp; struct proc *p; int s, s1; sc = device_lookup_private(&sabtty_cd, SABUNIT(dev)); if (sc == NULL) return (ENXIO); tp = sc->sc_tty; tp->t_dev = dev; p = l->l_proc; if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp)) return (EBUSY); mutex_spin_enter(&tty_lock); if ((tp->t_state & TS_ISOPEN) == 0) { ttychars(tp); tp->t_iflag = TTYDEF_IFLAG; tp->t_oflag = TTYDEF_OFLAG; tp->t_cflag = TTYDEF_CFLAG; if (sc->sc_openflags & TIOCFLAG_CLOCAL) tp->t_cflag |= CLOCAL; if (sc->sc_openflags & TIOCFLAG_CRTSCTS) tp->t_cflag |= CRTSCTS; if (sc->sc_openflags & TIOCFLAG_MDMBUF) tp->t_cflag |= MDMBUF; tp->t_lflag = TTYDEF_LFLAG; tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; sc->sc_rput = sc->sc_rget = sc->sc_rbuf; ttsetwater(tp); s1 = splhigh(); sabtty_reset(sc); sabtty_param(tp, &tp->t_termios); sc->sc_imr0 = SAB_IMR0_PERR | SAB_IMR0_FERR | SAB_IMR0_PLLA; SAB_WRITE(sc, SAB_IMR0, sc->sc_imr0); sc->sc_imr1 = SAB_IMR1_BRK | SAB_IMR1_ALLS | SAB_IMR1_XDU | SAB_IMR1_TIN | SAB_IMR1_CSC | SAB_IMR1_XMR | SAB_IMR1_XPR; SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1); SAB_WRITE(sc, SAB_CCR0, SAB_READ(sc, SAB_CCR0) | SAB_CCR0_PU); sabtty_cec_wait(sc); SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_XRES); sabtty_cec_wait(sc); SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_RRES); sabtty_cec_wait(sc); splx(s1); sabtty_flush(sc); if ((sc->sc_openflags & TIOCFLAG_SOFTCAR) || (SAB_READ(sc, SAB_VSTR) & SAB_VSTR_CD)) tp->t_state |= TS_CARR_ON; else tp->t_state &= ~TS_CARR_ON; } if ((flags & O_NONBLOCK) == 0) { while ((tp->t_cflag & CLOCAL) == 0 && (tp->t_state & TS_CARR_ON) == 0) { int error; error = ttysleep(tp, &tp->t_rawcv, true, 0); if (error != 0) { mutex_spin_exit(&tty_lock); return (error); } } } mutex_spin_exit(&tty_lock); s = (*tp->t_linesw->l_open)(dev, tp); if (s != 0) { mutex_spin_enter(&tty_lock); if (tp->t_state & TS_ISOPEN) { mutex_spin_exit(&tty_lock); return (s); } if (tp->t_cflag & HUPCL) { sabtty_mdmctrl(sc, 0, DMSET); cv_wait(&lbolt, &tty_lock); } if ((sc->sc_flags & (SABTTYF_CONS_IN | SABTTYF_CONS_OUT)) == 0) { /* Flush and power down if we're not the console */ sabtty_flush(sc); sabtty_reset(sc); } mutex_spin_exit(&tty_lock); } return (s); }
/* * open routine. returns zero if successful, else error code */ int mttyopen(dev_t dev, int flags, int mode, struct proc *p) { int card = MAGMA_CARD(dev); int port = MAGMA_PORT(dev); struct mtty_softc *ms; struct mtty_port *mp; struct tty *tp; struct cd1400 *cd; int s; if (card >= mtty_cd.cd_ndevs || (ms = mtty_cd.cd_devs[card]) == NULL || port >= ms->ms_nports) return (ENXIO); /* device not configured */ mp = &ms->ms_port[port]; tp = mp->mp_tty; tp->t_dev = dev; if (!ISSET(tp->t_state, TS_ISOPEN)) { SET(tp->t_state, TS_WOPEN); /* set defaults */ ttychars(tp); tp->t_iflag = TTYDEF_IFLAG; tp->t_oflag = TTYDEF_OFLAG; tp->t_cflag = TTYDEF_CFLAG; if (ISSET(mp->mp_openflags, TIOCFLAG_CLOCAL)) SET(tp->t_cflag, CLOCAL); if (ISSET(mp->mp_openflags, TIOCFLAG_CRTSCTS)) SET(tp->t_cflag, CRTSCTS); if (ISSET(mp->mp_openflags, TIOCFLAG_MDMBUF)) SET(tp->t_cflag, MDMBUF); tp->t_lflag = TTYDEF_LFLAG; tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; /* init ring buffer */ mp->mp_rput = mp->mp_rget = mp->mp_rbuf; s = spltty(); /* reset CD1400 channel */ cd = mp->mp_cd1400; CD1400_WRITE_REG(cd, CD1400_CAR, mp->mp_channel); cd1400_write_ccr(cd, CD1400_CCR_CMDRESET); /* encode the port number in top half of LIVR */ CD1400_WRITE_REG(cd, CD1400_LIVR, port << 4); /* sets parameters and raises DTR */ (void)mtty_param(tp, &tp->t_termios); /* set tty watermarks */ ttsetwater(tp); /* enable service requests */ CD1400_WRITE_REG(cd, CD1400_SRER, CD1400_SRER_RXDATA | CD1400_SRER_MDMCH); /* tell the tty about the carrier status */ if (ISSET(mp->mp_openflags, TIOCFLAG_SOFTCAR) || mp->mp_carrier) SET(tp->t_state, TS_CARR_ON); else CLR(tp->t_state, TS_CARR_ON); } else if (ISSET(tp->t_state, TS_XCLUDE) && suser(p, 0) != 0) { return (EBUSY); /* superuser can break exclusive access */ } else { s = spltty(); } /* wait for carrier if necessary */ if (!ISSET(flags, O_NONBLOCK)) { while (!ISSET(tp->t_cflag, CLOCAL) && !ISSET(tp->t_state, TS_CARR_ON)) { int error; SET(tp->t_state, TS_WOPEN); error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH, "mttydcd", 0); if (error != 0) { splx(s); CLR(tp->t_state, TS_WOPEN); return (error); } } } splx(s); return ((*linesw[tp->t_line].l_open)(dev, tp, p)); }
int com_activate(struct device *self, int act) { struct com_softc *sc = (struct com_softc *)self; int s, rv = 0; switch (act) { case DVACT_SUSPEND: if (timeout_del(&sc->sc_dtr_tmo)) { /* Make sure DTR gets raised upon resume. */ SET(sc->sc_mcr, MCR_DTR | MCR_RTS); } timeout_del(&sc->sc_diag_tmo); break; case DVACT_RESUME: com_resume(sc); break; case DVACT_DEACTIVATE: #ifdef KGDB if (sc->sc_hwflags & (COM_HW_CONSOLE|COM_HW_KGDB)) { #else if (sc->sc_hwflags & COM_HW_CONSOLE) { #endif /* KGDB */ rv = EBUSY; break; } s = spltty(); if (sc->disable != NULL && sc->enabled != 0) { (*sc->disable)(sc); sc->enabled = 0; } splx(s); break; } return (rv); } int comopen(dev_t dev, int flag, int mode, struct proc *p) { int unit = DEVUNIT(dev); struct com_softc *sc; bus_space_tag_t iot; bus_space_handle_t ioh; struct tty *tp; int s; int error = 0; if (unit >= com_cd.cd_ndevs) return ENXIO; sc = com_cd.cd_devs[unit]; if (!sc) 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 /* KGDB */ s = spltty(); if (!sc->sc_tty) { tp = sc->sc_tty = ttymalloc(1000000); } else tp = sc->sc_tty; splx(s); tp->t_oproc = comstart; tp->t_param = comparam; tp->t_dev = dev; if (!ISSET(tp->t_state, TS_ISOPEN)) { SET(tp->t_state, TS_WOPEN); ttychars(tp); tp->t_iflag = TTYDEF_IFLAG; tp->t_oflag = TTYDEF_OFLAG; #ifdef COM_CONSOLE if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) { tp->t_cflag = comconscflag; tp->t_ispeed = tp->t_ospeed = comconsrate; } else #endif { tp->t_cflag = TTYDEF_CFLAG; tp->t_ispeed = tp->t_ospeed = comdefaultrate; } 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; s = spltty(); sc->sc_initialize = 1; comparam(tp, &tp->t_termios); ttsetwater(tp); 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; iot = sc->sc_iot; ioh = sc->sc_ioh; /* * Wake up the sleepy heads. */ if (!ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) { switch (sc->sc_uarttype) { case COM_UART_ST16650: case COM_UART_ST16650V2: bus_space_write_1(iot, ioh, com_lcr, LCR_EFR); bus_space_write_1(iot, ioh, com_efr, EFR_ECB); bus_space_write_1(iot, ioh, com_ier, 0); bus_space_write_1(iot, ioh, com_efr, 0); bus_space_write_1(iot, ioh, com_lcr, 0); break; case COM_UART_TI16750: bus_space_write_1(iot, ioh, com_ier, 0); break; case COM_UART_PXA2X0: bus_space_write_1(iot, ioh, com_ier, IER_EUART); break; } } if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) { u_int8_t fifo = FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST; u_int8_t lcr; if (tp->t_ispeed <= 1200) fifo |= FIFO_TRIGGER_1; else if (tp->t_ispeed <= 38400) fifo |= FIFO_TRIGGER_4; else fifo |= FIFO_TRIGGER_8; if (sc->sc_uarttype == COM_UART_TI16750) { fifo |= FIFO_ENABLE_64BYTE; lcr = bus_space_read_1(iot, ioh, com_lcr); bus_space_write_1(iot, ioh, com_lcr, lcr | LCR_DLAB); } /* * (Re)enable and drain FIFOs. * * Certain SMC chips cause problems if the FIFOs are * enabled while input is ready. Turn off the FIFO * if necessary to clear the input. Test the input * ready bit after enabling the FIFOs to handle races * between enabling and fresh input. * * Set the FIFO threshold based on the receive speed. */ for (;;) { bus_space_write_1(iot, ioh, com_fifo, 0); delay(100); (void) bus_space_read_1(iot, ioh, com_data); bus_space_write_1(iot, ioh, com_fifo, fifo | FIFO_RCV_RST | FIFO_XMT_RST); delay(100); if(!ISSET(bus_space_read_1(iot, ioh, com_lsr), LSR_RXRDY)) break; } if (sc->sc_uarttype == COM_UART_TI16750) bus_space_write_1(iot, ioh, com_lcr, lcr); } /* Flush any pending I/O. */ while (ISSET(bus_space_read_1(iot, ioh, com_lsr), LSR_RXRDY)) (void) bus_space_read_1(iot, ioh, 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); bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr); sc->sc_ier = IER_ERXRDY | IER_ERLS | IER_EMSC; #ifdef COM_PXA2X0 if (sc->sc_uarttype == COM_UART_PXA2X0) sc->sc_ier |= IER_EUART | IER_ERXTOUT; #endif bus_space_write_1(iot, ioh, com_ier, sc->sc_ier); sc->sc_msr = bus_space_read_1(iot, ioh, com_msr); if (ISSET(sc->sc_swflags, COM_SW_SOFTCAR) || DEVCUA(dev) || 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); #ifdef COM_PXA2X0 if (sc->sc_uarttype == COM_UART_PXA2X0 && ISSET(sc->sc_hwflags, COM_HW_SIR)) { bus_space_write_1(iot, ioh, com_isr, ISR_RECV); #ifdef __zaurus__ scoop_set_irled(1); #endif } #endif } else if (ISSET(tp->t_state, TS_XCLUDE) && suser(p, 0) != 0) return EBUSY; else s = spltty(); if (DEVCUA(dev)) { if (ISSET(tp->t_state, TS_ISOPEN)) { /* Ah, but someone already is dialed in... */ splx(s); return EBUSY; } sc->sc_cua = 1; /* We go into CUA mode. */ } else { /* tty (not cua) device; wait for carrier if necessary. */ if (ISSET(flag, O_NONBLOCK)) { if (sc->sc_cua) { /* Opening TTY non-blocking... but the CUA is busy. */ splx(s); return EBUSY; } } else { while (sc->sc_cua || (!ISSET(tp->t_cflag, CLOCAL) && !ISSET(tp->t_state, TS_CARR_ON))) { SET(tp->t_state, TS_WOPEN); error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH, ttopen, 0); /* * If TS_WOPEN has been reset, that means the cua device * has been closed. We don't want to fail in that case, * so just go around again. */ if (error && ISSET(tp->t_state, TS_WOPEN)) { CLR(tp->t_state, TS_WOPEN); if (!sc->sc_cua && !ISSET(tp->t_state, TS_ISOPEN)) compwroff(sc); splx(s); return error; } } } } splx(s); return (*linesw[tp->t_line].l_open)(dev, tp, p); }
int mfcsopen(dev_t dev, int flag, int mode, struct lwp *l) { struct tty *tp; struct mfcs_softc *sc; int unit, error; error = 0; unit = dev & 0x1f; sc = device_lookup_private(&mfcs_cd, unit); if (sc == NULL || (mfcs_active & (1 << unit)) == 0) return (ENXIO); if (sc->sc_tty) tp = sc->sc_tty; else { tp = sc->sc_tty = tty_alloc(); tty_attach(tp); } tp->t_oproc = (void (*) (struct tty *)) mfcsstart; tp->t_param = mfcsparam; tp->t_dev = dev; tp->t_hwiflow = mfcshwiflow; if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp)) return (EBUSY); mutex_spin_enter(&tty_lock); if ((tp->t_state & TS_ISOPEN) == 0 && tp->t_wopen == 0) { ttychars(tp); if (tp->t_ispeed == 0) { /* * only when cleared do we reset to defaults. */ tp->t_iflag = TTYDEF_IFLAG; tp->t_oflag = TTYDEF_OFLAG; tp->t_cflag = TTYDEF_CFLAG; tp->t_lflag = TTYDEF_LFLAG; tp->t_ispeed = tp->t_ospeed = mfcsdefaultrate; } /* * do these all the time */ if (sc->swflags & TIOCFLAG_CLOCAL) tp->t_cflag |= CLOCAL; if (sc->swflags & TIOCFLAG_CRTSCTS) tp->t_cflag |= CRTSCTS; if (sc->swflags & TIOCFLAG_MDMBUF) tp->t_cflag |= MDMBUF; mfcsparam(tp, &tp->t_termios); ttsetwater(tp); (void)mfcsmctl(dev, TIOCM_DTR | TIOCM_RTS, DMSET); if ((SWFLAGS(dev) & TIOCFLAG_SOFTCAR) || (mfcsmctl(dev, 0, DMGET) & TIOCM_CD)) tp->t_state |= TS_CARR_ON; else tp->t_state &= ~TS_CARR_ON; } /* * if NONBLOCK requested, ignore carrier */ if (flag & O_NONBLOCK) goto done; /* * block waiting for carrier */ while ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0) { tp->t_wopen++; error = ttysleep(tp, &tp->t_rawcv, true, 0); tp->t_wopen--; if (error) { mutex_spin_exit(&tty_lock); return(error); } } done: /* This is a way to handle lost XON characters */ if ((flag & O_TRUNC) && (tp->t_state & TS_TTSTOP)) { tp->t_state &= ~TS_TTSTOP; ttstart (tp); } /* * Reset the tty pointer, as there could have been a dialout * use of the tty with a dialin open waiting. */ tp->t_dev = dev; mutex_spin_exit(&tty_lock); return tp->t_linesw->l_open(dev, tp); }
/*ARGSUSED*/ static int nmdmopen(struct dev_open_args *ap) { cdev_t dev = ap->a_head.a_dev; struct tty *tp, *tp2; int error; int minr; #if 0 cdev_t nextdev; #endif struct nm_softc *pti; int is_b; int pair; struct softpart *ourpart, *otherpart; minr = lminor(dev); pair = minr >> 1; is_b = minr & 1; #if 0 /* * XXX: Gross hack for DEVFS: * If we openned this device, ensure we have the * next one too, so people can open it. */ if (pair < 127) { nextdev = makedev(major(dev), (pair+pair) + 1); if (!nextdev->si_drv1) { nmdminit(pair + 1); } } #endif if (!dev->si_drv1) nmdminit(pair); if (!dev->si_drv1) return(ENXIO); lwkt_gettoken(&tty_token); pti = dev->si_drv1; if (is_b) tp = &pti->part2.nm_tty; else tp = &pti->part1.nm_tty; GETPARTS(tp, ourpart, otherpart); tp2 = &otherpart->nm_tty; ourpart->modemsignals |= TIOCM_LE; if ((tp->t_state & TS_ISOPEN) == 0) { ttychars(tp); /* Set up default chars */ tp->t_iflag = TTYDEF_IFLAG; tp->t_oflag = TTYDEF_OFLAG; tp->t_lflag = TTYDEF_LFLAG; tp->t_cflag = TTYDEF_CFLAG; tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; } else if (tp->t_state & TS_XCLUDE && priv_check_cred(ap->a_cred, PRIV_ROOT, 0)) { lwkt_reltoken(&tty_token); return (EBUSY); } else if (pti->pt_prison != ap->a_cred->cr_prison) { lwkt_reltoken(&tty_token); return (EBUSY); } /* * If the other side is open we have carrier */ if (tp2->t_state & TS_ISOPEN) { (void)(*linesw[tp->t_line].l_modem)(tp, 1); } /* * And the other side gets carrier as we are now open. */ (void)(*linesw[tp2->t_line].l_modem)(tp2, 1); /* External processing makes no sense here */ tp->t_lflag &= ~EXTPROC; /* * Wait here if we don't have carrier. */ #if 0 while ((tp->t_state & TS_CARR_ON) == 0) { if (flag & FNONBLOCK) break; error = ttysleep(tp, TSA_CARR_ON(tp), PCATCH, "nmdopn", 0); if (error) { lwkt_reltoken(&tty_token); return (error); } } #endif /* * Give the line disciplin a chance to set this end up. */ error = (*linesw[tp->t_line].l_open)(dev, tp); /* * Wake up the other side. * Theoretically not needed. */ ourpart->modemsignals |= TIOCM_DTR; nmdm_crossover(pti, ourpart, otherpart); if (error == 0) wakeup_other(tp, FREAD|FWRITE); /* XXX */ lwkt_reltoken(&tty_token); return (error); }
int sxiuart_param(struct tty *tp, struct termios *t) { struct sxiuart_softc *sc = sxiuart_cd.cd_devs[DEVUNIT(tp->t_dev)]; bus_space_tag_t iot = sc->sc_iot; bus_space_handle_t ioh = sc->sc_ioh; int ospeed = t->c_ospeed; int error; tcflag_t oldcflag; uint16_t ratediv; uint8_t lcr; if (t->c_ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed)) return (EINVAL); /* XXX get prev state of SXIUART_LCR_SBREAK bit */ 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; if (ospeed == 0) { CLR(sc->sc_mcr, MCR_DTR); bus_space_write_1(iot, ioh, SXIUART_MCR, sc->sc_mcr); } if (ospeed != 0) { /* XXX sc_initialize? */ while (ISSET(tp->t_state, TS_BUSY)) { ++sc->sc_halt; error = ttysleep(tp, &tp->t_outq, TTOPRI | PCATCH, "sxiuartprm", 0); --sc->sc_halt; if (error) { sxiuart_start(tp); return (error); } } bus_space_write_1(iot, ioh, SXIUART_LCR, lcr | LCR_DLAB); ratediv = 13; bus_space_write_1(iot, ioh, SXIUART_DLL, ratediv); bus_space_write_1(iot, ioh, SXIUART_DLH, ratediv >> 8); bus_space_write_1(iot, ioh, SXIUART_LCR, lcr); SET(sc->sc_mcr, MCR_DTR); bus_space_write_1(iot, ioh, SXIUART_MCR, sc->sc_mcr); } else
int stty_open(dev_t dev, int flags, int mode, struct lwp *l) { struct spif_softc *csc; struct stty_softc *sc; struct stty_port *sp; struct tty *tp; int card = SPIF_CARD(dev); int port = SPIF_PORT(dev); sc = device_lookup_private(&stty_cd, card); csc = device_lookup_private(&spif_cd, card); if (sc == NULL || csc == NULL) return (ENXIO); if (port >= sc->sc_nports) return (ENXIO); sp = &sc->sc_port[port]; tp = sp->sp_tty; tp->t_dev = dev; if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp)) return (EBUSY); mutex_spin_enter(&tty_lock); 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(sp->sp_openflags, TIOCFLAG_CLOCAL)) SET(tp->t_cflag, CLOCAL); if (ISSET(sp->sp_openflags, TIOCFLAG_CRTSCTS)) SET(tp->t_cflag, CRTSCTS); if (ISSET(sp->sp_openflags, TIOCFLAG_MDMBUF)) SET(tp->t_cflag, MDMBUF); tp->t_lflag = TTYDEF_LFLAG; tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; sp->sp_rput = sp->sp_rget = sp->sp_rbuf; STC_WRITE(csc, STC_CAR, sp->sp_channel); stty_write_ccr(csc, CD180_CCR_CMD_RESET|CD180_CCR_RESETCHAN); STC_WRITE(csc, STC_CAR, sp->sp_channel); stty_param(tp, &tp->t_termios); ttsetwater(tp); STC_WRITE(csc, STC_SRER, CD180_SRER_CD | CD180_SRER_RXD); if (ISSET(sp->sp_openflags, TIOCFLAG_SOFTCAR) || sp->sp_carrier) SET(tp->t_state, TS_CARR_ON); else CLR(tp->t_state, TS_CARR_ON); } if (!ISSET(flags, O_NONBLOCK)) { while (!ISSET(tp->t_cflag, CLOCAL) && !ISSET(tp->t_state, TS_CARR_ON)) { int error; error = ttysleep(tp, &tp->t_rawcv, true, 0); if (error != 0) { mutex_spin_exit(&tty_lock); return (error); } } } mutex_spin_exit(&tty_lock); return ((*tp->t_linesw->l_open)(dev, tp)); }
static void si_command(struct si_port *pp, int cmd, int waitflag) { int oldspl; volatile struct si_channel *ccbp = pp->sp_ccb; int x; DPRINT((pp, DBG_ENTRY|DBG_PARAM, "si_command(%x,%x,%d): hi_stat 0x%x\n", pp, cmd, waitflag, ccbp->hi_stat)); oldspl = spltty(); /* Keep others out */ /* wait until it's finished what it was doing.. */ /* XXX: sits in IDLE_BREAK until something disturbs it or break * is turned off. */ while((x = ccbp->hi_stat) != IDLE_OPEN && x != IDLE_CLOSE && x != IDLE_BREAK && x != cmd) { if (in_intr) { /* Prevent sleep in intr */ DPRINT((pp, DBG_PARAM, "cmd intr collision - completing %d\trequested %d\n", x, cmd)); splx(oldspl); return; } else if (ttysleep(pp->sp_tty, (caddr_t)&pp->sp_state, TTIPRI|PCATCH, "sicmd1", 1)) { splx(oldspl); return; } } /* it should now be in IDLE_{OPEN|CLOSE|BREAK}, or "cmd" */ /* if there was a pending command, cause a state-change wakeup */ switch(pp->sp_pend) { case LOPEN: case MPEND: case MOPEN: case CONFIG: case SBREAK: case EBREAK: wakeup(&pp->sp_state); break; default: break; } pp->sp_pend = cmd; /* New command pending */ ccbp->hi_stat = cmd; /* Post it */ if (waitflag) { if (in_intr) { /* If in interrupt handler */ DPRINT((pp, DBG_PARAM, "attempt to sleep in si_intr - cmd req %d\n", cmd)); splx(oldspl); return; } else while(ccbp->hi_stat != IDLE_OPEN && ccbp->hi_stat != IDLE_BREAK) { if (ttysleep(pp->sp_tty, (caddr_t)&pp->sp_state, TTIPRI|PCATCH, "sicmd2", 0)) break; } } splx(oldspl); }
int ucomopen(dev_t dev, int flag, int mode, struct proc *p) { int unit = UCOMUNIT(dev); usbd_status err; struct ucom_softc *sc; struct tty *tp; struct termios t; int s; int error; if (unit >= ucom_cd.cd_ndevs) return (ENXIO); sc = ucom_cd.cd_devs[unit]; if (sc == NULL) return (ENXIO); if (sc->sc_dying) return (EIO); if (ISSET(sc->sc_dev.dv_flags, DVF_ACTIVE) == 0) return (ENXIO); /* open the pipes if this is the first open */ ucom_lock(sc); if (sc->sc_open++ == 0) { s = splusb(); DPRINTF(("ucomopen: open pipes in=%d out=%d\n", sc->sc_bulkin_no, sc->sc_bulkout_no)); DPRINTF(("ucomopen: hid %p pipes in=%p out=%p\n", sc->sc_uhidev, sc->sc_ipipe, sc->sc_opipe)); if (sc->sc_bulkin_no != -1) { /* Open the bulk pipes */ err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkin_no, 0, &sc->sc_bulkin_pipe); if (err) { DPRINTF(("%s: open bulk out error (addr %d), err=%s\n", sc->sc_dev.dv_xname, sc->sc_bulkin_no, usbd_errstr(err))); error = EIO; goto fail_0; } err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkout_no, USBD_EXCLUSIVE_USE, &sc->sc_bulkout_pipe); if (err) { DPRINTF(("%s: open bulk in error (addr %d), err=%s\n", sc->sc_dev.dv_xname, sc->sc_bulkout_no, usbd_errstr(err))); error = EIO; goto fail_1; } /* Allocate a request and an input buffer and start reading. */ sc->sc_ixfer = usbd_alloc_xfer(sc->sc_udev); if (sc->sc_ixfer == NULL) { error = ENOMEM; goto fail_2; } sc->sc_ibuf = usbd_alloc_buffer(sc->sc_ixfer, sc->sc_ibufsizepad); if (sc->sc_ibuf == NULL) { error = ENOMEM; goto fail_2; } sc->sc_oxfer = usbd_alloc_xfer(sc->sc_udev); if (sc->sc_oxfer == NULL) { error = ENOMEM; goto fail_3; } } else { /* * input/output pipes and xfers already allocated * as is the input buffer. */ sc->sc_ipipe = sc->sc_uhidev->sc_ipipe; sc->sc_ixfer = sc->sc_uhidev->sc_ixfer; sc->sc_opipe = sc->sc_uhidev->sc_opipe; sc->sc_oxfer = sc->sc_uhidev->sc_oxfer; } sc->sc_obuf = usbd_alloc_buffer(sc->sc_oxfer, sc->sc_obufsize + sc->sc_opkthdrlen); if (sc->sc_obuf == NULL) { error = ENOMEM; goto fail_4; } if (sc->sc_methods->ucom_open != NULL) { error = sc->sc_methods->ucom_open(sc->sc_parent, sc->sc_portno); if (error) { ucom_cleanup(sc); splx(s); ucom_unlock(sc); return (error); } } ucom_status_change(sc); ucomstartread(sc); splx(s); } ucom_unlock(sc); s = spltty(); tp = sc->sc_tty; splx(s); DPRINTF(("ucomopen: unit=%d, tp=%p\n", unit, tp)); tp->t_dev = dev; if (!ISSET(tp->t_state, TS_ISOPEN)) { SET(tp->t_state, TS_WOPEN); ttychars(tp); /* * Initialize the termios status to the defaults. Add in the * sticky bits from TIOCSFLAGS. */ t.c_ispeed = 0; 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 ucomparam() will do something. */ tp->t_ospeed = 0; (void) ucomparam(tp, &t); tp->t_iflag = TTYDEF_IFLAG; tp->t_oflag = TTYDEF_OFLAG; tp->t_lflag = TTYDEF_LFLAG; s = spltty(); ttsetwater(tp); /* * 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. */ ucom_dtr(sc, 1); /* XXX CLR(sc->sc_rx_flags, RX_ANY_BLOCK);*/ ucom_hwiflow(sc); if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR) || UCOMCUA(dev) || ISSET(sc->sc_msr, UMSR_DCD) || ISSET(tp->t_cflag, MDMBUF)) SET(tp->t_state, TS_CARR_ON); else CLR(tp->t_state, TS_CARR_ON); } else if (ISSET(tp->t_state, TS_XCLUDE) && p->p_ucred->cr_uid != 0) { error = EBUSY; goto bad; } else s = spltty(); if (UCOMCUA(dev)) { if (ISSET(tp->t_state, TS_ISOPEN)) { /* Someone is already dialed in */ error = EBUSY; goto bad1; } sc->sc_cua = 1; } else { /* tty (not cua) device, wait for carrier */ if (ISSET(flag, O_NONBLOCK)) { if (sc->sc_cua) { error = EBUSY; goto bad1; } } else { while (sc->sc_cua || (!ISSET(tp->t_cflag, CLOCAL) && !ISSET(tp->t_state, TS_CARR_ON))) { SET(tp->t_state, TS_WOPEN); error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH, ttopen, 0); /* * If TS_WOPEN has been reset, that means the * cua device has been closed. We don't want * to fail in that case, so just go around * again. */ if (error && ISSET(tp->t_state, TS_WOPEN)) { CLR(tp->t_state, TS_WOPEN); goto bad1; } } } } splx(s); error = ttyopen(UCOMUNIT(dev), tp); if (error) goto bad; error = (*LINESW(tp, l_open))(dev, tp); if (error) goto bad; return (0); fail_4: if (sc->sc_uhidev == NULL) usbd_free_xfer(sc->sc_oxfer); sc->sc_oxfer = NULL; fail_3: usbd_free_xfer(sc->sc_ixfer); sc->sc_ixfer = NULL; fail_2: usbd_close_pipe(sc->sc_bulkout_pipe); sc->sc_bulkout_pipe = NULL; fail_1: usbd_close_pipe(sc->sc_bulkin_pipe); sc->sc_bulkin_pipe = NULL; fail_0: splx(s); ucom_unlock(sc); return (error); bad1: splx(s); bad: ucom_lock(sc); ucom_cleanup(sc); ucom_unlock(sc); return (error); }
int imxuartopen(dev_t dev, int flag, int mode, struct proc *p) { int unit = DEVUNIT(dev); struct imxuart_softc *sc; bus_space_tag_t iot; bus_space_handle_t ioh; struct tty *tp; int s; int error = 0; if (unit >= imxuart_cd.cd_ndevs) return ENXIO; sc = imxuart_cd.cd_devs[unit]; if (sc == NULL) return ENXIO; s = spltty(); if (sc->sc_tty == NULL) tp = sc->sc_tty = ttymalloc(0); else tp = sc->sc_tty; splx(s); tp->t_oproc = imxuart_start; tp->t_param = imxuart_param; tp->t_dev = dev; if (!ISSET(tp->t_state, TS_ISOPEN)) { SET(tp->t_state, TS_WOPEN); ttychars(tp); tp->t_iflag = TTYDEF_IFLAG; tp->t_oflag = TTYDEF_OFLAG; if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) tp->t_cflag = imxuartconscflag; else 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 = imxuartdefaultrate; s = spltty(); sc->sc_initialize = 1; imxuart_param(tp, &tp->t_termios); ttsetwater(tp); sc->sc_ibufp = sc->sc_ibuf = sc->sc_ibufs[0]; sc->sc_ibufhigh = sc->sc_ibuf + IMXUART_IHIGHWATER; sc->sc_ibufend = sc->sc_ibuf + IMXUART_IBUFSIZE; iot = sc->sc_iot; ioh = sc->sc_ioh; sc->sc_ucr1 = bus_space_read_2(iot, ioh, IMXUART_UCR1); sc->sc_ucr2 = bus_space_read_2(iot, ioh, IMXUART_UCR2); sc->sc_ucr3 = bus_space_read_2(iot, ioh, IMXUART_UCR3); sc->sc_ucr4 = bus_space_read_2(iot, ioh, IMXUART_UCR4); /* interrupt after one char on tx/rx */ /* reference frequency divider: 1 */ bus_space_write_2(iot, ioh, IMXUART_UFCR, 1 << IMXUART_FCR_TXTL_SH | 5 << IMXUART_FCR_RFDIV_SH | 1 << IMXUART_FCR_RXTL_SH); bus_space_write_2(iot, ioh, IMXUART_UBIR, (imxuartdefaultrate / 100) - 1); /* formula: clk / (rfdiv * 1600) */ bus_space_write_2(iot, ioh, IMXUART_UBMR, (imxccm_get_uartclk() * 1000) / 1600); SET(sc->sc_ucr1, IMXUART_CR1_EN|IMXUART_CR1_RRDYEN); SET(sc->sc_ucr2, IMXUART_CR2_TXEN|IMXUART_CR2_RXEN); bus_space_write_2(iot, ioh, IMXUART_UCR1, sc->sc_ucr1); bus_space_write_2(iot, ioh, IMXUART_UCR2, sc->sc_ucr2); /* sc->sc_mcr = MCR_DTR | MCR_RTS; XXX */ SET(sc->sc_ucr3, IMXUART_CR3_DSR); /* XXX */ bus_space_write_2(iot, ioh, IMXUART_UCR3, sc->sc_ucr3); SET(tp->t_state, TS_CARR_ON); /* XXX */ } else if (ISSET(tp->t_state, TS_XCLUDE) && p->p_ucred->cr_uid != 0) return EBUSY; else s = spltty(); if (DEVCUA(dev)) { if (ISSET(tp->t_state, TS_ISOPEN)) { splx(s); return EBUSY; } sc->sc_cua = 1; } else { /* tty (not cua) device; wait for carrier if necessary */ if (ISSET(flag, O_NONBLOCK)) { if (sc->sc_cua) { /* Opening TTY non-blocking... but the CUA is busy */ splx(s); return EBUSY; } } else { while (sc->sc_cua || (!ISSET(tp->t_cflag, CLOCAL) && !ISSET(tp->t_state, TS_CARR_ON))) { SET(tp->t_state, TS_WOPEN); error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH, ttopen, 0); /* * If TS_WOPEN has been reset, that means the * cua device has been closed. We don't want * to fail in that case, * so just go around again. */ if (error && ISSET(tp->t_state, TS_WOPEN)) { CLR(tp->t_state, TS_WOPEN); if (!sc->sc_cua && !ISSET(tp->t_state, TS_ISOPEN)) imxuart_pwroff(sc); splx(s); return error; } } } } splx(s); return (*linesw[tp->t_line].l_open)(dev,tp,p); }
int imxuart_param(struct tty *tp, struct termios *t) { struct imxuart_softc *sc = imxuart_cd.cd_devs[DEVUNIT(tp->t_dev)]; bus_space_tag_t iot = sc->sc_iot; bus_space_handle_t ioh = sc->sc_ioh; int ospeed = t->c_ospeed; int error; tcflag_t oldcflag; if (t->c_ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed)) return EINVAL; switch (ISSET(t->c_cflag, CSIZE)) { case CS5: return EINVAL; case CS6: return EINVAL; case CS7: CLR(sc->sc_ucr2, IMXUART_CR2_WS); break; case CS8: SET(sc->sc_ucr2, IMXUART_CR2_WS); break; } // bus_space_write_2(iot, ioh, IMXUART_UCR2, sc->sc_ucr2); if (ISSET(t->c_cflag, PARENB)) { SET(sc->sc_ucr2, IMXUART_CR2_PREN); bus_space_write_2(iot, ioh, IMXUART_UCR2, sc->sc_ucr2); } /* STOPB - XXX */ if (ospeed == 0) { /* lower dtr */ } if (ospeed != 0) { while (ISSET(tp->t_state, TS_BUSY)) { ++sc->sc_halt; error = ttysleep(tp, &tp->t_outq, TTOPRI | PCATCH, "imxuartprm", 0); --sc->sc_halt; if (error) { imxuart_start(tp); return (error); } } /* set speed */ } /* setup fifo */ /* When not using CRTSCTS, RTS follows DTR. */ /* 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. */ /* XXX */ imxuart_start(tp); return 0; }
static int ptsread(struct dev_read_args *ap) { cdev_t dev = ap->a_head.a_dev; struct proc *p = curproc; struct tty *tp = dev->si_tty; struct pt_ioctl *pti = dev->si_drv1; struct lwp *lp; int error = 0; lp = curthread->td_lwp; lwkt_gettoken(&tty_token); again: if (pti->pt_flags & PF_REMOTE) { while (isbackground(p, tp)) { if (SIGISMEMBER(p->p_sigignore, SIGTTIN) || SIGISMEMBER(lp->lwp_sigmask, SIGTTIN) || p->p_pgrp->pg_jobc == 0 || (p->p_flags & P_PPWAIT)) { lwkt_reltoken(&tty_token); return (EIO); } pgsignal(p->p_pgrp, SIGTTIN, 1); error = ttysleep(tp, &lbolt, PCATCH, "ptsbg", 0); if (error) { lwkt_reltoken(&tty_token); return (error); } } if (tp->t_canq.c_cc == 0) { if (ap->a_ioflag & IO_NDELAY) { lwkt_reltoken(&tty_token); return (EWOULDBLOCK); } error = ttysleep(tp, TSA_PTS_READ(tp), PCATCH, "ptsin", 0); if (error) { lwkt_reltoken(&tty_token); return (error); } goto again; } while (tp->t_canq.c_cc > 1 && ap->a_uio->uio_resid > 0) if (ureadc(clist_getc(&tp->t_canq), ap->a_uio) < 0) { error = EFAULT; break; } if (tp->t_canq.c_cc == 1) clist_getc(&tp->t_canq); if (tp->t_canq.c_cc) { lwkt_reltoken(&tty_token); return (error); } } else if (tp->t_oproc) error = (*linesw[tp->t_line].l_read)(tp, ap->a_uio, ap->a_ioflag); ptcwakeup(tp, FWRITE); lwkt_reltoken(&tty_token); return (error); }
/*ARGSUSED*/ static int ptsopen(struct dev_open_args *ap) { cdev_t dev = ap->a_head.a_dev; struct tty *tp; int error; struct pt_ioctl *pti; /* * The pti will already be assigned by the clone code or * pre-created if a non-unix 98 pty. If si_drv1 is NULL * we are somehow racing a unix98 termination. */ if (dev->si_drv1 == NULL) return(ENXIO); pti = dev->si_drv1; lwkt_gettoken(&tty_token); if (pti_hold(pti)) { lwkt_reltoken(&tty_token); return(ENXIO); } tp = dev->si_tty; /* * Reinit most of the tty state if it isn't open. Handle * exclusive access. */ if ((tp->t_state & TS_ISOPEN) == 0) { ttychars(tp); /* Set up default chars */ tp->t_iflag = TTYDEF_IFLAG; tp->t_oflag = TTYDEF_OFLAG; tp->t_lflag = TTYDEF_LFLAG; tp->t_cflag = TTYDEF_CFLAG; tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; } else if ((tp->t_state & TS_XCLUDE) && priv_check_cred(ap->a_cred, PRIV_ROOT, 0)) { pti_done(pti); lwkt_reltoken(&tty_token); return (EBUSY); } else if (pti->pt_prison != ap->a_cred->cr_prison) { pti_done(pti); lwkt_reltoken(&tty_token); return (EBUSY); } /* * If the ptc is already present this will connect us up. It * is unclear if this is actually needed. * * If neither side is open be sure to clear any left over * ZOMBIE state before continuing. */ if (tp->t_oproc) (void)(*linesw[tp->t_line].l_modem)(tp, 1); else if ((pti->pt_flags & PF_SOPEN) == 0) tp->t_state &= ~TS_ZOMBIE; /* * Wait for the carrier (ptc side) */ while ((tp->t_state & TS_CARR_ON) == 0) { if (ap->a_oflags & FNONBLOCK) break; error = ttysleep(tp, TSA_CARR_ON(tp), PCATCH, "ptsopn", 0); if (error) { pti_done(pti); lwkt_reltoken(&tty_token); return (error); } } /* * Mark the tty open and mark the slave side as being open. */ error = (*linesw[tp->t_line].l_open)(dev, tp); if (error == 0) { pti->pt_flags |= PF_SOPEN; pti->pt_flags &= ~PF_SCLOSED; ptcwakeup(tp, FREAD|FWRITE); } pti_done(pti); lwkt_reltoken(&tty_token); return (error); }
/* * Open a zs serial (tty) port. */ int zsopen(dev_t dev, int flags, int mode, struct proc *p) { struct zstty_softc *zst; struct zs_chanstate *cs; struct tty *tp; int s; #if IPL_ZS != IPL_TTY int s2; #endif int error; zst = zs_device_lookup(&zstty_cd, ZSUNIT(dev)); if (zst == NULL) return (ENXIO); tp = zst->zst_tty; cs = zst->zst_cs; /* If KGDB took the line, then tp==NULL */ if (tp == NULL) return (EBUSY); if (ISSET(tp->t_state, TS_ISOPEN) && ISSET(tp->t_state, TS_XCLUDE) && suser(p, 0) != 0) return (EBUSY); s = spltty(); /* * Do the following iff this is a first open. */ if (!ISSET(tp->t_state, TS_ISOPEN)) { struct termios t; tp->t_dev = dev; /* Call the power management hook. */ if (cs->enable) { if ((*cs->enable)(cs)) { splx(s); printf("%s: device enable failed\n", zst->zst_dev.dv_xname); return (EIO); } } /* * Initialize the termios status to the defaults. Add in the * sticky bits from TIOCSFLAGS. */ t.c_ispeed = 0; t.c_ospeed = cs->cs_defspeed; t.c_cflag = cs->cs_defcflag; if (ISSET(zst->zst_swflags, TIOCFLAG_CLOCAL)) SET(t.c_cflag, CLOCAL); if (ISSET(zst->zst_swflags, TIOCFLAG_CRTSCTS)) SET(t.c_cflag, CRTSCTS); if (ISSET(zst->zst_swflags, TIOCFLAG_MDMBUF)) SET(t.c_cflag, MDMBUF); #if IPL_ZS != IPL_TTY s2 = splzs(); #endif /* * Turn on receiver and status interrupts. * We defer the actual write of the register to zsparam(), * but we must make sure status interrupts are turned on by * the time zsparam() reads the initial rr0 state. */ SET(cs->cs_preg[1], ZSWR1_RIE | ZSWR1_TIE | ZSWR1_SIE); /* Clear PPS capture state on first open. */ zst->zst_ppsmask = 0; #if IPL_ZS != IPL_TTY splx(s2); #endif /* Make sure zsparam will see changes. */ tp->t_ospeed = 0; (void)zsparam(tp, &t); /* * Note: zsparam has done: cflag, ispeed, ospeed * so we just need to do: iflag, oflag, lflag, cc * For "raw" mode, just leave all zeros. */ if (!ISSET(zst->zst_hwflags, ZS_HWFLAG_RAW)) { tp->t_iflag = TTYDEF_IFLAG; tp->t_oflag = TTYDEF_OFLAG; tp->t_lflag = TTYDEF_LFLAG; } else { tp->t_iflag = 0; tp->t_oflag = 0; tp->t_lflag = 0; } ttychars(tp); ttsetwater(tp); if (ZSDIALOUT(dev)) SET(tp->t_state, TS_CARR_ON); else CLR(tp->t_state, TS_CARR_ON); #if IPL_ZS != IPL_TTY s2 = splzs(); #endif /* Clear the input ring, and unblock. */ zst->zst_rbget = zst->zst_rbput = zst->zst_rbuf; zst->zst_rbavail = zstty_rbuf_size; zs_iflush(cs); CLR(zst->zst_rx_flags, RX_ANY_BLOCK); zs_hwiflow(zst); #if IPL_ZS != IPL_TTY splx(s2); #endif } if (ZSDIALOUT(dev)) { if (ISSET(tp->t_state, TS_ISOPEN)) { /* someone already is dialed in... */ splx(s); return EBUSY; } cs->cs_cua = 1; } error = 0; /* wait for carrier if necessary */ if (ISSET(flags, O_NONBLOCK)) { if (!ZSDIALOUT(dev) && cs->cs_cua) { /* Opening TTY non-blocking... but the CUA is busy */ error = EBUSY; } } else while (cs->cs_cua || (!ISSET(tp->t_cflag, CLOCAL) && !ISSET(tp->t_state, TS_CARR_ON))) { int rr0; error = 0; SET(tp->t_state, TS_WOPEN); if (!ZSDIALOUT(dev) && !cs->cs_cua) { /* * Turn on DTR. We must always do this on non-CUA * devices, 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. */ #if IPL_ZS != IPL_TTY s2 = splzs(); #endif zs_modem(zst, 1); rr0 = zs_read_csr(cs); #if IPL_ZS != IPL_TTY splx(s2); #endif /* loop, turning on the device, until carrier present */ if (ISSET(rr0, ZSRR0_DCD) || ISSET(zst->zst_swflags, TIOCFLAG_SOFTCAR)) SET(tp->t_state, TS_CARR_ON); } if ((ISSET(tp->t_cflag, CLOCAL) || ISSET(tp->t_state, TS_CARR_ON)) && !cs->cs_cua) break; error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, ttopen, 0); if (!ZSDIALOUT(dev) && cs->cs_cua && error == EINTR) { error = 0; continue; } if (error) { if (!ISSET(tp->t_state, TS_ISOPEN)) { #if IPL_ZS != IPL_TTY s2 = splzs(); #endif zs_modem(zst, 0); #if IPL_ZS != IPL_TTY splx(s2); #endif CLR(tp->t_state, TS_WOPEN); ttwakeup(tp); } if (ZSDIALOUT(dev)) cs->cs_cua = 0; CLR(tp->t_state, TS_WOPEN); break; } if (!ZSDIALOUT(dev) && cs->cs_cua) continue; } splx(s); if (error == 0) error = ((*linesw[tp->t_line].l_open)(dev, tp, p)); if (error) goto bad; return (0); bad: if (!ISSET(tp->t_state, TS_ISOPEN)) { /* * We failed to open the device, and nobody else had it opened. * Clean up the state as appropriate. */ zs_shutdown(zst); } return (error); }