Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 6 Jul 2003 12:51:49 -0700 (PDT)
From:      Marcel Moolenaar <marcel@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 34133 for review
Message-ID:  <200307061951.h66JpnAR022295@repoman.freebsd.org>

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

Change 34133 by marcel@marcel_nfs on 2003/07/06 12:51:16

	Rework some of the bones and add some meat to try it on for size:
	o  Redefine the interrupt sources/priorities to have more relation
	   to the higher level operation. This gives a better abstraction
	   and therefore better hardware independence.
	o  Add a flag to the softc for when there's no interrupt resource.
	   We don't do anything with it yet.
	o  Add transmit and receive buffers. Make them OBUFSIZ and IBUFSIZ 
	   in size (resp). Both buffers are circular.
	o  Flesh-out the low-level (hardware) interrupt handler and add
	   the software interrupt stuff for the high-level processing.
	o  Improve uart_bus_probe() to properly create the KOBJ instance
	   of the UART class with which we're going to work. UART drivers
	   can now access their class specific data in all cases.
	o  Get the fundamentals of uart_bus_detach() filled in. UARTs
	   are likely to come and go, so we want this to work right.
	o  Add new UART interface methods to the ns8250 and the sab82532
	   drivers. We need to start fleshing those out next.

Affected files ...

.. //depot/projects/uart/dev/uart/uart_bus.h#3 edit
.. //depot/projects/uart/dev/uart/uart_core.c#3 edit
.. //depot/projects/uart/dev/uart/uart_dev_ns8250.c#2 edit
.. //depot/projects/uart/dev/uart/uart_dev_sab82532.c#3 edit
.. //depot/projects/uart/dev/uart/uart_if.m#3 edit
.. //depot/projects/uart/dev/uart/uart_tty.c#2 edit
.. //depot/projects/uart/dev/uart/uart_tty.h#2 edit

Differences ...

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

@@ -29,17 +29,17 @@
 #ifndef _DEV_UART_BUS_H_
 #define _DEV_UART_BUS_H_
 
-/*
- * Interrupt sources (in priority order):
- * line - line errors (overrun, framing)
- * recv - received data
- * xmit - transmitter idle
- * ctrl - line- and modem signals
- */
-#define	UART_IPEND_LINE		0x01
-#define	UART_IPEND_RECV		0x02
-#define	UART_IPEND_XMIT		0x04
-#define	UART_IPEND_CTRL		0x08
+/* 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
+
+/* Received character status bits. */
+#define	UART_STAT_BREAK		0x1000
+#define	UART_STAT_OVERRUN	0x2000
+#define	UART_STAT_PARERR	0x4000
 
 /*
  * UART class & instance (=softc)
@@ -69,14 +69,28 @@
 	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. */
-	int		sc_hasfifo:1;	/* This UART has a FIFO. */
+	int		sc_hasfifo:1;	/* This UART has FIFOs. */
 	int		sc_leaving:1;	/* This UART is going away. */
+	int		sc_polled:1;	/* This UART has no interrupts. */
 
+	/* Receiver data. */
+	uint16_t	*sc_rxbuf;
+	int		sc_rxbufsz;
+	int		sc_rxput;
+	int		sc_rxget;
 	int		sc_rxfifosz;	/* Size of RX FIFO. */
+
+	/* Transmitter data. */
+	uint8_t		*sc_txbuf;
+	int		sc_txbufsz;
+	int		sc_txput;
+	int		sc_txget;
 	int		sc_txfifosz;	/* Size of TX FIFO. */
 
 	dev_t		sc_si;
+	void		*sc_softih;
 	struct tty	*sc_tty;
+	uint32_t	sc_ttypend;
 };
 
 extern devclass_t uart_devclass;
@@ -86,4 +100,17 @@
 int uart_bus_detach(device_t dev);
 int uart_bus_probe(device_t dev, int regshft, int rclk, int rid);
 
+static __inline int
+uart_rx_put(struct uart_softc *sc, int xc)
+{
+	int ptr;
+
+	ptr = (sc->sc_rxput + 1 < sc->sc_rxbufsz) ? sc->sc_rxput + 1 : 0;
+	if (ptr == sc->sc_rxget)
+		return (ENOSPC);
+	sc->sc_rxbuf[sc->sc_rxput] = xc;
+	sc->sc_rxput = ptr;
+	return (0);
+}
+
 #endif /* _DEV_UART_BUS_H_ */

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

