Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 19 Aug 2003 12:07:26 -0700 (PDT)
From:      Marcel Moolenaar <marcel@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 36441 for review
Message-ID:  <200308191907.h7JJ7Q3v033278@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=36441

Change 36441 by marcel@marcel_nfs on 2003/08/19 12:06:59

	Pass the modem and line signals to the software interrupt
	handler in the low order 16 bits of the ttypend variable.
	Redefine the UART_IPEND_* constants accordingly. We still
	need to act upon signal changes.

Affected files ...

.. //depot/projects/uart/dev/uart/uart_bus.h#15 edit
.. //depot/projects/uart/dev/uart/uart_core.c#20 edit

Differences ...

==== //depot/projects/uart/dev/uart/uart_bus.h#15 (text+ko) ====

@@ -37,12 +37,20 @@
 #define	UART_FLUSH_RECEIVER	UART_DRAIN_RECEIVER
 #define	UART_FLUSH_TRANSMITTER	UART_DRAIN_TRANSMITTER
 
-/* Interrupt sources (in priority order). See also uart_core.c */
-#define	UART_IPEND_OVERRUN	0x0001
-#define	UART_IPEND_BREAK	0x0002
-#define	UART_IPEND_RXREADY	0x0004
-#define	UART_IPEND_SIGCHG	0x0008
-#define	UART_IPEND_TXIDLE	0x0010
+/*
+ * Interrupt sources (in priority order). See also uart_core.c
+ * Note that the low order 16 bits are used to pass modem signals
+ * from the hardware interrupt handler to the software interrupt
+ * handler. See UART_SIG_* and UART_SIGMASK_* below.
+ */
+#define	UART_IPEND_OVERRUN	0x010000
+#define	UART_IPEND_BREAK	0x020000
+#define	UART_IPEND_RXREADY	0x040000
+#define	UART_IPEND_SIGCHG	0x080000
+#define	UART_IPEND_TXIDLE	0x100000
+
+#define	UART_IPEND_MASK		0x1f0000
+#define	UART_IPEND_SIGMASK	0x00ffff
 
 /* Received character status bits. */
 #define	UART_STAT_BREAK		0x0100

==== //depot/projects/uart/dev/uart/uart_core.c#20 (text+ko) ====

@@ -180,13 +180,13 @@
 {
 	struct uart_softc *sc = arg;
 	struct tty *tp;
-	int c, pend, xc;
+	int c, pend, sig, xc;
 
 	if (sc->sc_leaving)
 		return;
 
 	pend = atomic_readandclear_32(&sc->sc_ttypend);
-	if (pend == 0)
+	if (!(pend & UART_IPEND_MASK))
 		return;
 
 	tp = sc->sc_tty;
@@ -203,6 +203,13 @@
 		}
 	}
 
+	if (pend & UART_IPEND_SIGCHG) {
+		sig = pend & UART_IPEND_SIGMASK;
+		/*
+		 * TODO: process signals.
+		 */
+	}
+
 	if (pend & UART_IPEND_TXIDLE) {
 		tp->t_state &= ~TS_BUSY;
 		(*linesw[tp->t_line].l_start)(tp);
@@ -293,16 +300,23 @@
 
 /*
  * Line or modem status change (OOB signalling).
+ * We pass the signals to the software interrupt handler for further
+ * processing. Note that we merge the delta bits, but set the state
+ * bits. This is to avoid loosing state transitions due to having more
+ * than 1 hardware interrupt between software interrupts.
  */
 static void
 uart_intr_sigchg(struct uart_softc *sc)
 {
-	int sig;
+	int new, old, sig;
 
 	sig = UART_GETSIG(sc);
-	/*
-	 * TODO: process the signals.
-	 */
+	do {
+		old = sc->sc_ttypend;
+		new = old & ~UART_SIGMASK_STATE;
+		new |= sig & UART_IPEND_SIGMASK;
+		new |= UART_IPEND_SIGCHG;
+	} while (!atomic_cmpset_32(&sc->sc_ttypend, old, new));
 }
 
 /*



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200308191907.h7JJ7Q3v033278>