示例#1
0
int
xencons_open(dev_t dev, int flag, int mode, struct lwp *l)
{
    struct xencons_softc *sc;
    struct tty *tp;

    sc = device_lookup_private(&xencons_cd, XENCONS_UNIT(dev));
    if (sc == NULL)
        return (ENXIO);

    tp = sc->sc_tty;

    if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp))
        return (EBUSY);

    if ((tp->t_state & TS_ISOPEN) == 0 && tp->t_wopen == 0) {
        tp->t_dev = dev;
        ttychars(tp);
        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;
        xencons_param(tp, &tp->t_termios);
        ttsetwater(tp);
    }
    tp->t_state |= TS_CARR_ON;

    return ((*tp->t_linesw->l_open)(dev, tp));
}
示例#2
0
int
uart_open(dev_t dev, int flag, int mode, struct lwp *l)
{
	struct uart_softc *sc = device_lookup_private(&uart_cd, minor(dev));
	struct tty *tp = sc->sc_tty;
	int s, error = 0;

	s = spltty();

	tp->t_dev = dev;
	if ((tp->t_state & TS_ISOPEN) == 0) {
		tp->t_state |= TS_CARR_ON;
		ttychars(tp);
		tp->t_iflag = TTYDEF_IFLAG;
		tp->t_oflag = TTYDEF_OFLAG;
		tp->t_cflag = TTYDEF_CFLAG | CLOCAL;
		tp->t_lflag = TTYDEF_LFLAG;
		tp->t_ispeed = tp->t_ospeed = 115200;
		ttsetwater(tp);
	} else if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN,
	    tp) != 0) {
		splx(s);
		return (EBUSY);
	}

	splx(s);

	error = (*tp->t_linesw->l_open)(dev, tp);

	return (error);
}
示例#3
0
int
biconsdevopen(dev_t dev, int flag, int mode, struct lwp *l)
{
	struct tty *tp = &biconsdev_tty[0];
	int status;

	if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp))
		return (EBUSY);

	if ((tp->t_state & TS_ISOPEN) == 0) {
		/*
		 * Leave baud rate alone!
		 */
		ttychars(tp);
		tp->t_iflag = TTYDEF_IFLAG;
		tp->t_oflag = TTYDEF_OFLAG;
		tp->t_lflag = TTYDEF_LFLAG;
		tp->t_cflag = TTYDEF_CFLAG;
		tp->t_state = TS_ISOPEN | TS_CARR_ON;
		(void)(*tp->t_param)(tp, &tp->t_termios);
		ttsetwater(tp);
	}

	status = (*tp->t_linesw->l_open)(dev, tp);
	return status;
}
示例#4
0
文件: cons.c 项目: goroutines/rumprun
int
cnioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
{
	int error;

	error = 0;

	/*
	 * Superuser can always use this to wrest control of console
	 * output from the "virtual" console.
	 */
	if (cmd == TIOCCONS && constty != NULL) {
		error = kauth_authorize_device_tty(l->l_cred,
		    KAUTH_DEVICE_TTY_VIRTUAL, constty);
		if (!error)
			constty = NULL;
		return (error);
	}

	/*
	 * Redirect the ioctl, if that's appropriate.
	 * Note that strange things can happen, if a program does
	 * ioctls on /dev/console, then the console is redirected
	 * out from under it.
	 */
	if (!cn_redirect(&dev, 0, &error))
		return error;
	return cdev_ioctl(dev, cmd, data, flag, l);
}
示例#5
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);
}
示例#6
0
int
kdopen(dev_t dev, int flag, int mode, struct lwp *l)
{
	struct kd_softc *kd;
	int error, s, unit;
	struct tty *tp;
static	int firstopen = 1;

	unit = minor(dev);
	if (unit != 0)
		return ENXIO;

	kd = &kd_softc; 	/* XXX */
	if (firstopen) {
		kd_init(kd);
		firstopen = 0;
	}

	tp = kd->kd_tty;

	/* It's simpler to do this up here. */
	if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp))
		return (EBUSY);

	s = spltty();
	if ((tp->t_state & TS_ISOPEN) == 0) {
		/* First open. */

		/* Notify the input device that serves us */
		struct cons_channel *cc = kd->kd_in;
		if (cc != NULL &&
		    (error = (*cc->cc_iopen)(cc)) != 0) {
			return (error);
		}

		ttychars(tp);
		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) kdparam(tp, &tp->t_termios);
		ttsetwater(tp);
		tp->t_winsize.ws_row = kd->rows;
		tp->t_winsize.ws_col = kd->cols;
		/* Flush pending input?  Clear translator? */
		/* This (pseudo)device always has SOFTCAR */
		tp->t_state |= TS_CARR_ON;
	}

	splx(s);

	return ((*tp->t_linesw->l_open)(dev, tp));
}
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
arcbios_ttyopen(dev_t dev, int flag, int mode, struct lwp *l)
{
	int unit = minor(dev);
	struct tty *tp;
	int s, error = 0, setuptimeout = 0;

	if (!arcbios_ch_init) {
		arcbios_ch_init = true;
		callout_init(&arcbios_tty_ch, 0);
	}

	if (unit != 0)
		return (ENODEV);

	s = spltty();

	if (arcbios_tty[unit] == NULL) {
		tp = arcbios_tty[unit] = tty_alloc();
		tty_attach(tp);
	} else
		tp = arcbios_tty[unit];

	tp->t_oproc = arcbios_tty_start;
	tp->t_param = arcbios_tty_param;
	tp->t_dev = dev;

	if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp)) {
		splx(s);
		return (EBUSY);
	}

	if ((tp->t_state & TS_ISOPEN) == 0) {
		tp->t_state |= TS_CARR_ON;
		ttychars(tp);
		tp->t_iflag = TTYDEF_IFLAG;
		tp->t_oflag = TTYDEF_OFLAG;
		tp->t_cflag = TTYDEF_CFLAG | CLOCAL;
		tp->t_lflag = TTYDEF_LFLAG;
		tp->t_ispeed = tp->t_ospeed = 9600;
		ttsetwater(tp);

		setuptimeout = 1;
	}

	splx(s);

	error = (*tp->t_linesw->l_open)(dev, tp);
	if (error == 0 && setuptimeout)
		callout_reset(&arcbios_tty_ch, 1, arcbios_tty_poll, tp);

	return (error);
}
示例#9
0
int
dlopen(dev_t dev, int flag, int mode, struct lwp *l)
{
	struct tty *tp;
	struct dl_softc *sc;
	int unit;

	unit = minor(dev);

	sc = device_lookup_private(&dl_cd, unit);
	if (!sc)
		return ENXIO;

	tp = sc->sc_tty;
	if (tp == NULL)
		return ENODEV;
	tp->t_oproc = dlstart;
	tp->t_param = dlparam;
	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)) {
		ttychars(tp);
		tp->t_iflag = TTYDEF_IFLAG;
		tp->t_oflag = TTYDEF_OFLAG;
		/* No modem control, so set CLOCAL. */
		tp->t_cflag = TTYDEF_CFLAG | CLOCAL;
		tp->t_lflag = TTYDEF_LFLAG;
		tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;

		dlparam(tp, &tp->t_termios);
		ttsetwater(tp);

	}

	return ((*tp->t_linesw->l_open)(dev, tp));
}
示例#10
0
int 
pconsopen(dev_t dev, int flag, int mode, struct lwp *l)
{
	struct pconssoftc *sc;
	struct tty *tp;
	
	sc = device_lookup_private(&pcons_cd, minor(dev));
	if (sc == NULL)
		return ENXIO;
	if ((tp = sc->of_tty) == NULL)
		sc->of_tty = tp = tty_alloc();
	tp->t_oproc = pconsstart;
	tp->t_param = pconsparam;
	tp->t_dev = dev;
	cn_tab->cn_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);
		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;
		pconsparam(tp, &tp->t_termios);
		ttsetwater(tp);
	}
	tp->t_state |= TS_CARR_ON;
	
	if ((sc->of_flags & OFPOLL) == 0) {
		sc->of_flags |= OFPOLL;
		callout_reset(&sc->sc_poll_ch, 1, pcons_poll, sc);
	}

	return (*tp->t_linesw->l_open)(dev, tp);
}
示例#11
0
/*
 * open routine. returns zero if successful, else error code
 */
