コード例 #1
0
int
at91usart_close(dev_t dev, int flag, int mode, struct lwp *l)
{
	struct at91usart_softc *sc = device_lookup_private(&at91usart_cd, COMUNIT(dev));
	struct tty *tp = sc->sc_tty;

	/* XXX This is for cons.c. */
	if (!ISSET(tp->t_state, TS_ISOPEN))
		return (0);

	(*tp->t_linesw->l_close)(tp, flag);
	ttyclose(tp);

	if (COM_ISALIVE(sc) == 0)
		return (0);

	if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
		/*
		 * Although we got a last close, the device may still be in
		 * use; e.g. if this was the dialout node, and there are still
		 * processes waiting for carrier on the non-dialout node.
		 */
		at91usart_shutdown(sc);
	}

	return (0);
}
コード例 #2
0
ファイル: com.c プロジェクト: lacombar/netbsd-alc
int
comclose(dev_t dev, int flag, int mode, struct lwp *l)
{
	struct com_softc *sc = device_lookup_private(&xcom_cd, COMUNIT(dev));
	struct tty *tp = sc->sc_tty;
	int iobase = sc->sc_iobase;
	int s;

	/* XXX This is for cons.c. */
	if (!ISSET(tp->t_state, TS_ISOPEN))
		return 0;

	(*tp->t_linesw->l_close)(tp, flag);
	s = spltty();
	CLR(sc->sc_lcr, LCR_SBREAK);
	outb(pio(iobase , com_lcr), sc->sc_lcr);
	outb(pio(iobase , com_ier), 0);
	if (ISSET(tp->t_cflag, HUPCL) &&
	    !ISSET(sc->sc_swflags, COM_SW_SOFTCAR)) {
		/* XXX perhaps only clear DTR */
		outb(pio(iobase , com_mcr), 0);
	}
	CLR(tp->t_state, TS_BUSY | TS_FLUSH);
	if (--comsopen == 0)
		callout_stop(&com_poll_ch);
	splx(s);
	ttyclose(tp);
#ifdef notyet /* XXXX */
	if (unit != comconsole) {
		ttyfree(tp);
		sc->sc_tty = 0;
	}
#endif
	return 0;
}
コード例 #3
0
ファイル: com.c プロジェクト: lacombar/netbsd-alc
struct tty *
comtty(dev_t dev)
{
	struct com_softc *sc = device_lookup_private(&xcom_cd, COMUNIT(dev));
	struct tty *tp = sc->sc_tty;

	return (tp);
}
コード例 #4
0
ファイル: com.c プロジェクト: lacombar/netbsd-alc
int
compoll(dev_t dev, int events, struct lwp *l)
{
	struct com_softc *sc = device_lookup_private(&xcom_cd, COMUNIT(dev));
	struct tty *tp = sc->sc_tty;

	return ((*tp->t_linesw->l_poll)(tp, events, l));
}
コード例 #5
0
ファイル: com.c プロジェクト: lacombar/netbsd-alc
int
comwrite(dev_t dev, struct uio *uio, int flag)
{
	struct com_softc *sc = device_lookup_private(&xcom_cd, COMUNIT(dev));
	struct tty *tp = sc->sc_tty;

	return ((*tp->t_linesw->l_write)(tp, uio, flag));
}
コード例 #6
0
struct tty *
at91usart_tty(dev_t dev)
{
	struct at91usart_softc *sc = device_lookup_private(&at91usart_cd, COMUNIT(dev));
	struct tty *tp = sc->sc_tty;

	return (tp);
}
コード例 #7
0
ファイル: sa11x0_com.c プロジェクト: lacombar/netbsd-alc
struct tty *
sacomtty(dev_t dev)
{
    struct sacom_softc *sc =
        device_lookup_private(&sacom_cd, COMUNIT(dev));
    struct tty *tp = sc->sc_tty;

    return tp;
}
コード例 #8
0
int
at91usart_poll(dev_t dev, int events, struct lwp *l)
{
	struct at91usart_softc *sc = device_lookup_private(&at91usart_cd, COMUNIT(dev));
	struct tty *tp = sc->sc_tty;

	if (COM_ISALIVE(sc) == 0)
		return (EIO);
 
	return ((*tp->t_linesw->l_poll)(tp, events, l));
}
コード例 #9
0
int
at91usart_write(dev_t dev, struct uio *uio, int flag)
{
	struct at91usart_softc *sc = device_lookup_private(&at91usart_cd, COMUNIT(dev));
	struct tty *tp = sc->sc_tty;

	if (COM_ISALIVE(sc) == 0)
		return (EIO);
 
	return ((*tp->t_linesw->l_write)(tp, uio, flag));
}
コード例 #10
0
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);
}
コード例 #11
0
ファイル: sa11x0_com.c プロジェクト: lacombar/netbsd-alc
int
sacompoll(dev_t dev, int events, struct lwp *l)
{
    struct sacom_softc *sc =
        device_lookup_private(&sacom_cd, COMUNIT(dev));
    struct tty *tp = sc->sc_tty;

    if (COM_ISALIVE(sc) == 0)
        return EIO;

    return (*tp->t_linesw->l_poll)(tp, events, l);
}
コード例 #12
0
ファイル: sa11x0_com.c プロジェクト: lacombar/netbsd-alc
int
sacomwrite(dev_t dev, struct uio *uio, int flag)
{
    struct sacom_softc *sc =
        device_lookup_private(&sacom_cd, COMUNIT(dev));
    struct tty *tp = sc->sc_tty;

    if (COM_ISALIVE(sc) == 0)
        return EIO;

    return (*tp->t_linesw->l_write)(tp, uio, flag);
}
コード例 #13
0
ファイル: sa11x0_com.c プロジェクト: lacombar/netbsd-alc
void
sacomstart(struct tty *tp)
{
    struct sacom_softc *sc =
        device_lookup_private(&sacom_cd, COMUNIT(tp->t_dev));
    bus_space_tag_t iot = sc->sc_iot;
    bus_space_handle_t ioh = sc->sc_ioh;
    int s;

    if (COM_ISALIVE(sc) == 0)
        return;

    s = spltty();
    if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP))
        goto out;
    if (!ttypull(tp))
        goto out;

    /* Grab the first contiguous region of buffer space. */
    {
        u_char *tba;
        int tbc;

        tba = tp->t_outq.c_cf;
        tbc = ndqb(&tp->t_outq, 0);

        (void)splserial();
        COM_LOCK(sc);

        sc->sc_tba = tba;
        sc->sc_tbc = tbc;
    }

    SET(tp->t_state, TS_BUSY);
    sc->sc_tx_busy = 1;

    /* Enable transmit completion interrupts if necessary. */
    if (!ISSET(sc->sc_cr3, CR3_TIE)) {
        SET(sc->sc_cr3, CR3_TIE);
        bus_space_write_4(iot, ioh, SACOM_CR3, sc->sc_cr3);
    }

    /* Output the first chunk of the contiguous buffer. */
    sacom_filltx(sc);

    COM_UNLOCK(sc);
