Beispiel #1
0
/*
 * close routine. returns zero if successful, else error code
 */
int
mttyclose(dev_t dev, int flag, int mode, struct proc *p)
{
    struct mtty_softc *ms = mtty_cd.cd_devs[MAGMA_CARD(dev)];
    struct mtty_port *mp = &ms->ms_port[MAGMA_PORT(dev)];
    struct tty *tp = mp->mp_tty;
    int s;

    (*linesw[tp->t_line].l_close)(tp, flag, p);
    s = spltty();

    /* if HUPCL is set, and the tty is no longer open
     * shut down the port
     */
    if (ISSET(tp->t_cflag, HUPCL) || !ISSET(tp->t_state, TS_ISOPEN)) {
        /* XXX wait until FIFO is empty before turning off the channel
        	struct cd1400 *cd = mp->mp_cd1400;
        */

        /* drop DTR and RTS */
        (void)mtty_modem_control(mp, 0, DMSET);

        /* turn off the channel
        CD1400_WRITE_REG(cd, CD1400_CAR, mp->mp_channel);
        cd1400_write_ccr(cd, CD1400_CCR_CMDRESET);
        */
    }

    splx(s);
    ttyclose(tp);

    return (0);
}
Beispiel #2
0
/*
 * Start output, after a stop.
 */
void
mtty_start(struct tty *tp)
{
    struct mtty_softc *ms = mtty_cd.cd_devs[MAGMA_CARD(tp->t_dev)];
    struct mtty_port *mp = &ms->ms_port[MAGMA_PORT(tp->t_dev)];
    int s;

    s = spltty();

    /* we only need to do something if we are not already busy
     * or delaying or stopped
     */
    if (!ISSET(tp->t_state, TS_TTSTOP | TS_TIMEOUT | TS_BUSY)) {

        /* if we are sleeping and output has drained below
         * low water mark, awaken
         */
        ttwakeupwr(tp);

        /* if something to send, start transmitting
         */
        if (tp->t_outq.c_cc) {
            mp->mp_txc = ndqb(&tp->t_outq, 0);
            mp->mp_txp = tp->t_outq.c_cf;
            SET(tp->t_state, TS_BUSY);
            cd1400_enable_transmitter(mp->mp_cd1400, mp->mp_channel);
        }
    }

    splx(s);
}
Beispiel #3
0
/*
 * return tty pointer
 */
struct tty *
mttytty(dev_t dev)
{
    struct mtty_softc *ms = mtty_cd.cd_devs[MAGMA_CARD(dev)];
    struct mtty_port *mp = &ms->ms_port[MAGMA_PORT(dev)];

    return (mp->mp_tty);
}
Beispiel #4
0
/*
 * Write routine
 */
int
mttywrite(dev_t dev, struct uio *uio, int flags)
{
    struct mtty_softc *ms = mtty_cd.cd_devs[MAGMA_CARD(dev)];
    struct mtty_port *mp = &ms->ms_port[MAGMA_PORT(dev)];
    struct tty *tp = mp->mp_tty;

    return ((*linesw[tp->t_line].l_write)(tp, uio, flags));
}
Beispiel #5
0
/*
 * return tty pointer
 */
struct tty *
mttytty(dev_t dev)
{
	struct mtty_softc *ms = device_lookup_private(&mtty_cd,
						      MAGMA_CARD(dev));
	struct mtty_port *mp = &ms->ms_port[MAGMA_PORT(dev)];

	return(mp->mp_tty);
}
Beispiel #6
0
/*
 * close routine. returns zero if successful, else error code
 */
int
mbppclose(dev_t dev, int flag, int mode, struct proc *p)
{
    struct mbpp_softc *ms = mbpp_cd.cd_devs[MAGMA_CARD(dev)];
    struct mbpp_port *mp = &ms->ms_port[MAGMA_PORT(dev)];

    mp->mp_flags = 0;
    return (0);
}
Beispiel #7
0
/*
 * close routine. returns zero if successful, else error code
 */