int
mttyopen(dev_t dev, int flags, int mode, struct lwp *l)
{
	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 error, s;

	if ((ms = device_lookup_private(&mtty_cd, 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 (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) {

		/* 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;

		/* 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);
	}
	splx(s);

	error = ttyopen(tp, MTTY_DIALOUT(dev), ISSET(flags, O_NONBLOCK));
	if (error != 0)
		goto bad;

	error = (*tp->t_linesw->l_open)(dev, tp);
	if (error != 0)
		goto bad;

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.
		 */
		/* XXX - do that here */
	}

	return (error);
}
示例#12
0
/*
 * czttyopen:
 *
 *	Open a Cyclades-Z serial port.
 */
static int
czttyopen(dev_t dev, int flags, int mode, struct lwp *l)
{
	struct cztty_softc *sc = CZTTY_SOFTC(dev);
	struct cz_softc *cz;
	struct tty *tp;
	int s, error;

	if (sc == NULL)
		return (ENXIO);

	if (sc->sc_channel == CZTTY_CHANNEL_DEAD)
		return (ENXIO);

	cz = CZTTY_CZ(sc);
	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 we're turning things on, enable interrupts */
		if ((cz->cz_nopenchan++ == 0) && (cz->cz_ih == NULL)) {
#ifdef CZ_DEBUG
			printf("%s: Enabling polling.\n",
			    device_xname(cz->cz_dev));
#endif
			callout_reset(&cz->cz_callout, cz_timeout_ticks,
			    cz_poll, cz);
		}

		/*
		 * Enable the channel.  Don't actually ring the
		 * doorbell here; czttyparam() will do it for us.
		 */
		cz_wait_pci_doorbell(cz, "czopen");

		CZTTY_CHAN_WRITE(sc, CHNCTL_OP_MODE, C_CH_ENABLE);

		/*
		 * 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);

		/*
		 * Reset the input and output rings.  Do this before
		 * we call czttyparam(), as that function enables
		 * the channel.
		 */
		CZTTY_BUF_WRITE(sc, BUFCTL_RX_GET,
		    CZTTY_BUF_READ(sc, BUFCTL_RX_PUT));
		CZTTY_BUF_WRITE(sc, BUFCTL_TX_PUT,
		    CZTTY_BUF_READ(sc, BUFCTL_TX_GET));

		/* Make sure czttyparam() will see changes. */
		tp->t_ospeed = 0;
		(void) czttyparam(tp, &t);
		tp->t_iflag = TTYDEF_IFLAG;
		tp->t_oflag = TTYDEF_OFLAG;
		tp->t_lflag = TTYDEF_LFLAG;
		ttychars(tp);
		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.
		 */
		cztty_modem(sc, 1);
	}

	splx(s);

	error = ttyopen(tp, CZTTY_DIALOUT(dev), ISSET(flags, 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.
		 */
		cztty_shutdown(sc);
	}

	return (error);
}
示例#13
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);
}
示例#14
0
/*
 * ioctl routine
 */
int
mttyioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l)
{
	struct mtty_softc *ms = device_lookup_private(&mtty_cd,
						      MAGMA_CARD(dev));
	struct mtty_port *mp = &ms->ms_port[MAGMA_PORT(dev)];
	struct tty *tp = mp->mp_tty;
	int error;

	error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flags, l);
	if( error != EPASSTHROUGH ) return(error);

	error = ttioctl(tp, cmd, data, flags, l);
	if( error != EPASSTHROUGH ) return(error);

	error = 0;

	switch(cmd) {
	case TIOCSBRK:	/* set break */
		SET(mp->mp_flags, MTTYF_SET_BREAK);
		cd1400_enable_transmitter(mp->mp_cd1400, mp->mp_channel);
		break;

	case TIOCCBRK:	/* clear break */
		SET(mp->mp_flags, MTTYF_CLR_BREAK);
		cd1400_enable_transmitter(mp->mp_cd1400, mp->mp_channel);
		break;

	case TIOCSDTR:	/* set DTR */
		mtty_modem_control(mp, TIOCM_DTR, DMBIS);
		break;

	case TIOCCDTR:	/* clear DTR */
		mtty_modem_control(mp, TIOCM_DTR, DMBIC);
		break;

	case TIOCMSET:	/* set modem lines */
		mtty_modem_control(mp, *((int *)data), DMSET);
		break;

	case TIOCMBIS:	/* bit set modem lines */
		mtty_modem_control(mp, *((int *)data), DMBIS);
		break;

	case TIOCMBIC:	/* bit clear modem lines */
		mtty_modem_control(mp, *((int *)data), DMBIC);
		break;

	case TIOCMGET:	/* get modem lines */
		*((int *)data) = mtty_modem_control(mp, 0, DMGET);
		break;

	case TIOCGFLAGS:
		*((int *)data) = mp->mp_openflags;
		break;

	case TIOCSFLAGS:
		if (kauth_authorize_device_tty(l->l_cred, 
		    KAUTH_DEVICE_TTY_PRIVSET, tp))
			error = EPERM;
		else
			mp->mp_openflags = *((int *)data) &
				(TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL |
				TIOCFLAG_CRTSCTS | TIOCFLAG_MDMBUF);
		break;

	default:
		error = EPASSTHROUGH;
	}

	return(error);
}
示例#15
0
/*
 * czttyioctl:
 *
 *	Perform a control operation on a Cyclades-Z serial port.
 */
