Esempio n. 1
0
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);
}
Esempio n. 2
0
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);
}
Esempio n. 3
0
/*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);
}
Esempio n. 4
0
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);
}
Esempio n. 5
0
/*
 * 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));
}
Esempio n. 6
0
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);
}
Esempio n. 7
0
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);
}
Esempio n. 8
0
/*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);
}
Esempio n. 9
0
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
Esempio n. 10
0
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));
}
Esempio n. 11
0
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);
}
Esempio n. 12
0
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);
}
Esempio n. 13
0
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);
}
Esempio n. 14
0
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;
}
Esempio n. 15
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);
}
Esempio n. 16
0
/*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);
}
Esempio n. 17
0
/*
 * 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);
}