@@ -32,11 +32,14 @@
 #include <sys/bus.h>
 #include <sys/conf.h>
 #include <sys/cons.h>
+#include <sys/interrupt.h>
 #include <sys/kernel.h>
 #include <sys/malloc.h>
 #include <sys/reboot.h>
 #include <machine/bus.h>
 #include <sys/rman.h>
+#include <sys/termios.h>
+#include <sys/tty.h>
 #include <machine/resource.h>
 
 #include <dev/uart/uart.h>
@@ -54,28 +57,87 @@
 
 MALLOC_DEFINE(M_UART, "UART", "UART driver");
 
-static int
-uart_intr_line(struct uart_softc *sc)
+/*
+ * A break condition has been detected. We treat the break condition as
+ * a special case that should not happen during normal operation. When
+ * the break condition is to be passed to higher levels in the form of
+ * a NUL character, we really want the break to be in the right place in
+ * the input stream. The overhead to achieve that is not in relation to
+ * the exceptional nature of the break condition, so we permit ourselves
+ * to be sloppy.
+ */
+static void
+uart_intr_break(struct uart_softc *sc)
+{
+#if defined(DDB) && defined(BREAK_TO_DEBUGGER)
+	breakpoint();
+#else
+	if (sc->sc_tty == NULL || sc->sc_tty->t_iflag & IGNBRK)
+		return;
+	if (uart_rx_put(sc, UART_STAT_BREAK))
+		sc->sc_rxbuf[sc->sc_rxput] |= UART_STAT_BREAK;
+	atomic_set_32(&sc->sc_ttypend, UART_IPEND_RXREADY);
+#endif
+}
+
+/*
+ * Handle a receiver overrun situation. We lost at least 1 byte in the
+ * input stream and it's our job to contain the situation. We grab as
+ * much of the data we can, but otherwise flush the receiver FIFO to
+ * create some breathing room. The net effect is that we avoid the
+ * overrun condition to happen for the next X characters, where X is
+ * related to the FIFO size at the cost of loosing data right away.
+ * So, instead of having multiple overrun interrupts in close proximity
+ * to each other and possibly pessimizing UART interrupt latency for
+ * other UARTs in a multiport configuration, we create a longer segment
+ * of missing characters by freeing up the FIFO.
+ * Each overrun condition is marked in the input buffer by a token. The
+ * token represents the loss of at least one, but possible more bytes in
+ * the input stream.
+ */
+static void
+uart_intr_overrun(struct uart_softc *sc)
 {
-	return (0);
+	UART_RECEIVE(sc);
+	UART_RXFLUSH(sc);
+	if (uart_rx_put(sc, UART_STAT_OVERRUN))
+		sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN;
+	atomic_set_32(&sc->sc_ttypend, UART_IPEND_RXREADY);
 }
 
-static int
-uart_intr_recv(struct uart_softc *sc)
+/*
+ * Received data ready.
+ */
+static void
+uart_intr_rxready(struct uart_softc *sc)
 {
-	return (0);
+	UART_RECEIVE(sc);
+	atomic_set_32(&sc->sc_ttypend, UART_IPEND_RXREADY);
 }
 
-static int
-uart_intr_xmit(struct uart_softc *sc)
+/*
+ * Line or modem status change (OOB signalling).
+ */
+static void
+uart_intr_sigchg(struct uart_softc *sc)
 {
-	return (0);
+	int sig;
+
+	sig = UART_GETSIG(sc);
+	/*
+	 * TODO: process the signals.
+	 */
 }
 
-static int
-uart_intr_ctrl(struct uart_softc *sc)
+/*
+ * The transmitter can accept more data.
+ */
+static void
+uart_intr_txidle(struct uart_softc *sc)
 {
-	return (0);
+	if (sc->sc_txget != sc->sc_txput)
+		UART_TRANSMIT(sc);
+	atomic_set_32(&sc->sc_ttypend, UART_IPEND_TXIDLE);
 }
 
 static void
@@ -84,48 +146,46 @@
 	struct uart_softc *sc = arg;
 	int ipend;
 
+	if (sc->sc_leaving)
+		return;
+
 	ipend = UART_IPEND(sc);