int
mbppclose(dev_t dev, int flag, int mode, struct lwp *l)
{
	struct mbpp_softc *ms = device_lookup_private(&mbpp_cd,
						      MAGMA_CARD(dev));
	struct mbpp_port *mp = &ms->ms_port[MAGMA_PORT(dev)];

	mp->mp_flags = 0;
	return(0);
}
Beispiel #8
0
/*
 * Write routine
 */
int
mttywrite(dev_t dev, struct uio *uio, int flags)
{
	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;

	return( (*tp->t_linesw->l_write)(tp, uio, flags) );
}
Beispiel #9
0
/*
 * Poll routine
 */
int
mttypoll(dev_t dev, int events, 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;

	return ((*tp->t_linesw->l_poll)(tp, events, l));
}
Beispiel #10
0
/*
 * open routine. returns zero if successful, else error code
 */
int
mbppopen(dev_t dev, int flags, int mode, struct lwp *l)
{
	int card = MAGMA_CARD(dev);
	int port = MAGMA_PORT(dev);
	struct mbpp_softc *ms;
	struct mbpp_port *mp;
	int s;

	if ((ms = device_lookup_private(&mbpp_cd, card)) == NULL
	    || port >= ms->ms_nports )
		return(ENXIO);

	mp = &ms->ms_port[port];

	s = spltty();
	if( ISSET(mp->mp_flags, MBPPF_OPEN) ) {
		splx(s);
		return(EBUSY);
	}
	SET(mp->mp_flags, MBPPF_OPEN);
	splx(s);

	/* set defaults */
	mp->mp_burst = MBPP_BURST;
	mp->mp_timeout = mbpp_mstohz(MBPP_TIMEOUT);
	mp->mp_delay = mbpp_mstohz(MBPP_DELAY);

	/* init chips */
	if( mp->mp_cd1400 ) {	/* CD1400 */
		struct cd1400 *cd = mp->mp_cd1400;

		/* set up CD1400 channel */
		s = spltty();
		cd1400_write_reg(cd, CD1400_CAR, 0);
		cd1400_write_ccr(cd, CD1400_CCR_CMDRESET);
		cd1400_write_reg(cd, CD1400_LIVR, (1<<3));
		splx(s);
	} else {		/* CD1190 */
		mp->mp_flags = 0;
		return (ENXIO);
	}

	return (0);
}
Beispiel #11
0
/*
 * ioctl routine
 */
int
mbppioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l)
{
	struct mbpp_softc *ms = device_lookup_private(&mbpp_cd,
						      MAGMA_CARD(dev));
	struct mbpp_port *mp = &ms->ms_port[MAGMA_PORT(dev)];
	struct mbpp_param *bp;
	int error = 0;
	int s;

	switch(cmd) {
	case MBPPIOCSPARAM:
		bp = (struct mbpp_param *)data;
		if( bp->bp_burst < MBPP_BURST_MIN || bp->bp_burst > MBPP_BURST_MAX ||
		    bp->bp_delay < MBPP_DELAY_MIN || bp->bp_delay > MBPP_DELAY_MIN ) {
			error = EINVAL;
		} else {
			mp->mp_burst = bp->bp_burst;
			mp->mp_timeout = mbpp_mstohz(bp->bp_timeout);
			mp->mp_delay = mbpp_mstohz(bp->bp_delay);
		}
		break;
	case MBPPIOCGPARAM:
		bp = (struct mbpp_param *)data;
		bp->bp_burst = mp->mp_burst;
		bp->bp_timeout = mbpp_hztoms(mp->mp_timeout);
		bp->bp_delay = mbpp_hztoms(mp->mp_delay);
		break;
	case MBPPIOCGSTAT:
		/* XXX make this more generic */
		s = spltty();
		cd1400_write_reg(mp->mp_cd1400, CD1400_CAR, 0);
		*(int *)data = cd1400_read_reg(mp->mp_cd1400, CD1400_PSVR);
		splx(s);
		break;
	default:
		error = ENOTTY;
	}

	return(error);
}
Beispiel #12
0
/*
 * ioctl routine
 */
