PERFORCE change 35317 for review
Marcel Moolenaar
marcel at FreeBSD.org
Thu Jul 31 22:21:36 PDT 2003
http://perforce.freebsd.org/chv.cgi?CH=35317
Change 35317 by marcel at marcel_nfs on 2003/07/31 22:20:54
Add the callout/callin device support from sio(4).
Callin devices are named ttyu#, callout devices
are named uart#.
Affected files ...
.. //depot/projects/uart/dev/uart/uart_bus.h#13 edit
.. //depot/projects/uart/dev/uart/uart_core.c#15 edit
Differences ...
==== //depot/projects/uart/dev/uart/uart_bus.h#13 (text+ko) ====
@@ -96,6 +96,7 @@
void *sc_icookie;
int sc_irid;
+ int sc_callout:1; /* This UART is opened for callout. */
int sc_console:1; /* This UART is a console. */
int sc_dbgport:1; /* This UART is a debug port. */
int sc_fastintr:1; /* This UART uses fast interrupts. */
@@ -116,7 +117,7 @@
int sc_txdatasz;
int sc_txfifosz; /* Size of TX FIFO and buffer. */
- dev_t sc_si;
+ dev_t sc_si[2]; /* We have 2 device special files. */
void *sc_softih;
struct tty *sc_tty;
uint32_t sc_ttypend;
==== //depot/projects/uart/dev/uart/uart_core.c#15 (text+ko) ====
@@ -55,6 +55,8 @@
MALLOC_DEFINE(M_UART, "UART", "UART driver");
+#define UART_MINOR_CALLOUT 0x10000
+
static d_open_t uart_open;
static d_close_t uart_close;
static d_ioctl_t uart_ioctl;
@@ -77,6 +79,7 @@
{
struct uart_softc *sc;
+ KASSERT(tp->t_dev != NULL, ("foo"));
sc = tp->t_dev->si_drv1;
if (sc == NULL || sc->sc_leaving)
return;
@@ -95,6 +98,7 @@
struct uart_softc *sc;
int databits, parity, stopbits;
+ KASSERT(tp->t_dev != NULL, ("foo"));
sc = tp->t_dev->si_drv1;
if (sc == NULL || sc->sc_leaving)
return (ENODEV);
@@ -120,6 +124,7 @@
UART_SETSIG(sc, UART_SIG_DDTR | UART_SIG_DTR);
if ((t->c_cflag & CRTS_IFLOW) == 0)
UART_SETSIG(sc, UART_SIG_DRTS | UART_SIG_RTS);
+ ttsetwater(tp);
return (0);
}
@@ -128,6 +133,7 @@
{
struct uart_softc *sc;
+ KASSERT(tp->t_dev != NULL, ("foo"));
sc = tp->t_dev->si_drv1;
if (sc == NULL || sc->sc_leaving)
return;
@@ -454,13 +460,16 @@
tp = ttymalloc(NULL);
sc->sc_tty = tp;
- sc->sc_si = make_dev(&uart_cdevsw, device_get_unit(sc->sc_dev),
- UID_ROOT, GID_WHEEL, 0600, "%s%r", uart_driver_name,
- device_get_unit(sc->sc_dev));
- sc->sc_si->si_drv1 = sc;
- sc->sc_si->si_tty = tp;
+ sc->sc_si[0] = make_dev(&uart_cdevsw, device_get_unit(sc->sc_dev),
+ UID_ROOT, GID_WHEEL, 0600, "ttyu%r", device_get_unit(sc->sc_dev));
+ sc->sc_si[0]->si_drv1 = sc;
+ sc->sc_si[0]->si_tty = tp;
+ sc->sc_si[1] = make_dev(&uart_cdevsw,
+ device_get_unit(sc->sc_dev) | UART_MINOR_CALLOUT, UID_ROOT,
+ GID_WHEEL, 0600, "uart%r", device_get_unit(sc->sc_dev));
+ sc->sc_si[1]->si_drv1 = sc;
+ sc->sc_si[1]->si_tty = tp;
- tp->t_dev = sc->sc_si;
tp->t_oproc = uart_tty_oproc;
tp->t_param = uart_tty_param;
tp->t_stop = uart_tty_stop;
@@ -499,7 +508,8 @@
sc->sc_leaving = 1;
ithread_remove_handler(sc->sc_softih);
- destroy_dev(sc->sc_si);
+ destroy_dev(sc->sc_si[0]);
+ destroy_dev(sc->sc_si[1]);
/* ttyfree(sc->sc_tty); */
UART_DETACH(sc);
@@ -526,30 +536,78 @@
sc = dev->si_drv1;
if (sc == NULL || sc->sc_leaving)
- return (ENXIO);
+ return (ENODEV);
tp = dev->si_tty;
+
+ loop:
if (tp->t_state & TS_ISOPEN) {
- if ((tp->t_state & TS_XCLUDE) && suser(td) != 0)
+ /*
+ * The device is open, so everything has been initialized.
+ * Handle conflicts.
+ */
+ if (minor(dev) & UART_MINOR_CALLOUT) {
+ if (!sc->sc_callout)
+ return (EBUSY);
+ } else {
+ if (sc->sc_callout) {
+ if (flags & O_NONBLOCK)
+ return (EBUSY);
+ error = tsleep(sc, TTIPRI|PCATCH, "uartbi", 0);
+ sc = dev->si_drv1;
+ if (sc == NULL || sc->sc_leaving)
+ return (ENODEV);
+ if (error)
+ return (error);
+ goto loop;
+ }
+ }
+ if (tp->t_state & TS_XCLUDE && suser(td) != 0)
return (EBUSY);
} else {
+ /*
+ * The device isn't open, so there are no conflicts.
+ * Initialize it. Initialization is done twice in many
+ * cases: to preempt sleeping callin opens if we are
+ * callout, and to complete a callin open after DCD rises.
+ */
+ sc->sc_callout = (minor(dev) & UART_MINOR_CALLOUT) ? 1 : 0;
+ tp->t_dev = dev;
+
tp->t_cflag = TTYDEF_CFLAG;
tp->t_iflag = TTYDEF_IFLAG;
tp->t_lflag = TTYDEF_LFLAG;
tp->t_oflag = TTYDEF_OFLAG;
if (sc->sc_console) {
tp->t_cflag |= CLOCAL;
+ tp->t_cflag &= ~HUPCL;
tp->t_ispeed = tp->t_ospeed = uart_console.baudrate;
} else
tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
error = uart_tty_param(tp, &tp->t_termios);
if (error)
return (error);
- ttsetwater(tp);
+ /*
+ * Handle initial DCD.
+ */
+ if ((UART_GETSIG(sc) & UART_SIG_DCD) || sc->sc_callout)
+ (*linesw[tp->t_line].l_modem)(tp, 1);
+ }
+ /*
+ * Wait for DCD if necessary.
+ */
+ if (!(tp->t_state & TS_CARR_ON) && !sc->sc_callout &&
+ !(tp->t_cflag & CLOCAL) && !(flags & O_NONBLOCK)) {
+ error = tsleep(TSA_CARR_ON(tp), TTIPRI|PCATCH, "uartdcd", 0);
+ sc = dev->si_drv1;
+ if (sc == NULL || sc->sc_leaving)
+ return (ENODEV);
+ if (error)
+ return (error);
+ goto loop;
}
-
error = ttyopen(dev, tp);
- if (error == 0)
+ if (!error)
error = (*linesw[tp->t_line].l_open)(dev, tp);
return (error);
}
@@ -557,17 +615,24 @@
static int
uart_close(dev_t dev, int flags, int mode, struct thread *td)
{
+ struct uart_softc *sc;
struct tty *tp;
+ sc = dev->si_drv1;
+ if (sc == NULL || sc->sc_leaving)
+ return (ENODEV);
+
tp = dev->si_tty;
-
if (!(tp->t_state & TS_ISOPEN))
return (0);
- /* XXX reset UART line and modem signals. */
+ if (!sc->sc_console)
+ UART_SETSIG(sc, UART_SIG_DDTR | UART_SIG_DRTS);
(*linesw[tp->t_line].l_close)(tp, flags);
ttyclose(tp);
+ wakeup(sc);
+ wakeup(TSA_CARR_ON(tp));
return (0);
}
@@ -580,7 +645,7 @@
sc = dev->si_drv1;
if (sc == NULL || sc->sc_leaving)
- return (ENXIO);
+ return (ENODEV);
tp = dev->si_tty;
error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flags, td);
More information about the p4-projects
mailing list