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