out:
    splx(s);
    return;
}
コード例 #14
0
/*
 * Stop output on a line.
 */
void
at91usart_stop(struct tty *tp, int flag)
{
	struct at91usart_softc *sc
		= device_lookup_private(&at91usart_cd, COMUNIT(tp->t_dev));
	int s;

	s = spltty();
	if (ISSET(tp->t_state, TS_BUSY)) {
		/* Stop transmitting at the next chunk. */
		sc->sc_tbc = 0;
		if (!ISSET(tp->t_state, TS_TTSTOP))
			SET(tp->t_state, TS_FLUSH);
	}
	splx(s);
}
コード例 #15
0
static void
at91usart_start(struct tty *tp)
{
	struct at91usart_softc *sc
		= device_lookup_private(&at91usart_cd, COMUNIT(tp->t_dev));
	int s;

	if (COM_ISALIVE(sc) == 0) {
		DPRINTFN(5, ("%s: %s / COM_ISALIVE == 0\n", device_xname(sc->sc_dev), __FUNCTION__));
		return;
	}

	s = spltty();
	if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP)) {
		DPRINTFN(5, ("%s: %s: TS_BUSY || TS_TIMEOUT || TS_TTSTOP\n", device_xname(sc->sc_dev), __FUNCTION__));
		goto out;
	}

	if (!ttypull(tp))
		goto out;

	/* Grab the first contiguous region of buffer space. */
	{
		u_char *tba;
		int tbc;

		tba = tp->t_outq.c_cf;
		tbc = ndqb(&tp->t_outq, 0);

		sc->sc_tba = tba;
		sc->sc_tbc = tbc;
	}

	SET(tp->t_state, TS_BUSY);

	/* Output the first chunk of the contiguous buffer. */
	at91usart_filltx(sc);
	at91usart_writereg(sc, US_IER, sc->sc_ier);
	DPRINTFN(5, ("%s: %s, ier=%08x (csr=%08x)\n", device_xname(sc->sc_dev), __FUNCTION__, sc->sc_ier, at91usart_readreg(sc, US_CSR)));