-	while (ipend != 0) {
-		if (ipend & UART_IPEND_LINE)
-			uart_intr_line(sc);
-		if (ipend & UART_IPEND_RECV)
-			uart_intr_recv(sc);
-		if (ipend & UART_IPEND_XMIT)
-			uart_intr_xmit(sc);
-		if (ipend & UART_IPEND_CTRL)
-			uart_intr_ctrl(sc);
-		ipend = UART_IPEND(sc);
-	}
+	if (ipend & UART_IPEND_OVERRUN)
+		uart_intr_overrun(sc);
+	if (ipend & UART_IPEND_BREAK)
+		uart_intr_break(sc);
+	if (ipend & UART_IPEND_RXREADY)
+		uart_intr_rxready(sc);
+	if (ipend & UART_IPEND_SIGCHG)
+		uart_intr_sigchg(sc);
+	if (ipend & UART_IPEND_TXIDLE)
+		uart_intr_txidle(sc);
+	if (sc->sc_ttypend != 0)
+		swi_sched(sc->sc_softih, 0);
 }
 
 int
 uart_bus_probe(device_t dev, int regshft, int rclk, int rid)
 {
-	struct uart_softc *sc;
+	struct uart_softc *sc, *sc0;
 	int error;
 
-	sc = device_get_softc(dev);
-	sc->sc_dev = dev;
-
 	/*
 	 * The sc_class field defines the type of UART we're going to work
-	 * with. Initialize the softc (=object/instance) so that we can use
-	 * the class methods. Initializing the softc also compiles the
-	 * class if not already compiled. Note that at this time the class
-	 * does not match the softc. The softc belongs to class uart_class
-	 * (the abstract base class), while the sc_class field points to
-	 * a derived class (e.g. ns8250_class). The object of the derived
-	 * class can be (and likely is) larger than the base class. We
-	 * therefore depend on kobj_init to not assume that the object is
-	 * in fact an instantiation of the class we give it. When we attach
-	 * the device, the assignment (device->driver) is definite and we'll
-	 * make sure the softc is replaced with the correct one. This means
-	 * that the UART_PROBE() method cannot use any of the class specific
-	 * data items. This is a bit annoying, because a driver may need to
-	 * do extensive probing to accurately set the device description and
-	 * it's a pain to have to do it again because we couldn't save the
-	 * results of the previous probing. This may need to be revisited.
+	 * with and thus the size of the softc. Replace the generic softc
+	 * with one that matches the UART and initialize it. Initialization
+	 * also compiles the class if not already compiled. We also set the
+	 * initial device description equal to the UART class name, unless
+	 * a description has already been set. This name can be overwritten
+	 * with a more specific description.
 	 */
+	sc0 = device_get_softc(dev);
+	sc = malloc(sc0->sc_class->size, M_UART, M_WAITOK|M_ZERO);
+	bcopy(sc0, sc, sizeof(*sc));
+	device_set_softc(dev, sc);
+	sc->sc_dev = dev;
+	if (device_get_desc(dev) == NULL)
+		device_set_desc(dev, sc->sc_class->name);
 	kobj_init((kobj_t)sc, (kobj_class_t)sc->sc_class);
 
 	/*
@@ -159,11 +219,8 @@
 	sc->sc_bas.rclk = (rclk == 0) ? sc->sc_class->uc_rclk : rclk;
 
 	error = UART_PROBE(sc);
-	if (error) {
-		bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid,
-		    sc->sc_rres);
-		return (error);
-	}
+	if (error)
+		goto out;
 
 	/*
 	 * Figure out if this UART is a console device or a debug port and
@@ -183,22 +240,17 @@
 
 	if (!sc->sc_console && !sc->sc_dbgport) {
 		error = UART_RESET(sc);
-		if (error) {
-			bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid,
-			    sc->sc_rres);
-			return (error);
-		}
+		if (error)
+			goto out;
 	}
 
 	error = UART_INITFIFO(sc);
-	if (error) {
-		bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid,
-		    sc->sc_rres);
-		return (error);
-	}
+	if (error)
+		goto out;
 
-	device_set_desc(dev, sc->sc_class->name);
 	error = UART_DESCRIBE(sc);
+
+ out:
 	bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid, sc->sc_rres);
 	return (error);
 }
@@ -243,12 +295,11 @@
 		}
 	}
 	if (sc->sc_ires == NULL) {
-		/*
-		 * XXX no interrupt resource. Force polled mode.
-		 */
+		/* XXX no interrupt resource. Force polled mode. */
+		sc->sc_polled = 1;
 	}
 