static int
czttyioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
{
	struct cztty_softc *sc = CZTTY_SOFTC(dev);
	struct tty *tp = sc->sc_tty;
	int s, 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);

	error = 0;

	s = spltty();

	switch (cmd) {
	case TIOCSBRK:
		cztty_break(sc, 1);
		break;

	case TIOCCBRK:
		cztty_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;

	case TIOCSDTR:
		cztty_modem(sc, 1);
		break;

	case TIOCCDTR:
		cztty_modem(sc, 0);
		break;

	case TIOCMSET:
	case TIOCMBIS:
	case TIOCMBIC:
		tiocm_to_cztty(sc, cmd, *(int *)data);
		break;

	case TIOCMGET:
		*(int *)data = cztty_to_tiocm(sc);
		break;

	default:
		error = EPASSTHROUGH;
		break;
	}

	splx(s);

	return (error);
}
示例#16
0
int
sscomopen(dev_t dev, int flag, int mode, struct lwp *l)
{
	struct sscom_softc *sc;
	struct tty *tp;
	int s, s2;
	int error;

	sc = device_lookup_private(&sscom_cd, SSCOMUNIT(dev));
	if (sc == NULL || !ISSET(sc->sc_hwflags, SSCOM_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, SSCOM_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();
		SSCOM_LOCK(sc);

		/* Turn on interrupts. */
		sscom_enable_txrxint(sc);

		/* Fetch the current modem control status, needed later. */
		sc->sc_msts = sc->sc_read_modem_status(sc);

#if 0
		/* Clear PPS capture state on first open. */
		sc->sc_ppsmask = 0;
		sc->ppsparam.mode = 0;
#endif

		SSCOM_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, SSCOM_HW_CONSOLE)) {
			t.c_ospeed = sscomconsrate;
			t.c_cflag = sscomconscflag;
		} 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 sscomparam() will do something. */
		tp->t_ospeed = 0;
		(void) sscomparam(tp, &t);
		tp->t_iflag = TTYDEF_IFLAG;
		tp->t_oflag = TTYDEF_OFLAG;
		tp->t_lflag = TTYDEF_LFLAG;
		ttychars(tp);
		ttsetwater(tp);

		s2 = splserial();
		SSCOM_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.
		 */
		sscom_modem(sc, 1);

		/* Clear the input ring, and unblock. */
		sc->sc_rbput = sc->sc_rbget = sc->sc_rbuf;
		sc->sc_rbavail = sscom_rbuf_size;
		sscom_iflush(sc);
		CLR(sc->sc_rx_flags, RX_ANY_BLOCK);
		sscom_hwiflow(sc);

		if (sscom_debug)
			sscomstatus(sc, "sscomopen  ");

		SSCOM_UNLOCK(sc);
		splx(s2);
	}
	
	splx(s);

	error = ttyopen(tp, SSCOMDIALOUT(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.
		 */
		sscom_shutdown(sc);
	}

	return error;
}
示例#17
0
文件: ucom.c 项目: ryoon/netbsd-xhci
static int
ucom_do_ioctl(struct ucom_softc *sc, u_long cmd, void *data,
	      int flag, struct lwp *l)
{
	struct tty *tp = sc->sc_tty;
	int error;
	int s;

	DPRINTF(("ucomioctl: cmd=0x%08lx\n", cmd));

	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);

	if (sc->sc_methods->ucom_ioctl != NULL) {
		error = sc->sc_methods->ucom_ioctl(sc->sc_parent,
			    sc->sc_portno, cmd, data, flag, l->l_proc);
		if (error != EPASSTHROUGH)
			return (error);
	}

	error = 0;

	DPRINTF(("ucomioctl: our cmd=0x%08lx\n", cmd));
	s = spltty();

	switch (cmd) {
	case TIOCSBRK:
		ucom_break(sc, 1);
		break;

	case TIOCCBRK:
		ucom_break(sc, 0);
		break;

	case TIOCSDTR:
		ucom_dtr(sc, 1);
		break;

	case TIOCCDTR:
		ucom_dtr(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_ucom(sc, cmd, *(int *)data);
		break;

	case TIOCMGET:
		*(int *)data = ucom_to_tiocm(sc);
		break;

	case PPS_IOC_CREATE:
	case PPS_IOC_DESTROY:
	case PPS_IOC_GETPARAMS:
	case PPS_IOC_SETPARAMS:
	case PPS_IOC_GETCAP:
	case PPS_IOC_FETCH:
#ifdef PPS_SYNC
	case PPS_IOC_KCBIND:
#endif
		mutex_spin_enter(&timecounter_lock);
		error = pps_ioctl(cmd, data, &sc->sc_pps_state);
		mutex_spin_exit(&timecounter_lock);
		break;

	default:
		error = EPASSTHROUGH;
		break;
	}

	splx(s);

	return (error);
}
示例#18
0
int
sscomioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
{
	struct sscom_softc *sc = device_lookup_private(&sscom_cd, SSCOMUNIT(dev));
	struct tty *tp = sc->sc_tty;
	int error;
	int s;

	if (SSCOM_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();
	SSCOM_LOCK(sc);	

	switch (cmd) {
	case TIOCSBRK:
		sscom_break(sc, 1);
		break;

	case TIOCCBRK:
		sscom_break(sc, 0);
		break;

	case TIOCSDTR:
		sscom_modem(sc, 1);
		break;

	case TIOCCDTR:
		sscom_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_sscom(sc, cmd, *(int *)data);
		break;

	case TIOCMGET:
		*(int *)data = sscom_to_tiocm(sc);
		break;

	default:
		error = EPASSTHROUGH;
		break;
	}

	SSCOM_UNLOCK(sc);
	splx(s);

	if (sscom_debug)
		sscomstatus(sc, "sscomioctl ");

	return error;
}
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);
}
示例#20
0
int
ucomopen(dev_t dev, int flag, int mode, struct lwp *l)
{
	int unit = UCOMUNIT(dev);
	usbd_status err;
	struct ucom_softc *sc = device_lookup_private(&ucom_cd, unit);
	struct ucom_buffer *ub;
	struct tty *tp;
	int s, i;
	int error;

	if (sc == NULL)
		return (ENXIO);

	if (sc->sc_dying)
		return (EIO);

	if (!device_is_active(sc->sc_dev))
		return (ENXIO);

	tp = sc->sc_tty;

	DPRINTF(("ucomopen: unit=%d, tp=%p\n", unit, tp));

	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.
	 */
	while (sc->sc_opening)
		tsleep(&sc->sc_opening, PRIBIO, "ucomop", 0);

	if (sc->sc_dying) {
		splx(s);
		return (EIO);
	}
	sc->sc_opening = 1;

	if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
		struct termios t;

		tp->t_dev = dev;

		if (sc->sc_methods->ucom_open != NULL) {
			error = sc->sc_methods->ucom_open(sc->sc_parent,
							  sc->sc_portno);
			if (error) {
				ucom_cleanup(sc);
				sc->sc_opening = 0;
				wakeup(&sc->sc_opening);
				splx(s);
				return (error);
			}
		}

		ucom_status_change(sc);

		/*
		 * 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;
		ttychars(tp);
		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.  Ditto RTS.
		 */
		ucom_dtr(sc, 1);
		ucom_rts(sc, 1);		

		DPRINTF(("ucomopen: open pipes in=%d out=%d\n",
			 sc->sc_bulkin_no, sc->sc_bulkout_no));

		/* Open the bulk pipes */
		err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkin_no,
				     USBD_EXCLUSIVE_USE, &sc->sc_bulkin_pipe);
		if (err) {
			DPRINTF(("%s: open bulk in error (addr %d), err=%s\n",
				 USBDEVNAME(sc->sc_dev), 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 out error (addr %d), err=%s\n",
				 USBDEVNAME(sc->sc_dev), sc->sc_bulkout_no,
				 usbd_errstr(err)));
			error = EIO;
			goto fail_1;
		}

		sc->sc_rx_unblock = 0;
		sc->sc_rx_stopped = 0;
		sc->sc_tx_stopped = 0;

		memset(sc->sc_ibuff, 0, sizeof(sc->sc_ibuff));
		memset(sc->sc_obuff, 0, sizeof(sc->sc_obuff));

		SIMPLEQ_INIT(&sc->sc_ibuff_empty);
		SIMPLEQ_INIT(&sc->sc_ibuff_full);
		SIMPLEQ_INIT(&sc->sc_obuff_free);
		SIMPLEQ_INIT(&sc->sc_obuff_full);

		/* Allocate input buffers */
		for (ub = &sc->sc_ibuff[0]; ub != &sc->sc_ibuff[UCOM_IN_BUFFS];
		    ub++) {
			ub->ub_xfer = usbd_alloc_xfer(sc->sc_udev);
			if (ub->ub_xfer == NULL) {
				error = ENOMEM;
				goto fail_2;
			}
			ub->ub_data = usbd_alloc_buffer(ub->ub_xfer,
			    sc->sc_ibufsizepad);
			if (ub->ub_data == NULL) {
				error = ENOMEM;
				goto fail_2;
			}

			if (ucomsubmitread(sc, ub) != USBD_NORMAL_COMPLETION) {
				error = EIO;
				goto fail_2;
			}
		}

		for (ub = &sc->sc_obuff[0]; ub != &sc->sc_obuff[UCOM_OUT_BUFFS];
		    ub++) {
			ub->ub_xfer = usbd_alloc_xfer(sc->sc_udev);
			if (ub->ub_xfer == NULL) {
				error = ENOMEM;
				goto fail_2;
			}
			ub->ub_data = usbd_alloc_buffer(ub->ub_xfer,
			    sc->sc_obufsize);
			if (ub->ub_data == NULL) {
				error = ENOMEM;
				goto fail_2;
			}

			SIMPLEQ_INSERT_TAIL(&sc->sc_obuff_free, ub, ub_link);
		}

	}
	sc->sc_opening = 0;
	wakeup(&sc->sc_opening);
	splx(s);

	error = ttyopen(tp, UCOMDIALOUT(dev), ISSET(flag, O_NONBLOCK));
	if (error)
		goto bad;

	error = (*tp->t_linesw->l_open)(dev, tp);
	if (error)
		goto bad;

	return (0);