out:
	splx(s);

	return;
}
コード例 #16
0
static void
at91dbgu_start(struct tty *tp)
{
	struct at91dbgu_softc *sc
		= device_lookup_private(&at91dbgu_cd, COMUNIT(tp->t_dev));
	int s;

	if (COM_ISALIVE(sc) == 0)
		return;

	s = spltty();
	if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP))
		goto out;
	if (sc->sc_tx_stopped)
		goto out;
	if (!ttypull(tp))
		goto out;

	/* Grab the first contiguous region of buffer space. */
	{
		u_char *tba;
		int tbc;

		tba = tp->t_outq.c_cf;
		tbc = ndqb(&tp->t_outq, 0);

		(void)splserial();

		sc->sc_tba = tba;
		sc->sc_tbc = tbc;
	}

	SET(tp->t_state, TS_BUSY);
	sc->sc_tx_busy = 1;

	/* Output the first chunk of the contiguous buffer. */
	at91dbgu_filltx(sc);

	SET(sc->sc_ier, DBGU_INT_TXRDY);
	DBGUREG(DBGU_IER) = DBGU_INT_TXRDY;

out:
	splx(s);
	return;
}
コード例 #17
0
ファイル: sa11x0_com.c プロジェクト: lacombar/netbsd-alc
/*
 * Stop output on a line.
 */
void
sacomstop(struct tty *tp, int flag)
{
    struct sacom_softc *sc =
        device_lookup_private(&sacom_cd, COMUNIT(tp->t_dev));
    int s;

    s = splserial();
    COM_LOCK(sc);
    if (ISSET(tp->t_state, TS_BUSY)) {
        /* Stop transmitting at the next chunk. */
        sc->sc_tbc = 0;
        sc->sc_heldtbc = 0;
        if (!ISSET(tp->t_state, TS_TTSTOP))
            SET(tp->t_state, TS_FLUSH);
    }
    COM_UNLOCK(sc);
    splx(s);
}
コード例 #18
0
ファイル: sa11x0_com.c プロジェクト: lacombar/netbsd-alc
int
sacomhwiflow(struct tty *tp, int block)
{
#if 0
    struct sacom_softc *sc =
        device_lookup_private(&sacom_cd, COMUNIT(tp->t_dev));
    int s;

    if (COM_ISALIVE(sc) == 0)
        return 0;

    if (sc->sc_mcr_rts == 0)
        return 0;

    s = splserial();
    COM_LOCK(sc);

    if (block) {
        if (!ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED)) {
            SET(sc->sc_rx_flags, RX_TTY_BLOCKED);
            sacom_hwiflow(sc);
        }
    } else {
        if (ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED)) {
            CLR(sc->sc_rx_flags, RX_TTY_OVERFLOWED);
            sacom_schedrx(sc);
        }
        if (ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED)) {
            CLR(sc->sc_rx_flags, RX_TTY_BLOCKED);
            sacom_hwiflow(sc);
        }
    }

    COM_UNLOCK(sc);
    splx(s);