-	if (sc->sc_console || sc->sc_dbgport || sc->sc_fastintr) {
+	if (sc->sc_console || sc->sc_dbgport) {
 		sep = "";
 		device_print_prettyname(dev);
 		if (sc->sc_console) {
@@ -261,13 +312,30 @@
 			printf("%sdebug port", sep);
 			sep = ", ";
 		}
+		printf("\n");
+	}
+
+	if (bootverbose && (sc->sc_fastintr || sc->sc_polled)) {
+		sep = "";
+		device_print_prettyname(dev);
 		if (sc->sc_fastintr) {
 			printf("%sfast interrupt", sep);
 			sep = ", ";
 		}
+		if (sc->sc_polled) {
+			printf("%spolled mode", sep);
+			sep = ", ";
+		}
 		printf("\n");
 	}
 
+	sc->sc_rxbufsz = IBUFSIZ;
+	sc->sc_rxbuf = malloc(sc->sc_rxbufsz * sizeof(*sc->sc_rxbuf),
+	    M_UART, M_WAITOK);
+	sc->sc_txbufsz = OBUFSIZ;
+	sc->sc_txbuf = malloc(sc->sc_txbufsz * sizeof(*sc->sc_txbuf),
+	    M_UART, M_WAITOK);
+
 	uart_tty_attach(sc);
 
 	return (0);
@@ -279,13 +347,21 @@
 
 	sc = device_get_softc(dev);
 
+	sc->sc_leaving = 1;
+
 	uart_tty_detach(sc);
 
+	free(sc->sc_txbuf, M_UART);
+	free(sc->sc_rxbuf, M_UART);
+
 	if (sc->sc_ires != NULL) {
 		bus_teardown_intr(dev, sc->sc_ires, sc->sc_icookie);
 		bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid,
 		    sc->sc_ires);
 	}
 	bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid, sc->sc_rres);
+
+	UART_SHUTDOWN(sc);
+
 	return (0);
 }

==== //depot/projects/uart/dev/uart/uart_dev_ns8250.c#2 (text+ko) ====

@@ -253,15 +253,29 @@
 };
 
 static int ns8250_bus_describe(struct uart_softc *);
+static int ns8250_bus_getsig(struct uart_softc *);
 static int ns8250_bus_initfifo(struct uart_softc *);
+static int ns8250_bus_ipend(struct uart_softc *);
 static int ns8250_bus_probe(struct uart_softc *);
+static int ns8250_bus_receive(struct uart_softc *);
 static int ns8250_bus_reset(struct uart_softc *);
+static int ns8250_bus_rxflush(struct uart_softc *);
+static int ns8250_bus_shutdown(struct uart_softc *);
+static int ns8250_bus_transmit(struct uart_softc *);
+static int ns8250_bus_txflush(struct uart_softc *);
 
 static kobj_method_t ns8250_methods[] = {
 	KOBJMETHOD(uart_describe,	ns8250_bus_describe),
+	KOBJMETHOD(uart_getsig,		ns8250_bus_getsig),
 	KOBJMETHOD(uart_initfifo,	ns8250_bus_initfifo),
+	KOBJMETHOD(uart_ipend,		ns8250_bus_ipend),
 	KOBJMETHOD(uart_probe,		ns8250_bus_probe),
+	KOBJMETHOD(uart_receive,	ns8250_bus_receive),
 	KOBJMETHOD(uart_reset,		ns8250_bus_reset),
+	KOBJMETHOD(uart_rxflush,	ns8250_bus_rxflush),
+	KOBJMETHOD(uart_shutdown,	ns8250_bus_shutdown),
+	KOBJMETHOD(uart_transmit,	ns8250_bus_transmit),
+	KOBJMETHOD(uart_txflush,	ns8250_bus_txflush),
 	{ 0, 0 }
 };
 
@@ -313,6 +327,13 @@
 }
 
 static int
+ns8250_bus_getsig(struct uart_softc *sc)
+{
+
+	return (0);
+}
+
+static int
 ns8250_bus_initfifo(struct uart_softc *sc)
 {
 
@@ -320,6 +341,13 @@
 }
 
 static int