fail_2:
	usbd_abort_pipe(sc->sc_bulkin_pipe);
	for (i = 0; i < UCOM_IN_BUFFS; i++) {
		if (sc->sc_ibuff[i].ub_xfer != NULL) {
			usbd_free_xfer(sc->sc_ibuff[i].ub_xfer);
			sc->sc_ibuff[i].ub_xfer = NULL;
			sc->sc_ibuff[i].ub_data = NULL;
		}
	}
	usbd_abort_pipe(sc->sc_bulkout_pipe);
	for (i = 0; i < UCOM_OUT_BUFFS; i++) {
		if (sc->sc_obuff[i].ub_xfer != NULL) {
			usbd_free_xfer(sc->sc_obuff[i].ub_xfer);
			sc->sc_obuff[i].ub_xfer = NULL;
			sc->sc_obuff[i].ub_data = NULL;
		}
	}

	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:
	sc->sc_opening = 0;
	wakeup(&sc->sc_opening);
	splx(s);
	return (error);

bad:
	s = spltty();
	CLR(tp->t_state, TS_BUSY);
	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.
		 */
		ucom_cleanup(sc);
	}
	splx(s);

	return (error);
}
示例#21
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));
}
示例#22
0
文件: gtmpsc.c 项目: ryo/netbsd-src
int
gtmpscopen(dev_t dev, int flag, int mode, struct lwp *l)
{
	struct gtmpsc_softc *sc;
	int unit = GTMPSCUNIT(dev);
	struct tty *tp;
	int s;
	int error;

	sc = device_lookup_private(&gtmpsc_cd, unit);
	if (!sc)
		return ENXIO;
#ifdef KGDB
	/*
	 * If this is the kgdb port, no other use is permitted.
	 */
	if (sc->sc_flags & GTMPSC_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();

	if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
		struct termios t;

		tp->t_dev = dev;

		mutex_spin_enter(&sc->sc_lock);

		/* Turn on interrupts. */
		sdma_imask |= SDMA_INTR_RXBUF(sc->sc_unit);
		gt_sdma_imask(device_parent(sc->sc_dev), sdma_imask);

		/* Clear PPS capture state on first open. */
		mutex_spin_enter(&timecounter_lock);
		memset(&sc->sc_pps_state, 0, sizeof(sc->sc_pps_state));
		sc->sc_pps_state.ppscap = PPS_CAPTUREASSERT | PPS_CAPTURECLEAR;
		pps_init(&sc->sc_pps_state);
		mutex_spin_exit(&timecounter_lock);

		mutex_spin_exit(&sc->sc_lock);

		if (sc->sc_flags & GTMPSC_CONSOLE) {
			t.c_ospeed = sc->sc_baudrate;
			t.c_cflag = sc->sc_cflag;
		} else {
			t.c_ospeed = TTYDEF_SPEED;
			t.c_cflag = TTYDEF_CFLAG;
		}
		t.c_ispeed = t.c_ospeed;

		/* Make sure gtmpscparam() will do something. */
		tp->t_ospeed = 0;
		(void) gtmpscparam(tp, &t);
		tp->t_iflag = TTYDEF_IFLAG;
		tp->t_oflag = TTYDEF_OFLAG;
		tp->t_lflag = TTYDEF_LFLAG;
		ttychars(tp);
		ttsetwater(tp);

		mutex_spin_enter(&sc->sc_lock);

		/* Clear the input/output ring */
		sc->sc_rcvcnt = 0;
		sc->sc_roffset = 0;
		sc->sc_rcvrx = 0;
		sc->sc_rcvdrx = 0;
		sc->sc_nexttx = 0;
		sc->sc_lasttx = 0;

		/*
		 * enable SDMA receive
		 */
		GT_SDMA_WRITE(sc, SDMA_SDCM, SDMA_SDCM_ERD);

		mutex_spin_exit(&sc->sc_lock);
	}
	splx(s);
	error = ttyopen(tp, GTMPSCDIALOUT(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.
		 */
		gtmpscshutdown(sc);
	}

	return error;
}
示例#23
0
文件: sab.c 项目: lacombar/netbsd-alc
int
sabioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l)
{
	struct sabtty_softc *sc = device_lookup_private(&sabtty_cd, SABUNIT(dev));
	struct tty *tp = sc->sc_tty;
	int error;

	error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flags, l);
	if (error >= 0)
		return (error);

	error = ttioctl(tp, cmd, data, flags, l);
	if (error >= 0)
		return (error);

	error = 0;

	switch (cmd) {
	case TIOCSBRK:
		SAB_WRITE(sc, SAB_DAFO,
		    SAB_READ(sc, SAB_DAFO) | SAB_DAFO_XBRK);
		break;
	case TIOCCBRK:
		SAB_WRITE(sc, SAB_DAFO,
		    SAB_READ(sc, SAB_DAFO) & ~SAB_DAFO_XBRK);
		break;
	case TIOCSDTR:
		sabtty_mdmctrl(sc, TIOCM_DTR, DMBIS);
		break;
	case TIOCCDTR:
		sabtty_mdmctrl(sc, TIOCM_DTR, DMBIC);
		break;
	case TIOCMBIS:
		sabtty_mdmctrl(sc, *((int *)data), DMBIS);
		break;
	case TIOCMBIC:
		sabtty_mdmctrl(sc, *((int *)data), DMBIC);
		break;
	case TIOCMGET:
		*((int *)data) = sabtty_mdmctrl(sc, 0, DMGET);
		break;
	case TIOCMSET:
		sabtty_mdmctrl(sc, *((int *)data), DMSET);
		break;
	case TIOCGFLAGS:
		*((int *)data) = sc->sc_openflags;
		break;
	case TIOCSFLAGS:
		if (kauth_authorize_device_tty(l->l_cred,
		    KAUTH_DEVICE_TTY_PRIVSET, tp))
			error = EPERM;
		else
			sc->sc_openflags = *((int *)data) &
			    (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL |
			     TIOCFLAG_CRTSCTS | TIOCFLAG_MDMBUF);
		break;
	default:
		error = ENOTTY;
	}

	return (error);
}
示例#24
0
文件: sab.c 项目: lacombar/netbsd-alc
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);
}
示例#25
0
int
mfcsioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
{
	register struct tty *tp;
	register int error;
	struct mfcs_softc *sc = device_lookup_private(&mfcs_cd, dev & 31);

	tp = sc->sc_tty;
	if (!tp)
		return ENXIO;

	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:
		sc->sc_duart->ch_cr = 0x60;		/* start break */
		break;

	case TIOCCBRK:
		sc->sc_duart->ch_cr = 0x70;		/* stop break */
		break;

	case TIOCSDTR:
		(void) mfcsmctl(dev, TIOCM_DTR | TIOCM_RTS, DMBIS);
		break;

	case TIOCCDTR:
		(void) mfcsmctl(dev, TIOCM_DTR | TIOCM_RTS, DMBIC);
		break;

	case TIOCMSET:
		(void) mfcsmctl(dev, *(int *) data, DMSET);
		break;

	case TIOCMBIS:
		(void) mfcsmctl(dev, *(int *) data, DMBIS);
		break;

	case TIOCMBIC:
		(void) mfcsmctl(dev, *(int *) data, DMBIC);
		break;

	case TIOCMGET:
		*(int *)data = mfcsmctl(dev, 0, DMGET);
		break;
	case TIOCGFLAGS:
		*(int *)data = SWFLAGS(dev);
		break;
	case TIOCSFLAGS:
		error = kauth_authorize_device_tty(l->l_cred,
		    KAUTH_DEVICE_TTY_PRIVSET, tp);
		if (error != 0)
			return(EPERM);

		sc->swflags = *(int *)data;
                sc->swflags &= /* only allow valid flags */
                  (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL | TIOCFLAG_CRTSCTS);
		/* XXXX need to change duart parameters? */
		break;
	default:
		return(EPASSTHROUGH);
	}

	return(0);
}
示例#26
0
/*
 * Open a zs serial port.
 */
