Ejemplo n.º 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);
}
Ejemplo n.º 2
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);
}
Ejemplo n.º 3
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);
}
Ejemplo n.º 4
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);
}