+ns8250_bus_ipend(struct uart_softc *sc)
+{
+
+	return (0);
+}
+
+static int
 ns8250_bus_probe(struct uart_softc *sc)
 {
 
@@ -327,9 +355,44 @@
 }
 
 static int
+ns8250_bus_receive(struct uart_softc *sc)
+{
+
+	return (0);
+}
+
+static int
 ns8250_bus_reset(struct uart_softc *sc)
 {
 
 	ns8250_init(&sc->sc_bas, 9600, 8, 1, UART_PARITY_NONE);
 	return (0);
 }
+
+static int
+ns8250_bus_rxflush(struct uart_softc *sc)
+{
+
+	return (0);
+}
+
+static int
+ns8250_bus_shutdown(struct uart_softc *sc)
+{
+
+	return (0);
+}
+
+static int
+ns8250_bus_transmit(struct uart_softc *sc)
+{
+
+	return (0);
+}
+
+static int
+ns8250_bus_txflush(struct uart_softc *sc)
+{
+
+	return (0);
+}

==== //depot/projects/uart/dev/uart/uart_dev_sab82532.c#3 (text+ko) ====

@@ -115,15 +115,29 @@
 };
 
 static int sab82532_bus_describe(struct uart_softc *);
+static int sab82532_bus_getsig(struct uart_softc *);
 static int sab82532_bus_initfifo(struct uart_softc *);
+static int sab82532_bus_ipend(struct uart_softc *);
 static int sab82532_bus_probe(struct uart_softc *);
+static int sab82532_bus_receive(struct uart_softc *);
 static int sab82532_bus_reset(struct uart_softc *);
+static int sab82532_bus_rxflush(struct uart_softc *);
+static int sab82532_bus_shutdown(struct uart_softc *);
+static int sab82532_bus_transmit(struct uart_softc *);
+static int sab82532_bus_txflush(struct uart_softc *);
 
 static kobj_method_t sab82532_methods[] = {
 	KOBJMETHOD(uart_describe,	sab82532_bus_describe),
+	KOBJMETHOD(uart_getsig,         sab82532_bus_getsig),
 	KOBJMETHOD(uart_initfifo,	sab82532_bus_initfifo),
+	KOBJMETHOD(uart_ipend,          sab82532_bus_ipend),
 	KOBJMETHOD(uart_probe,		sab82532_bus_probe),
+	KOBJMETHOD(uart_receive,        sab82532_bus_receive),
 	KOBJMETHOD(uart_reset,		sab82532_bus_reset),
+	KOBJMETHOD(uart_rxflush,        sab82532_bus_rxflush),
+	KOBJMETHOD(uart_shutdown,       sab82532_bus_shutdown),
+	KOBJMETHOD(uart_transmit,       sab82532_bus_transmit),
+	KOBJMETHOD(uart_txflush,        sab82532_bus_txflush),
 	{ 0, 0 }
 };
 
@@ -151,12 +165,19 @@
         default:		vstr = "v4?"; break;
 	}
 
-	snprintf(buf, sizeof(buf), "Siemens SAB 82532 %s (ch %s)", vstr, ch);
+	snprintf(buf, sizeof(buf), "SAB 82532 %s, channel %s", vstr, ch);
 	device_set_desc_copy(sc->sc_dev, buf);
 	return (0);
 }
 
 static int
+sab82532_bus_getsig(struct uart_softc *sc)
+{
+
+	return (0);
+}
+
+static int
 sab82532_bus_initfifo(struct uart_softc *sc)
 {
 
@@ -164,6 +185,13 @@
 }
 
 static int
+sab82532_bus_ipend(struct uart_softc *sc)
+{
+
+	return (0);
+}
+
+static int
 sab82532_bus_probe(struct uart_softc *sc)
 {
 
@@ -171,9 +199,44 @@
 }
 
 static int
+sab82532_bus_receive(struct uart_softc *sc)
+{
+
+	return (0);
+}
+
+static int
 sab82532_bus_reset(struct uart_softc *sc)
 {
 
 	sab82532_init(&sc->sc_bas, 9600, 8, 1, UART_PARITY_NONE);
 	return (0);
 }
+
+static int
+sab82532_bus_rxflush(struct uart_softc *sc)
+{
+
+	return (0);
+}
+
+static int
+sab82532_bus_shutdown(struct uart_softc *sc)
+{
+
+	return (0);
+}
+
+static int
+sab82532_bus_transmit(struct uart_softc *sc)
+{
+
+	return (0);
+}
+
+static int
+sab82532_bus_txflush(struct uart_softc *sc)
+{
+
+	return (0);
+}