int
zsopen(dev_t dev, int flags, int mode, struct lwp *l)
{
	struct tty *tp;
	struct zs_chanstate *cs;
	struct zs_softc *sc;
	int unit = ZS_UNIT(dev);
	int zs = unit >> 1;
	int error, s;

	sc = device_lookup_private(&zs_cd, zs);
	if (sc == NULL)
		return ENXIO;
	cs = sc->sc_cs[unit & 1];

	/*
	 * When port A (ser02) is selected on the TT, make sure
	 * the port is enabled.
	 */
	if ((machineid & ATARI_TT) && !(unit & 1))
		ym2149_ser2(1);

	if (cs->cs_rbuf == NULL) {
		cs->cs_rbuf = malloc(ZLRB_RING_SIZE * sizeof(int), M_DEVBUF,
		    M_WAITOK);
	}

	tp = cs->cs_ttyp;
	if (tp == NULL) {
		cs->cs_ttyp = tp = tty_alloc();
		tty_attach(tp);
		tp->t_dev   = dev;
		tp->t_oproc = zsstart;
		tp->t_param = zsparam;
	}

	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 ((tp->t_state & TS_ISOPEN) == 0 && tp->t_wopen == 0) {
		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;
		}
		ttychars(tp);
		ttsetwater(tp);

		(void)zsparam(tp, &tp->t_termios);

		/*
		 * 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.
		 */
		zs_modem(cs, ZSWR5_RTS|ZSWR5_DTR, DMSET);
		/* May never get a status intr. if DCD already on. -gwr */
		if (((cs->cs_rr0 = cs->cs_zc->zc_csr) & ZSRR0_DCD) != 0)
			tp->t_state |= TS_CARR_ON;
		if (cs->cs_softcar)
			tp->t_state |= TS_CARR_ON;
	}

	splx(s);

	error = ttyopen(tp, ZS_DIALOUT(dev), (flags & O_NONBLOCK));
	if (error)
		goto bad;
	
	error = tp->t_linesw->l_open(dev, tp);
	if (error)
		goto bad;
	return 0;

