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