#endif
    return 1;
}
コード例 #19
0
ファイル: sa11x0_com.c プロジェクト: lacombar/netbsd-alc
int
sacomopen(dev_t dev, int flag, int mode, struct lwp *l)
{
    struct sacom_softc *sc;
    struct tty *tp;
    int s, s2;
    int error;

    sc = device_lookup_private(&sacom_cd, COMUNIT(dev));
    if (sc == NULL || !ISSET(sc->sc_hwflags, COM_HW_DEV_OK) ||
            sc->sc_rbuf == NULL)
        return ENXIO;

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

    tp = sc->sc_tty;

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

    s = spltty();

    /*
     * Do the following iff this is a first open.
     */
    if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
        struct termios t;

        tp->t_dev = dev;

        s2 = splserial();
        COM_LOCK(sc);

        if (sc->enable) {
            if ((*sc->enable)(sc)) {
                COM_UNLOCK(sc);
                splx(s2);
                splx(s);
                printf("%s: device enable failed\n",
                       sc->sc_dev.dv_xname);
                return EIO;
            }
            sc->enabled = 1;
            sacom_config(sc);
        }

        /* Turn on interrupts. */
        sc->sc_cr3 = CR3_RXE | CR3_TXE | CR3_RIE | CR3_TIE;
        bus_space_write_4(sc->sc_iot, sc->sc_ioh, SACOM_CR3,
                          sc->sc_cr3);


        COM_UNLOCK(sc);
        splx(s2);

        /*
         * Initialize the termios status to the defaults.  Add in the
         * sticky bits from TIOCSFLAGS.
         */
        t.c_ispeed = 0;
        if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
            t.c_ospeed = sacomconsrate;
            t.c_cflag = sacomconscflag;
        } else {
            t.c_ospeed = TTYDEF_SPEED;
            t.c_cflag = TTYDEF_CFLAG;
        }
        if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL))
            SET(t.c_cflag, CLOCAL);
        if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS))
            SET(t.c_cflag, CRTSCTS);
        if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF))
            SET(t.c_cflag, MDMBUF);
        /* Make sure sacomparam() will do something. */
        tp->t_ospeed = 0;
        (void) sacomparam(tp, &t);
        tp->t_iflag = TTYDEF_IFLAG;
        tp->t_oflag = TTYDEF_OFLAG;
        tp->t_lflag = TTYDEF_LFLAG;
        ttychars(tp);
        ttsetwater(tp);

        s2 = splserial();
        COM_LOCK(sc);

        /*
         * Turn on DTR.  We must always do this, even if carrier is not
         * present, because otherwise we'd have to use TIOCSDTR
         * immediately after setting CLOCAL, which applications do not
         * expect.  We always assert DTR while the device is open
         * unless explicitly requested to deassert it.
         */
        sacom_modem(sc, 1);

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

#ifdef COM_DEBUG
        if (sacom_debug)
            comstatus(sc, "sacomopen  ");
#endif

        COM_UNLOCK(sc);
        splx(s2);
    }

    splx(s);

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

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

    return 0;