int
mbppioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p)
{
    struct mbpp_softc *ms = mbpp_cd.cd_devs[MAGMA_CARD(dev)];
    struct mbpp_port *mp = &ms->ms_port[MAGMA_PORT(dev)];
    struct bpp_param *bp;
    int error = 0;
    int s;

    switch(cmd) {
    case BPPIOCSPARAM:
        bp = (struct bpp_param *)data;
        if (bp->bp_burst < BPP_BURST_MIN || bp->bp_burst > BPP_BURST_MAX ||
                bp->bp_delay < BPP_DELAY_MIN || bp->bp_delay > BPP_DELAY_MIN) {
            error = EINVAL;
        } else {
            mp->mp_burst = bp->bp_burst;
            mp->mp_timeout = mbpp_mstohz(bp->bp_timeout);
            mp->mp_delay = mbpp_mstohz(bp->bp_delay);
        }
        break;
    case BPPIOCGPARAM:
        bp = (struct bpp_param *)data;
        bp->bp_burst = mp->mp_burst;
        bp->bp_timeout = mbpp_hztoms(mp->mp_timeout);
        bp->bp_delay = mbpp_hztoms(mp->mp_delay);
        break;
    case BPPIOCGSTAT:
        /* XXX make this more generic */
        s = spltty();
        CD1400_WRITE_REG(mp->mp_cd1400, CD1400_CAR, 0);
        *(int *)data = CD1400_READ_REG(mp->mp_cd1400, CD1400_PSVR);
        splx(s);
        break;
    default:
        error = ENOTTY;
    }

    return (error);
}
Beispiel #13
0
/*
 * Stop output, e.g., for ^S or output flush.
 */
int
mttystop(struct tty *tp, int flags)
{
    struct mtty_softc *ms = mtty_cd.cd_devs[MAGMA_CARD(tp->t_dev)];
    struct mtty_port *mp = &ms->ms_port[MAGMA_PORT(tp->t_dev)];
    int s;

    s = spltty();

    if (ISSET(tp->t_state, TS_BUSY)) {
        if (!ISSET(tp->t_state, TS_TTSTOP))
            SET(tp->t_state, TS_FLUSH);

        /*
         * the transmit interrupt routine will disable transmit when it
         * notices that MTTYF_STOP has been set.
         */
        SET(mp->mp_flags, MTTYF_STOP);
    }

    splx(s);
    return (0);
}
Beispiel #14
0
/*
 * Start output, after a stop.
 */
void
mtty_start(struct tty *tp)
{
	struct mtty_softc *ms = device_lookup_private(&mtty_cd,
						      MAGMA_CARD(tp->t_dev));
	struct mtty_port *mp = &ms->ms_port[MAGMA_PORT(tp->t_dev)];
	int s;

	s = spltty();

	/* we only need to do something if we are not already busy
	 * or delaying or stopped
	 */
	if( !ISSET(tp->t_state, TS_TTSTOP | TS_TIMEOUT | TS_BUSY) ) {
		if (ttypull(tp)) {
			mp->mp_txc = ndqb(&tp->t_outq, 0);
			mp->mp_txp = tp->t_outq.c_cf;
			SET(tp->t_state, TS_BUSY);
			cd1400_enable_transmitter(mp->mp_cd1400, mp->mp_channel);
		}
	}

	splx(s);
}
Beispiel #15
0
/*
 * ioctl routine
 */
