Use generic support for BREAK and modem control ioctls.

This commit is contained in:
Poul-Henning Kamp 2004-06-25 10:54:05 +00:00
parent 85bc8ea7fc
commit 96df2b0bfb
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=131095
2 changed files with 93 additions and 127 deletions

View File

@ -49,7 +49,7 @@
#include <sys/tty.h>
#include <sys/syslog.h>
#include <sys/fcntl.h>
#include <sys/bus.h>
#include <sys/serial.h>
#include <sys/bus.h>
#include <machine/resource.h>
@ -79,7 +79,8 @@ static d_write_t digiwrite;
static d_ioctl_t digiioctl;
static void digistop(struct tty *tp, int rw);
static int digimctl(struct digi_p *port, int bits, int how);
static int digibreak(struct tty *tp, int brk);
static int digimodem(struct tty *tp, int sigon, int sigoff);
static void digi_poll(void *ptr);
static void digi_freemoduledata(struct digi_softc *);
static void fepcmd(struct digi_p *port, int cmd, int op, int ncmds);
@ -647,49 +648,51 @@ digi_init(struct digi_softc *sc)
}
static int
digimctl(struct digi_p *port, int bits, int how)
digimodem(struct tty *tp, int sigon, int sigoff)
{
int mstat;
struct digi_softc *sc;
struct digi_p *port;
int mynor, unit, pnum;
int bitand, bitor, mstat;
if (how == DMGET) {
mynor = minor(tp->t_dev);
unit = MINOR_TO_UNIT(mynor);
pnum = MINOR_TO_PORT(mynor);
sc = (struct digi_softc *)devclass_get_softc(digi_devclass, unit);
port = &sc->ports[pnum];
if (sigon == 0 && sigoff == 0) {
port->sc->setwin(port->sc, 0);
mstat = port->bc->mstat;
port->sc->hidewin(port->sc);
bits = TIOCM_LE;
if (mstat & port->sc->csigs->rts)
bits |= TIOCM_RTS;
sigon |= SER_RTS;
if (mstat & port->cd)
bits |= TIOCM_CD;
sigon |= SER_DCD;
if (mstat & port->dsr)
bits |= TIOCM_DSR;
sigon |= SER_DSR;
if (mstat & port->sc->csigs->cts)
bits |= TIOCM_CTS;
sigon |= SER_CTS;
if (mstat & port->sc->csigs->ri)
bits |= TIOCM_RI;
sigon |= SER_RI;
if (mstat & port->sc->csigs->dtr)
bits |= TIOCM_DTR;
return (bits);
sigon |= SER_DTR;
return (sigon);
}
/* Only DTR and RTS may be set */
mstat = 0;
if (bits & TIOCM_DTR)
mstat |= port->sc->csigs->dtr;
if (bits & TIOCM_RTS)
mstat |= port->sc->csigs->rts;
switch (how) {
case DMSET:
fepcmd_b(port, SETMODEM, mstat, ~mstat, 0);
break;
case DMBIS:
fepcmd_b(port, SETMODEM, mstat, 0, 0);
break;
case DMBIC:
fepcmd_b(port, SETMODEM, 0, mstat, 0);
break;
}
bitand = 0;
bitor = 0;
if (sigoff & SER_DTR)
bitand |= port->sc->csigs->dtr;
if (sigoff & SER_RTS)
bitand |= port->sc->csigs->rts;
if (sigon & SER_DTR)
bitor |= port->sc->csigs->dtr;
if (sigon & SER_RTS)
bitor |= port->sc->csigs->rts;
fepcmd_b(port, SETMODEM, bitor, ~bitand, 0);
return (0);
}
@ -785,6 +788,8 @@ digiopen(struct cdev *dev, int flag, int mode, struct thread *td)
*/
tp->t_oproc = digistart;
tp->t_param = digiparam;
tp->t_modem = digimodem;
tp->t_break = digibreak;
tp->t_stop = digistop;
tp->t_dev = dev;
tp->t_termios = (mynor & CALLOUT_MASK) ?
@ -923,7 +928,7 @@ digihardclose(struct digi_p *port)
(!port->active_out && !(bc->mstat & port->cd) &&
!(port->it_in.c_cflag & CLOCAL)) ||
!(port->tp->t_state & TS_ISOPEN)) {
digimctl(port, TIOCM_DTR | TIOCM_RTS, DMBIC);
digimodem(port->tp, 0, SER_DTR | SER_RTS);
if (port->dtr_wait != 0) {
/* Schedule a wakeup of any callin devices */
port->wopeners++;
@ -1277,34 +1282,6 @@ digiioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t
case DIGIIO_RING:
port->send_ring = *(u_char *)data;
break;
case TIOCSBRK:
/*
* now it sends 400 millisecond break because I don't know
* how to send an infinite break
*/
fepcmd_w(port, SENDBREAK, 400, 10);
break;
case TIOCCBRK:
/* now it's empty */
break;
case TIOCSDTR:
digimctl(port, TIOCM_DTR, DMBIS);
break;
case TIOCCDTR:
digimctl(port, TIOCM_DTR, DMBIC);
break;
case TIOCMSET:
digimctl(port, *(int *)data, DMSET);
break;
case TIOCMBIS:
digimctl(port, *(int *)data, DMBIS);
break;
case TIOCMBIC:
digimctl(port, *(int *)data, DMBIC);
break;
case TIOCMGET:
*(int *)data = digimctl(port, 0, DMGET);
break;
case TIOCMSDTRWAIT:
error = suser(td);
if (error != 0) {
@ -1331,6 +1308,33 @@ digiioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t
return (0);
}
static int
digibreak(struct tty *tp, int brk)
{
int mynor;
int unit;
int pnum;
struct digi_softc *sc;
struct digi_p *port;
mynor = minor(tp->t_dev);
unit = MINOR_TO_UNIT(mynor);
pnum = MINOR_TO_PORT(mynor);
sc = (struct digi_softc *)devclass_get_softc(digi_devclass, unit);
KASSERT(sc, ("digi%d: softc not allocated in digiparam\n", unit));
port = &sc->ports[pnum];
/*
* now it sends 400 millisecond break because I don't know
* how to send an infinite break
*/
if (brk)
fepcmd_w(port, SENDBREAK, 400, 10);
return (0);
}
static int
digiparam(struct tty *tp, struct termios *t)
{
@ -1371,9 +1375,9 @@ digiparam(struct tty *tp, struct termios *t)
if (cflag == 0) { /* hangup */
DLOG(DIGIDB_SET, (sc->dev, "port%d: hangup\n", pnum));
digimctl(port, TIOCM_DTR | TIOCM_RTS, DMBIC);
digimodem(port->tp, 0, SER_DTR | SER_RTS);
} else {
digimctl(port, TIOCM_DTR | TIOCM_RTS, DMBIS);
digimodem(port->tp, SER_DTR | SER_RTS, 0);
DLOG(DIGIDB_SET, (sc->dev, "port%d: CBAUD = %d\n", pnum,
cflag));

View File

@ -240,6 +240,27 @@ uart_tty_param(struct tty *tp, struct termios *t)
return (0);
}
static int
uart_tty_modem(struct tty *tp, int biton, int bitoff)
{
struct uart_softc *sc;
sc = tp->t_dev->si_drv1;
if (biton != 0 || bitoff != 0)
UART_SETSIG(sc, SER_DELTA(bitoff|biton) | biton);
return (sc->sc_hwsig);
}
static int
uart_tty_break(struct tty *tp, int state)
{
struct uart_softc *sc;
sc = tp->t_dev->si_drv1;
UART_IOCTL(sc, UART_IOCTL_BREAK, state);
return (0);
}
static void
uart_tty_stop(struct tty *tp, int rw)
{
@ -337,6 +358,8 @@ uart_tty_attach(struct uart_softc *sc)
tp->t_oproc = uart_tty_oproc;
tp->t_param = uart_tty_param;
tp->t_stop = uart_tty_stop;
tp->t_modem = uart_tty_modem;
tp->t_break = uart_tty_break;
if (sc->sc_sysdev != NULL && sc->sc_sysdev->type == UART_DEV_CONSOLE) {
sprintf(((struct consdev *)sc->sc_sysdev->cookie)->cn_name,
@ -484,7 +507,7 @@ uart_tty_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flags,
{
struct uart_softc *sc;
struct tty *tp;
int bits, error, sig;
int error;
sc = dev->si_drv1;
if (sc == NULL || sc->sc_leaving)
@ -495,69 +518,8 @@ uart_tty_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flags,
if (error != ENOTTY)
return (error);
error = 0;
switch (cmd) {
case TIOCSBRK:
UART_IOCTL(sc, UART_IOCTL_BREAK, 1);
break;
case TIOCCBRK:
UART_IOCTL(sc, UART_IOCTL_BREAK, 0);
break;
case TIOCSDTR:
UART_SETSIG(sc, SER_DDTR | SER_DTR);
break;
case TIOCCDTR:
UART_SETSIG(sc, SER_DDTR);
break;
case TIOCMSET:
bits = *(int*)data;
sig = SER_DDTR | SER_DRTS;
if (bits & TIOCM_DTR)
sig |= SER_DTR;
if (bits & TIOCM_RTS)
sig |= SER_RTS;
UART_SETSIG(sc, sig);
break;
case TIOCMBIS:
bits = *(int*)data;
sig = 0;
if (bits & TIOCM_DTR)
sig |= SER_DDTR | SER_DTR;
if (bits & TIOCM_RTS)
sig |= SER_DRTS | SER_RTS;
UART_SETSIG(sc, sig);
break;
case TIOCMBIC:
bits = *(int*)data;
sig = 0;
if (bits & TIOCM_DTR)
sig |= SER_DDTR;
if (bits & TIOCM_RTS)
sig |= SER_DRTS;
UART_SETSIG(sc, sig);
break;
case TIOCMGET:
sig = sc->sc_hwsig;
bits = TIOCM_LE;
if (sig & SER_DTR)
bits |= TIOCM_DTR;
if (sig & SER_RTS)
bits |= TIOCM_RTS;
if (sig & SER_DSR)
bits |= TIOCM_DSR;
if (sig & SER_CTS)
bits |= TIOCM_CTS;
if (sig & SER_DCD)
bits |= TIOCM_CD;
if (sig & (SER_DRI | SER_RI))
bits |= TIOCM_RI;
*(int*)data = bits;
break;
default:
error = pps_ioctl(cmd, data, &sc->sc_pps);
if (error == ENODEV)
error = ENOTTY;
break;
}
error = pps_ioctl(cmd, data, &sc->sc_pps);
if (error == ENODEV)
error = ENOTTY;
return (error);
}