bad:
    if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
        /*
         * We failed to open the device, and nobody else had it opened.
         * Clean up the state as appropriate.
         */
        sacom_shutdown(sc);
    }

    return error;
}
コード例 #20
0
ファイル: com.c プロジェクト: lacombar/netbsd-alc
static int
comparam(struct tty *tp, struct termios *t)
{
	struct com_softc *sc = device_lookup_private(&xcom_cd, COMUNIT(tp->t_dev));
	int iobase = sc->sc_iobase;
	int ospeed = comspeed(t->c_ospeed);
	u_char lcr;
	tcflag_t oldcflag;
	int s;

	/* check requested parameters */
	if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
		return EINVAL;

	lcr = ISSET(sc->sc_lcr, LCR_SBREAK);

	switch (ISSET(t->c_cflag, CSIZE)) {
	case CS5:
		SET(lcr, LCR_5BITS);
		break;
	case CS6:
		SET(lcr, LCR_6BITS);
		break;
	case CS7:
		SET(lcr, LCR_7BITS);
		break;
	case CS8:
		SET(lcr, LCR_8BITS);
		break;
	}
	if (ISSET(t->c_cflag, PARENB)) {
		SET(lcr, LCR_PENAB);
		if (!ISSET(t->c_cflag, PARODD))
			SET(lcr, LCR_PEVEN);
	}
	if (ISSET(t->c_cflag, CSTOPB))
		SET(lcr, LCR_STOPB);

	sc->sc_lcr = lcr;

	s = spltty();

	if (ospeed == 0) {
		CLR(sc->sc_mcr, MCR_DTR);
		outb(pio(iobase , com_mcr), sc->sc_mcr);
	}

	/*
	 * Set the FIFO threshold based on the receive speed, if we are
	 * changing it.
	 */
	if (tp->t_ispeed != t->c_ispeed) {
		if (ISSET(sc->sc_hwflags, COM_HW_FIFO))
			outb(pio(iobase , com_fifo),
			    FIFO_ENABLE |
			    (t->c_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8));
	}

	if (ospeed != 0) {
		outb(pio(iobase , com_lcr), lcr | LCR_DLAB);
		outb(pio(iobase , com_dlbl), ospeed);
		outb(pio(iobase , com_dlbh), ospeed >> 8);
		outb(pio(iobase , com_lcr), lcr);
		SET(sc->sc_mcr, MCR_DTR);
		outb(pio(iobase , com_mcr), sc->sc_mcr);
	} else
コード例 #21
0
ファイル: com.c プロジェクト: lacombar/netbsd-alc
int
comioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
{
	struct com_softc *sc = device_lookup_private(&xcom_cd, COMUNIT(dev));
	struct tty *tp = sc->sc_tty;
	int iobase = sc->sc_iobase;
	int error;

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

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

	switch (cmd) {
	case TIOCSBRK:
		SET(sc->sc_lcr, LCR_SBREAK);
		outb(pio(iobase , com_lcr), sc->sc_lcr);
		break;
	case TIOCCBRK:
		CLR(sc->sc_lcr, LCR_SBREAK);
		outb(pio(iobase , com_lcr), sc->sc_lcr);
		break;
	case TIOCSDTR:
		SET(sc->sc_mcr, sc->sc_dtr);
		outb(pio(iobase , com_mcr), sc->sc_mcr);
		break;
	case TIOCCDTR:
		CLR(sc->sc_mcr, sc->sc_dtr);
		outb(pio(iobase , com_mcr), sc->sc_mcr);
		break;
	case TIOCMSET:
		CLR(sc->sc_mcr, MCR_DTR | MCR_RTS);
	case TIOCMBIS:
		SET(sc->sc_mcr, tiocm_xxx2mcr(*(int *)data));
		outb(pio(iobase , com_mcr), sc->sc_mcr);
		break;
	case TIOCMBIC:
		CLR(sc->sc_mcr, tiocm_xxx2mcr(*(int *)data));
		outb(pio(iobase , com_mcr), sc->sc_mcr);
		break;
	case TIOCMGET: {
		u_char m;
		int bits = 0;

		m = sc->sc_mcr;
		if (ISSET(m, MCR_DTR))
			SET(bits, TIOCM_DTR);
		if (ISSET(m, MCR_RTS))
			SET(bits, TIOCM_RTS);
		m = sc->sc_msr;
		if (ISSET(m, MSR_DCD))
			SET(bits, TIOCM_CD);
		if (ISSET(m, MSR_CTS))
			SET(bits, TIOCM_CTS);
		if (ISSET(m, MSR_DSR))
			SET(bits, TIOCM_DSR);
		if (ISSET(m, MSR_RI | MSR_TERI))
			SET(bits, TIOCM_RI);
		if (inb(pio(iobase , com_ier)))
			SET(bits, TIOCM_LE);
		*(int *)data = bits;
		break;
	}
	case TIOCGFLAGS: {
		int driverbits, userbits = 0;

		driverbits = sc->sc_swflags;
		if (ISSET(driverbits, COM_SW_SOFTCAR))
			SET(userbits, TIOCFLAG_SOFTCAR);
		if (ISSET(driverbits, COM_SW_CLOCAL))
			SET(userbits, TIOCFLAG_CLOCAL);
		if (ISSET(driverbits, COM_SW_CRTSCTS))
			SET(userbits, TIOCFLAG_CRTSCTS);
		if (ISSET(driverbits, COM_SW_MDMBUF))
			SET(userbits, TIOCFLAG_MDMBUF);

		*(int *)data = userbits;
		break;
	}
	case TIOCSFLAGS: {
		int userbits, driverbits = 0;

		error = kauth_authorize_device_tty(l->l_cred,
		    KAUTH_DEVICE_TTY_PRIVSET, tp);
		if (error != 0)
			return(EPERM);

		userbits = *(int *)data;
		if (ISSET(userbits, TIOCFLAG_SOFTCAR) ||
		    ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
			SET(driverbits, COM_SW_SOFTCAR);
		if (ISSET(userbits, TIOCFLAG_CLOCAL))
			SET(driverbits, COM_SW_CLOCAL);
		if (ISSET(userbits, TIOCFLAG_CRTSCTS))
			SET(driverbits, COM_SW_CRTSCTS);
		if (ISSET(userbits, TIOCFLAG_MDMBUF))
			SET(driverbits, COM_SW_MDMBUF);

		sc->sc_swflags = driverbits;
		break;
	}
	default:
		return EPASSTHROUGH;
	}

	return 0;
}
コード例 #22
0
int
at91usart_open(dev_t dev, int flag, int mode, struct lwp *l)
{
	struct at91usart_softc *sc;
	struct tty *tp;
	int s;
	int error;

	sc = device_lookup_private(&at91usart_cd, COMUNIT(dev));
	if (sc == NULL || !ISSET(sc->sc_hwflags, COM_HW_DEV_OK))
		return (ENXIO);

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

#ifdef KGDB
	/*
	 * If this is the kgdb port, no other use is permitted.
	 */
	if (ISSET(sc->sc_hwflags, COM_HW_KGDB))
		return (EBUSY);
#endif

	tp = sc->sc_tty;

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

	s = spltty();

	/*
	 * Do the following iff this is a first open.
	 */
	if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
		struct termios t;

		tp->t_dev = dev;

		if (sc->enable) {
			if ((*sc->enable)(sc)) {
				splx(s);
				printf("%s: device enable failed\n",
				       device_xname(sc->sc_dev));
				return (EIO);
			}
			sc->enabled = 1;
#if 0
/* XXXXXXXXXXXXXXX */
			com_config(sc);
#endif
		}

		/* reset fifos: */
		AT91PDC_RESET_FIFO(sc->sc_iot, sc->sc_ioh, sc->sc_dmat, US_PDC, &sc->sc_rx_fifo, 0);
		AT91PDC_RESET_FIFO(sc->sc_iot, sc->sc_ioh, sc->sc_dmat, US_PDC, &sc->sc_tx_fifo, 1);

		/* reset receive */
		at91usart_writereg(sc, US_CR, US_CR_RSTSTA | US_CR_STTTO);

		/* Turn on interrupts. */
		sc->sc_ier = US_CSR_ENDRX|US_CSR_RXBUFF|US_CSR_TIMEOUT|US_CSR_RXBRK;
		at91usart_writereg(sc, US_IER, sc->sc_ier);

		/* enable DMA: */
		at91usart_writereg(sc, US_PDC + PDC_PTCR, PDC_PTCR_RXTEN);

		/*
		 * Initialize the termios status to the defaults.  Add in the
		 * sticky bits from TIOCSFLAGS.
		 */
		t.c_ispeed = 0;
/*		if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
			t.c_ospeed = usart_cn_sc.sc_ospeed;
			t.c_cflag = usart_cn_sc.sc_cflag;
		} else*/ {
			t.c_ospeed = TTYDEF_SPEED;
			t.c_cflag = TTYDEF_CFLAG;
		}
		if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL))
			SET(t.c_cflag, CLOCAL);
		if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS))
			SET(t.c_cflag, CRTSCTS);
		if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF))
			SET(t.c_cflag, MDMBUF);

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

		/* and unblock. */
		CLR(sc->sc_rx_flags, RX_ANY_BLOCK);