int
mttyioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p)
{
    struct mtty_softc *ms = mtty_cd.cd_devs[MAGMA_CARD(dev)];
    struct mtty_port *mp = &ms->ms_port[MAGMA_PORT(dev)];
    struct tty *tp = mp->mp_tty;
    int error;

    error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flags, p);
    if (error >= 0)
        return (error);

    error = ttioctl(tp, cmd, data, flags, p);
    if (error >= 0)
        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 (suser(p, 0))
            error = EPERM;
        else
            mp->mp_openflags = *((int *)data) &
                               (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL |
                                TIOCFLAG_CRTSCTS | TIOCFLAG_MDMBUF);
        break;

    default:
        error = ENOTTY;
    }

    return (error);
}
Beispiel #16
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);
}
Beispiel #17
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));
}
Beispiel #18
0
int
mbpp_rw(dev_t dev, struct uio *uio)
{
    int card = MAGMA_CARD(dev);
    int port = MAGMA_PORT(dev);
    struct mbpp_softc *ms = mbpp_cd.cd_devs[card];
    struct mbpp_port *mp = &ms->ms_port[port];
    caddr_t buffer, ptr;
    int buflen, cnt, len;
    int s, error = 0;
    int gotdata = 0;

    if (uio->uio_resid == 0)
        return (0);

    buflen = min(uio->uio_resid, mp->mp_burst);
    buffer = malloc(buflen, M_DEVBUF, M_WAITOK);

    SET(mp->mp_flags, MBPPF_UIO);

    /*
     * start timeout, if needed
     */
    if (mp->mp_timeout > 0) {
        SET(mp->mp_flags, MBPPF_TIMEOUT);
        timeout_add(&mp->mp_timeout_tmo, mp->mp_timeout);
    }

    len = cnt = 0;
    while (uio->uio_resid > 0) {
        len = min(buflen, uio->uio_resid);
        ptr = buffer;

        if (uio->uio_rw == UIO_WRITE) {
            error = uiomove(ptr, len, uio);
            if (error)
                break;
        }
again:		/* goto bad */
        /* timed out?  */
        if (!ISSET(mp->mp_flags, MBPPF_UIO))
            break;

        /*
         * perform the operation
         */
        if (uio->uio_rw == UIO_WRITE) {
            cnt = mbpp_send(mp, ptr, len);
        } else {
            cnt = mbpp_recv(mp, ptr, len);
        }

        if (uio->uio_rw == UIO_READ) {
            if (cnt) {
                error = uiomove(ptr, cnt, uio);
                if (error)
                    break;
                gotdata++;
            }
            else if (gotdata)	/* consider us done */
                break;
        }

        /* timed out?  */
        if (!ISSET(mp->mp_flags, MBPPF_UIO))
            break;

        /*
         * poll delay?
         */
        if (mp->mp_delay > 0) {
            s = spltty();	/* XXX */
            SET(mp->mp_flags, MBPPF_DELAY);
            timeout_add(&mp->mp_start_tmo, mp->mp_delay);
            error = tsleep(mp, PCATCH | PZERO, "mbppdelay", 0);
            splx(s);
            if (error)
                break;
        }

        /*
         * don't call uiomove again until we used all the data we grabbed
         */
        if (uio->uio_rw == UIO_WRITE && cnt != len) {
            ptr += cnt;
            len -= cnt;
            cnt = 0;
            goto again;
        }
    }

    /*
     * clear timeouts
     */
    s = spltty();	/* XXX */
    if (ISSET(mp->mp_flags, MBPPF_TIMEOUT)) {
        timeout_del(&mp->mp_timeout_tmo);
        CLR(mp->mp_flags, MBPPF_TIMEOUT);
    }
    if (ISSET(mp->mp_flags, MBPPF_DELAY)) {
        timeout_del(&mp->mp_start_tmo);
        CLR(mp->mp_flags, MBPPF_DELAY);
    }
    splx(s);

    /*
     * adjust for those chars that we uiomoved but never actually wrote
     */
    if (uio->uio_rw == UIO_WRITE && cnt != len) {
        uio->uio_resid += (len - cnt);
    }

    free(buffer, M_DEVBUF);
    return (error);
}
Beispiel #19
0
/*
 * Set tty parameters, returns error or 0 on success
 */