==== //depot/projects/uart/dev/uart/uart_if.m#3 (text+ko) ====

@@ -34,7 +34,7 @@
 
 INTERFACE uart;
 
-# describe() - set the device description
+# describe() - set the device description.
 # This method is called after FIFOs are initialized and is used to set the
 # device description to match the actual hardware (as much as is possible).
 # The method is free to perform whatever UART programming is required to
@@ -44,7 +44,13 @@
 	struct uart_softc *this;
 };
 
-# initfifo() - detect and size FIFOs
+# getsig() - get line and modem signals.
+# XXX needs explanation.
+METHOD int getsig {
+	struct uart_softc *this;
+};
+
+# initfifo() - detect and size FIFOs.
 # This method is called after the UART is reset and is responsible for finding
 # out the size of the transmitter and receiver FIFOs. The method is allowed
 # to reprogram the UART, but should not permanently disrupt console or debug
@@ -53,7 +59,7 @@
 	struct uart_softc *this;
 };
 
-# ipend() - query UART for pending interrupts
+# ipend() - query UART for pending interrupts.
 # When an interrupt is signalled, the handler will call this method to find
 # out which of the interrupt sources needs attention. The handler will use
 # this information to dispatch service routines that deal with each of the
@@ -74,6 +80,13 @@
 	struct uart_softc *this;
 };
 
+# receive() - move data from the receive FIFO to the receive buffer.
+# This method is called to move received data to the receive buffer and
+# additionally should make sure the receive interrupt should be cleared.
+METHOD int receive {
+	struct uart_softc *this;
+};
+
 # reset() - program an initial state.
 # It is unspecified at this time what the initial state is and/or whether it
 # should be a state that is common for all supported UARTs. This method is
@@ -81,3 +94,27 @@
 METHOD int reset {
 	struct uart_softc *this;
 };
+
+# rxflush() - flush the receiver and receiver FIFO.
+# XXX needs explanation.
+METHOD int rxflush {
+	struct uart_softc *this;
+};
+
+# shutdown() - disable or inactivate UART.
+# XXX needs explanation.
+METHOD int shutdown {
+	struct uart_softc *this;
+};
+
+# transmit() - move data from the transmit buffer to the transmit FIFO.
+# XXX needs explanation.
+METHOD int transmit {
+	struct uart_softc *this;
+};
+
+# txflush() - flush the transmitter and transmitter FIFO.
+# XXX needs explanation.
+METHOD int txflush {
+	struct uart_softc *this;
+};

==== //depot/projects/uart/dev/uart/uart_tty.c#2 (text+ko) ====

@@ -36,6 +36,7 @@
 #include <machine/bus.h>
 #include <sys/bus.h>
 #include <sys/conf.h>
+#include <sys/interrupt.h>
 #include <sys/kobj.h>
 #include <sys/tty.h>
 
@@ -143,6 +144,15 @@
 	return (ENOTTY);
 }
 
+void
+uart_tty_intr(void *arg)
+{
+	struct uart_softc *sc = arg;
+
+	if (sc->sc_leaving)
+		return;
+}
+
 int
 uart_tty_attach(struct uart_softc *sc)
 {
@@ -158,6 +168,9 @@
 
 	tp->t_dev = sc->sc_si;
 
+	swi_add(&tty_ithd, uart_driver_name, uart_tty_intr, sc, SWI_TTY,
+	    INTR_TYPE_TTY, &sc->sc_softih);
+
 	return (0);
 }
 
@@ -165,6 +178,8 @@
 uart_tty_detach(struct uart_softc *sc)
 {
 
-	/* XXX */
+	ithread_remove_handler(sc->sc_softih);
+	destroy_dev(sc->sc_si);
+	/* ttyfree(sc->sc_tty); */
 	return (0);
 }

==== //depot/projects/uart/dev/uart/uart_tty.h#2 (text+ko) ====

@@ -33,5 +33,6 @@
 
 int uart_tty_attach(struct uart_softc *);
 int uart_tty_detach(struct uart_softc *);
+void uart_tty_intr(void *arg);
 
 #endif /* _DEV_UART_TTY_H_ */



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