#ifdef COM_DEBUG
		if (at91usart_debug)
			comstatus(sc, "at91usart_open  ");
#endif

	}
	
	splx(s);

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

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

	return (0);

bad:
	if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
		/*
		 * We failed to open the device, and nobody else had it opened.
		 * Clean up the state as appropriate.
		 */
		at91usart_shutdown(sc);
	}

	return (error);
}
コード例 #23
0
static int
at91usart_param(struct tty *tp, struct termios *t)
{
	struct at91usart_softc *sc
		= device_lookup_private(&at91usart_cd, COMUNIT(tp->t_dev));
	int s;

	if (COM_ISALIVE(sc) == 0)
		return (EIO);

	if (t->c_ispeed && t->c_ispeed != t->c_ospeed)
		return (EINVAL);

	/*
	 * For the console, always force CLOCAL and !HUPCL, so that the port
	 * is always active.
	 */
	if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR) ||
	    ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
		SET(t->c_cflag, CLOCAL);
		CLR(t->c_cflag, HUPCL);
	}

	/*
	 * If there were no changes, don't do anything.  This avoids dropping
	 * input and improves performance when all we did was frob things like
	 * VMIN and VTIME.
	 */
	if (tp->t_ospeed == t->c_ospeed &&
	    tp->t_cflag == t->c_cflag)
		return (0);

	s = spltty();

	sc->sc_brgr = (AT91_MSTCLK / 16 + t->c_ospeed / 2) / t->c_ospeed;
	
	/* And copy to tty. */
	tp->t_ispeed = 0;
	tp->t_ospeed = t->c_ospeed;
	tp->t_cflag = t->c_cflag;
	at91usart_set(sc);

	splx(s);

	/*
	 * Update the tty layer's idea of the carrier bit.
	 * We tell tty the carrier is always on.
	 */
	(void) (*tp->t_linesw->l_modem)(tp, 1);

#ifdef COM_DEBUG
	if (com_debug)
		comstatus(sc, "comparam ");