int
mtty_param(struct tty *tp, struct termios *t)
{
    struct mtty_softc *ms = mtty_cd.cd_devs[MAGMA_CARD(tp->t_dev)];
    struct mtty_port *mp = &ms->ms_port[MAGMA_PORT(tp->t_dev)];
    struct cd1400 *cd = mp->mp_cd1400;
    int rbpr, tbpr, rcor, tcor;
    u_char mcor1 = 0, mcor2 = 0;
    int s, opt;

    if (t->c_ospeed &&
            cd1400_compute_baud(t->c_ospeed, cd->cd_clock, &tcor, &tbpr))
        return (EINVAL);

    if (t->c_ispeed &&
            cd1400_compute_baud(t->c_ispeed, cd->cd_clock, &rcor, &rbpr))
        return (EINVAL);

    s = spltty();

    /* hang up the line if ospeed is zero, else raise DTR */
    (void)mtty_modem_control(mp, TIOCM_DTR,
                             (t->c_ospeed == 0 ? DMBIC : DMBIS));

    /* select channel, done in mtty_modem_control() */
    /* CD1400_WRITE_REG(cd, CD1400_CAR, mp->mp_channel); */

    /* set transmit speed */
    if (t->c_ospeed) {
        CD1400_WRITE_REG(cd, CD1400_TCOR, tcor);
        CD1400_WRITE_REG(cd, CD1400_TBPR, tbpr);
    }

    /* set receive speed */
    if (t->c_ispeed) {
        CD1400_WRITE_REG(cd, CD1400_RCOR, rcor);
        CD1400_WRITE_REG(cd, CD1400_RBPR, rbpr);
    }

    /* enable transmitting and receiving on this channel */
    opt = CD1400_CCR_CMDCHANCTL | CD1400_CCR_XMTEN | CD1400_CCR_RCVEN;
    cd1400_write_ccr(cd, opt);

    /* set parity, data and stop bits */
    opt = 0;
    if (ISSET(t->c_cflag, PARENB))
        opt |= (ISSET(t->c_cflag, PARODD) ? CD1400_COR1_PARODD : CD1400_COR1_PARNORMAL);

    if (!ISSET(t->c_iflag, INPCK))
        opt |= CD1400_COR1_NOINPCK; /* no parity checking */

    if (ISSET(t->c_cflag, CSTOPB))
        opt |= CD1400_COR1_STOP2;

    switch( t->c_cflag & CSIZE) {
    case CS5:
        opt |= CD1400_COR1_CS5;
        break;

    case CS6:
        opt |= CD1400_COR1_CS6;
        break;

    case CS7:
        opt |= CD1400_COR1_CS7;
        break;

    default:
        opt |= CD1400_COR1_CS8;
        break;
    }

    CD1400_WRITE_REG(cd, CD1400_COR1, opt);

    /*
     * enable Embedded Transmit Commands (for breaks)
     * use the CD1400 automatic CTS flow control if CRTSCTS is set
     */
    opt = CD1400_COR2_ETC;
    if (ISSET(t->c_cflag, CRTSCTS))
        opt |= CD1400_COR2_CCTS_OFLOW;
    CD1400_WRITE_REG(cd, CD1400_COR2, opt);

    CD1400_WRITE_REG(cd, CD1400_COR3, MTTY_RX_FIFO_THRESHOLD);

    cd1400_write_ccr(cd, CD1400_CCR_CMDCORCHG | CD1400_CCR_COR1 | CD1400_CCR_COR2 | CD1400_CCR_COR3);

    CD1400_WRITE_REG(cd, CD1400_COR4, CD1400_COR4_PFO_EXCEPTION);
    CD1400_WRITE_REG(cd, CD1400_COR5, 0);

    /*
     * if automatic RTS handshaking enabled, set DTR threshold
     * (RTS and DTR lines are switched, CD1400 thinks its DTR)
     */
    if (ISSET(t->c_cflag, CRTSCTS))
        mcor1 = MTTY_RX_DTR_THRESHOLD;

    /* set up `carrier detect' interrupts */
    if (cd->cd_parmode) {
        SET(mcor1, CD1400_MCOR1_DSRzd);
        SET(mcor2, CD1400_MCOR2_DSRod);
    } else {
        SET(mcor1, CD1400_MCOR1_CDzd);
        SET(mcor2, CD1400_MCOR2_CDod);
    }

    CD1400_WRITE_REG(cd, CD1400_MCOR1, mcor1);
    CD1400_WRITE_REG(cd, CD1400_MCOR2, mcor2);

    /* receive timeout 2ms */
    CD1400_WRITE_REG(cd, CD1400_RTPR, 2);

    splx(s);
    return (0);
}
Beispiel #20
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);
}