bad:
	if ((tp->t_state & TS_ISOPEN) == 0 && tp->t_wopen == 0) {
		/*
		 * We failed to open the device, and nobody else had it opened.
		 * Clean up the state as appropriate.
		 */
		zs_shutdown(cs);
	}
	return error;
}
示例#27
0
int
stty_ioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l)
{
	struct stty_softc *stc = device_lookup_private(&stty_cd,
						       SPIF_CARD(dev));
	struct stty_port *sp = &stc->sc_port[SPIF_PORT(dev)];
	struct spif_softc *sc = sp->sp_sc;
	struct tty *tp = sp->sp_tty;
	int error;

	error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flags, l);
	if (error >= 0)
		return (error);

	error = ttioctl(tp, cmd, data, flags, l);
	if (error >= 0)
		return (error);

	error = 0;

	switch (cmd) {
	case TIOCSBRK:
		SET(sp->sp_flags, STTYF_SET_BREAK);
		STC_WRITE(sc, STC_CAR, sp->sp_channel);
		STC_WRITE(sc, STC_SRER,
		    STC_READ(sc, STC_SRER) | CD180_SRER_TXD);
		break;
	case TIOCCBRK:
		SET(sp->sp_flags, STTYF_CLR_BREAK);
		STC_WRITE(sc, STC_CAR, sp->sp_channel);
		STC_WRITE(sc, STC_SRER,
		    STC_READ(sc, STC_SRER) | CD180_SRER_TXD);
		break;
	case TIOCSDTR:
		stty_modem_control(sp, TIOCM_DTR, DMBIS);
		break;
	case TIOCCDTR:
		stty_modem_control(sp, TIOCM_DTR, DMBIC);
		break;
	case TIOCMBIS:
		stty_modem_control(sp, *((int *)data), DMBIS);
		break;
	case TIOCMBIC:
		stty_modem_control(sp, *((int *)data), DMBIC);
		break;
	case TIOCMGET:
		*((int *)data) = stty_modem_control(sp, 0, DMGET);
		break;
	case TIOCMSET:
		stty_modem_control(sp, *((int *)data), DMSET);
		break;
	case TIOCGFLAGS:
		*((int *)data) = sp->sp_openflags;
		break;
	case TIOCSFLAGS:
		if (kauth_authorize_device_tty(l->l_cred,
		    KAUTH_DEVICE_TTY_PRIVSET, tp))
			error = EPERM;
		else
			sp->sp_openflags = *((int *)data) &
			    (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL |
			     TIOCFLAG_CRTSCTS | TIOCFLAG_MDMBUF);
		break;
	default:
		error = ENOTTY;
	}

	return (error);
}
示例#28
0
文件: gtmpsc.c 项目: ryo/netbsd-src
int
gtmpscioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
{
	struct gtmpsc_softc *sc =
	    device_lookup_private(&gtmpsc_cd, GTMPSCUNIT(dev));
	struct tty *tp = sc->sc_tty;
	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;

	error = 0;
	switch (cmd) {
	case TIOCSFLAGS:
		error = kauth_authorize_device_tty(l->l_cred,
		    KAUTH_DEVICE_TTY_PRIVSET, tp);
		if (error)
			return error;
		break;
	default:
		/* nothing */
		break;
	}

	mutex_spin_enter(&sc->sc_lock);

	switch (cmd) {
	case PPS_IOC_CREATE:
	case PPS_IOC_DESTROY:
	case PPS_IOC_GETPARAMS:
	case PPS_IOC_SETPARAMS:
	case PPS_IOC_GETCAP:
	case PPS_IOC_FETCH:
#ifdef PPS_SYNC
	case PPS_IOC_KCBIND:
#endif
		mutex_spin_enter(&timecounter_lock);
		error = pps_ioctl(cmd, data, &sc->sc_pps_state);
		mutex_spin_exit(&timecounter_lock);
		break;

	case TIOCDCDTIMESTAMP:	/* XXX old, overloaded  API used by xntpd v3 */
		mutex_spin_enter(&timecounter_lock);
#ifndef PPS_TRAILING_EDGE
		TIMESPEC_TO_TIMEVAL((struct timeval *)data,
		    &sc->sc_pps_state.ppsinfo.assert_timestamp);
#else
		TIMESPEC_TO_TIMEVAL((struct timeval *)data,
		    &sc->sc_pps_state.ppsinfo.clear_timestamp);
#endif
		mutex_spin_exit(&timecounter_lock);
		break;

	default:
		error = EPASSTHROUGH;
		break;
	}

	mutex_spin_exit(&sc->sc_lock);

	return error;
}
示例#29
0
static int
ucom_do_ioctl(struct ucom_softc *sc, u_long cmd, void *data,
	      int flag, struct lwp *l)
{
	struct tty *tp = sc->sc_tty;
	int error;
	int s;

	if (sc->sc_dying)
		return (EIO);

	DPRINTF(("ucomioctl: cmd=0x%08lx\n", cmd));

	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);

	if (sc->sc_methods->ucom_ioctl != NULL) {
		error = sc->sc_methods->ucom_ioctl(sc->sc_parent,
			    sc->sc_portno, cmd, data, flag, l->l_proc);
		if (error != EPASSTHROUGH)
			return (error);
	}

	error = 0;

	DPRINTF(("ucomioctl: our cmd=0x%08lx\n", cmd));
	s = spltty();

	switch (cmd) {
	case TIOCSBRK:
		ucom_break(sc, 1);
		break;

	case TIOCCBRK:
		ucom_break(sc, 0);
		break;

	case TIOCSDTR:
		ucom_dtr(sc, 1);
		break;

	case TIOCCDTR:
		ucom_dtr(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_ucom(sc, cmd, *(int *)data);
		break;

	case TIOCMGET:
		*(int *)data = ucom_to_tiocm(sc);
		break;

	default:
		error = EPASSTHROUGH;
		break;
	}

	splx(s);

	return (error);
}
示例#30
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);
}