#endif

	/* tell the upper layer about hwflow.. */
	if (sc->hwflow)
		(*sc->hwflow)(sc, t->c_cflag);

	return (0);
}
コード例 #24
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);
}
コード例 #25
0
ファイル: sa11x0_com.c プロジェクト: lacombar/netbsd-alc
int
sacomparam(struct tty *tp, struct termios *t)
{
    struct sacom_softc *sc =
        device_lookup_private(&sacom_cd, COMUNIT(tp->t_dev));
    int ospeed = SACOMSPEED(t->c_ospeed);
    u_int cr0;
    int s;

    if (COM_ISALIVE(sc) == 0)
        return EIO;

    /* Check requested parameters. */
    if (ospeed < 0)
        return EINVAL;
    if (t->c_ispeed && t->c_ispeed != t->c_ospeed)
        return EINVAL;

    /*
     * For the console, always force CLOCAL and !HUPCL, so that the port
     * is always active.
     */
    if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR) ||
            ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
        SET(t->c_cflag, CLOCAL);
        CLR(t->c_cflag, HUPCL);
    }

    /*
     * If there were no changes, don't do anything.  This avoids dropping
     * input and improves performance when all we did was frob things like
     * VMIN and VTIME.
     */
    if (tp->t_ospeed == t->c_ospeed &&
            tp->t_cflag == t->c_cflag)
        return 0;

    cr0 = cflag2cr0(t->c_cflag);

    s = splserial();
    COM_LOCK(sc);

    sc->sc_cr0 = cr0;

    sc->sc_speed = ospeed;

    /* And copy to tty. */
    tp->t_ispeed = 0;
    tp->t_ospeed = t->c_ospeed;
    tp->t_cflag = t->c_cflag;

    if (!sc->sc_heldchange) {
        if (sc->sc_tx_busy) {
            sc->sc_heldtbc = sc->sc_tbc;
            sc->sc_tbc = 0;
            sc->sc_heldchange = 1;
        } else
            sacom_loadchannelregs(sc);
    }

    if (!ISSET(t->c_cflag, CHWFLOW)) {
        /* Disable the high water mark. */
        if (ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED)) {
            CLR(sc->sc_rx_flags, RX_TTY_OVERFLOWED);
            sacom_schedrx(sc);
        }
        if (ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED|RX_IBUF_BLOCKED)) {
            CLR(sc->sc_rx_flags, RX_TTY_BLOCKED|RX_IBUF_BLOCKED);
            sacom_hwiflow(sc);
        }
    }

    COM_UNLOCK(sc);
    splx(s);

    (void) (*tp->t_linesw->l_modem)(tp, 1);

#ifdef COM_DEBUG
    if (sacom_debug)
        comstatus(sc, "comparam ");
#endif

    return 0;
}
コード例 #26
0
ファイル: sa11x0_com.c プロジェクト: lacombar/netbsd-alc
int
sacomioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
{
    struct sacom_softc *sc =
        device_lookup_private(&sacom_cd, COMUNIT(dev));
    struct tty *tp = sc->sc_tty;
    int error;
    int s;

    if (COM_ISALIVE(sc) == 0)
        return EIO;

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

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

    error = 0;

    s = splserial();
    COM_LOCK(sc);

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

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

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

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

    case TIOCGFLAGS:
        *(int *)data = sc->sc_swflags;
        break;

    case TIOCSFLAGS:
        error = kauth_authorize_device_tty(l->l_cred,
                                           KAUTH_DEVICE_TTY_PRIVSET, tp);
        if (error)
            break;
        sc->sc_swflags = *(int *)data;
        break;

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

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

    default:
        error = EPASSTHROUGH;
        break;
    }

    COM_UNLOCK(sc);
    splx(s);

#ifdef COM_DEBUG
    if (sacom_debug)
        comstatus(sc, "comioctl ");
#endif

    return error;
}
コード例 #27
0
ファイル: com.c プロジェクト: lacombar/netbsd-alc
int
comopen(dev_t dev, int flag, int mode, struct lwp *l)
{
	struct com_softc *sc;
	int iobase;
	struct tty *tp;
	int s;
	int error = 0;

	sc =  device_lookup_private(&xcom_cd, COMUNIT(dev));
	if (!sc)
		return ENXIO;

	if (!sc->sc_tty) {
		tp = sc->sc_tty = ttymalloc();
		tty_attach(tp);
	} else
		tp = sc->sc_tty;

	tp->t_oproc = comstart;
	tp->t_param = comparam;
	tp->t_dev = dev;

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

	s = spltty();

	if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
		ttychars(tp);
		tp->t_iflag = TTYDEF_IFLAG;
		tp->t_oflag = TTYDEF_OFLAG;
		tp->t_cflag = TTYDEF_CFLAG;
		if (ISSET(sc->sc_swflags, COM_SW_CLOCAL))
			SET(tp->t_cflag, CLOCAL);
		if (ISSET(sc->sc_swflags, COM_SW_CRTSCTS))
			SET(tp->t_cflag, CRTSCTS);
		if (ISSET(sc->sc_swflags, COM_SW_MDMBUF))
			SET(tp->t_cflag, MDMBUF);
		tp->t_lflag = TTYDEF_LFLAG;
		tp->t_ispeed = tp->t_ospeed = comdefaultrate;

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

		if (comsopen++ == 0)
			callout_reset(&com_poll_ch, 1, compollin, NULL);

		sc->sc_ibufp = sc->sc_ibuf = sc->sc_ibufs[0];
		sc->sc_ibufhigh = sc->sc_ibuf + COM_IHIGHWATER;
		sc->sc_ibufend = sc->sc_ibuf + COM_IBUFSIZE;

		iobase = sc->sc_iobase;
#ifdef COM_HAYESP
		/* Setup the ESP board */
		if (ISSET(sc->sc_hwflags, COM_HW_HAYESP)) {
			int hayespbase = sc->sc_hayespbase;

			outb(iobase + com_fifo,
			     FIFO_DMA_MODE|FIFO_ENABLE|
			     FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_8);

			/* Set 16550 compatibility mode */
			outb(hayespbase + HAYESP_CMD1, HAYESP_SETMODE);
			outb(hayespbase + HAYESP_CMD2,
			     HAYESP_MODE_FIFO|HAYESP_MODE_RTS|
			     HAYESP_MODE_SCALE);

			/* Set RTS/CTS flow control */
			outb(hayespbase + HAYESP_CMD1, HAYESP_SETFLOWTYPE);
			outb(hayespbase + HAYESP_CMD2, HAYESP_FLOW_RTS);
			outb(hayespbase + HAYESP_CMD2, HAYESP_FLOW_CTS);

			/* Set flow control levels */
			outb(hayespbase + HAYESP_CMD1, HAYESP_SETRXFLOW);
			outb(hayespbase + HAYESP_CMD2,
			     HAYESP_HIBYTE(HAYESP_RXHIWMARK));
			outb(hayespbase + HAYESP_CMD2,
			     HAYESP_LOBYTE(HAYESP_RXHIWMARK));
			outb(hayespbase + HAYESP_CMD2,
			     HAYESP_HIBYTE(HAYESP_RXLOWMARK));
			outb(hayespbase + HAYESP_CMD2,
			     HAYESP_LOBYTE(HAYESP_RXLOWMARK));
		} else
#endif
		if (ISSET(sc->sc_hwflags, COM_HW_FIFO))
			/* Set the FIFO threshold based on the receive speed. */
			outb(pio(iobase , com_fifo),
			    FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST |
			    (tp->t_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8));
		/* flush any pending I/O */
		while (ISSET(inb(pio(iobase , com_lsr)), LSR_RXRDY))
			(void) inb(pio(iobase , com_data));
		/* you turn me on, baby */
		sc->sc_mcr = MCR_DTR | MCR_RTS;
		if (!ISSET(sc->sc_hwflags, COM_HW_NOIEN))
			SET(sc->sc_mcr, MCR_IENABLE | MCR_DRS); /*   */
		outb(pio(iobase , com_mcr), sc->sc_mcr);
		sc->sc_ier = IER_ERXRDY | IER_ERLS | IER_EMSC;
		outb(pio(iobase , com_ier), sc->sc_ier);

		sc->sc_msr = inb(pio(iobase , com_msr));
		if (ISSET(sc->sc_swflags, COM_SW_SOFTCAR) ||
		    ISSET(sc->sc_msr, MSR_DCD) || ISSET(tp->t_cflag, MDMBUF))
			SET(tp->t_state, TS_CARR_ON);
		else
			CLR(tp->t_state, TS_CARR_ON);
	}
	splx(s);

	error = ttyopen(tp, COMDIALOUT(dev), ISSET(flag, O_NONBLOCK));

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

	/* XXX cleanup on error */

	return error;
}