PERFORCE change 34169 for review

Marcel Moolenaar marcel at FreeBSD.org
Mon Jul 7 13:19:18 PDT 2003


http://perforce.freebsd.org/chv.cgi?CH=34169

Change 34169 by marcel at marcel_nfs on 2003/07/07 13:19:04

	Simplify the UART hardware interface. Abandon creating methods
	with specific (implied) meaning and replace them with methods
	that have a 1-to-1 relation with probe(), attach() and detach().
	We call these methods the same. The point is that the set of
	probe(), reset(), initfifo() and describe() we had before had
	too much implied assumptions embedded in them. Now that we
	call a single probe(), the hardware driver has more control
	over probing (including disrupting console I/O).
	The same has been done for attach() and detach(), where detach()
	replaces shutdown().
	Likewise, rxflush() is merged with txflush() and is called flush().
	The flush() method takes a second argument identifying what to
	flush. This is how the tty code does it too.
	
	Implement ns8250::probe() as a proof of concept. The code has
	been brought over from sio/ng. And keep the 82532 driver in
	sync.
	
	This commit "leaks" uart_debug(). The function is either going
	away completely, or implemented differently. We definitely need
	tracing and debugging support, but I don't know yet in what form
	or shape.

Affected files ...

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

Differences ...

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

@@ -29,6 +29,13 @@
 #ifndef _DEV_UART_BUS_H_
 #define _DEV_UART_BUS_H_
 
+#include <sys/systm.h>
+#include <machine/stdarg.h>
+
+/* Flush targets. */
+#define	UART_FLUSH_RECEIVER	0x0001
+#define	UART_FLUSH_TRANSMITTER	0x0002
+
 /* Interrupt sources (in priority order). See also uart_core.c */
 #define	UART_IPEND_OVERRUN	0x0001
 #define	UART_IPEND_BREAK	0x0002
@@ -113,4 +120,17 @@
 	return (0);
 }
 
+static __inline void
+uart_debug(struct uart_softc *sc, const char *fmt, ...)
+{
+#if defined(UART_DEBUG) || 1
+	va_list ap;
+	va_start(ap, fmt);
+	if (sc != NULL)
+		device_print_prettyname(sc->sc_dev);
+	vprintf(fmt, ap);
+	va_end(ap);
+#endif
+}
+
 #endif /* _DEV_UART_BUS_H_ */

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

@@ -99,7 +99,7 @@
 uart_intr_overrun(struct uart_softc *sc)
 {
 	UART_RECEIVE(sc);
-	UART_RXFLUSH(sc);
+	UART_FLUSH(sc, UART_FLUSH_RECEIVER);
 	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);
@@ -177,23 +177,23 @@
 	 * 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.
+	 * with a more specific description later on.
 	 */
 	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);
+	kobj_init((kobj_t)sc, (kobj_class_t)sc->sc_class);
 	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);
 
 	/*
 	 * Allocate the register resource. We assume that all UARTs have
 	 * a single register window in either I/O port space or memory
 	 * mapped I/O space. Any UART that needs multiple windows will
-	 * consequently not be supported by this driver. We try I/O port
-	 * space first.
+	 * consequently not be supported by this driver as-is. We try I/O
+	 * port space first because that's the common case.
 	 */
 	sc->sc_rrid = rid;
 	sc->sc_rtype = SYS_RES_IOPORT;
@@ -209,24 +209,17 @@
 	}
 
 	/*
-	 * Fill in the bus access structure and perform a first level device
-	 * probe. The probe is non-destructive and can be used on console
-	 * devices and debug ports.
+	 * Fill in the bus access structure and compare this device with
+	 * a possible console device and/or a debug port. We set the flags
+	 * in the softc so that the hardware dependent probe can adjust
+	 * accordingly. In general, you don't want to permanently disrupt
+	 * console I/O.
 	 */
 	sc->sc_bas.bsh = rman_get_bushandle(sc->sc_rres);
 	sc->sc_bas.bst = rman_get_bustag(sc->sc_rres);
 	sc->sc_bas.regshft = regshft;
 	sc->sc_bas.rclk = (rclk == 0) ? sc->sc_class->uc_rclk : rclk;
 
-	error = UART_PROBE(sc);
-	if (error)
-		goto out;
-
-	/*
-	 * Figure out if this UART is a console device or a debug port and
-	 * if neither, reset it. We assume console devices and debug ports
-	 * are already in a working state, so there's no need to reset them.
-	 */
 	if (uart_cpu_eqres(&sc->sc_bas, &uart_console.bas)) {
 		sc->sc_console = 1;
 		/* XXX check if ops matches class. */
@@ -238,19 +231,7 @@
 	}
 #endif
 
-	if (!sc->sc_console && !sc->sc_dbgport) {
-		error = UART_RESET(sc);
-		if (error)
-			goto out;
-	}
-
-	error = UART_INITFIFO(sc);
-	if (error)
-		goto out;
-
-	error = UART_DESCRIBE(sc);
-
- out:
+	error = UART_PROBE(sc);
 	bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid, sc->sc_rres);
 	return (error);
 }
@@ -299,6 +280,17 @@
 		sc->sc_polled = 1;
 	}
 
+	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);
+
+	error = UART_ATTACH(sc);
+	if (error)
+		goto fail;
+
 	if (sc->sc_console || sc->sc_dbgport) {
 		sep = "";
 		device_print_prettyname(dev);
@@ -329,16 +321,26 @@
 		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);
+	error = uart_tty_attach(sc);
+	if (!error)
+		return (0);
+
+	sc->sc_leaving = 1;
+
+	UART_DETACH(sc);
+
+ fail:
+	free(sc->sc_txbuf, M_UART);
+	free(sc->sc_rxbuf, M_UART);
 
-	uart_tty_attach(sc);
+	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);
 
-	return (0);
+	return (error);
 }
 
 int uart_bus_detach(device_t dev)
@@ -351,6 +353,8 @@
 
 	uart_tty_detach(sc);
 
+	UART_DETACH(sc);
+
 	free(sc->sc_txbuf, M_UART);
 	free(sc->sc_rxbuf, M_UART);
 
@@ -361,7 +365,5 @@
 	}
 	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#3 (text+ko) ====

@@ -54,8 +54,8 @@
 	uart_setreg(bas, REG_LCR, lcr);
 	uart_barrier(bas);
 
-        /* 1/10th the time to transmit 1 character (estimate). */
-        return (16000000 * divisor / bas->rclk);
+	/* 1/10th the time to transmit 1 character (estimate). */
+	return (16000000 * divisor / bas->rclk);
 }
 
 static int
@@ -82,6 +82,52 @@
 	return (divisor);
 }
 
+static int
+ns8250_flush(struct uart_bas *bas, int what)
+{
+	int delay, limit;
+
+	delay = ns8250_delay(bas);
+
+	if (what & UART_FLUSH_TRANSMITTER) {
+		/*
+		 * Pick an arbitrary high limit to avoid getting stuck in
+		 * an infinite loop when the hardware is broken. Make the
+		 * limit high enough to handle large FIFOs.
+		 */
+		limit = 10*1024;
+		while ((uart_getreg(bas, REG_LSR) & LSR_TEMT) == 0 && --limit)
+			DELAY(delay);
+		if (limit == 0) {
+			uart_debug(NULL, "transmitter appears stuck... ");
+			return (EIO);
+		}
+	}
+
+	if (what & UART_FLUSH_RECEIVER) {
+		/*
+		 * Pick an arbitrary high limit to avoid getting stuck in
+		 * an infinite loop when the hardware is broken. Make the
+		 * limit high enough to handle large FIFOs and integrated
+		 * UARTs. The HP rx2600 for example has 3 UARTs on the
+		 * management board that tend to get a lot of data send
+		 * to it when the UART is first activated.
+		 */
+		limit=10*4096;
+		while ((uart_getreg(bas, REG_LSR) & LSR_RXRDY) && --limit) {
+			(void)uart_getreg(bas, REG_DATA);
+			uart_barrier(bas);
+			DELAY(delay << 2);
+		}
+		if (limit == 0) {
+			uart_debug(NULL, "receiver appears broken... ");
+			return (EIO);
+		}
+	}
+
+	return (0);
+}
+
 /*
  * Low-level UART interface.
  */
@@ -140,6 +186,8 @@
 	int divisor;
 	u_char iir, lcr;
 
+	uart_debug(NULL, "%s\n", __func__);
+
 	lcr = 0;
 	if (databits >= 8)
 		lcr |= LCR_8BITS;
@@ -188,7 +236,7 @@
 		if (iir == IIR_RLS)
 			(void)uart_getreg(bas, REG_LSR);
 		else if (iir == IIR_RXRDY || iir == IIR_RXTOUT)
-			(void)uart_getreg(bas, REG_RBR);
+			(void)uart_getreg(bas, REG_DATA);
 		else if (iir == IIR_MLSC)
 			(void)uart_getreg(bas, REG_MSR);
 		uart_barrier(bas);
@@ -217,7 +265,7 @@
 	limit = 20;
 	while ((uart_getreg(bas, REG_LSR) & LSR_THRE) == 0 && --limit)
 		DELAY(delay);
-	uart_setreg(bas, REG_THR, c);
+	uart_setreg(bas, REG_DATA, c);
 	limit = 40;
 	while ((uart_getreg(bas, REG_LSR) & LSR_TEMT) == 0 && --limit)
 		DELAY(delay);
@@ -228,7 +276,7 @@
 {
 
 	if (uart_getreg(bas, REG_LSR) & LSR_RXRDY)
-		return (uart_getreg(bas, REG_RBR));
+		return (uart_getreg(bas, REG_DATA));
 	return (-1);
 }
 
@@ -242,7 +290,7 @@
 
 	while ((uart_getreg(bas, REG_LSR) & LSR_RXRDY) == 0)
 		DELAY(delay);
-	return (uart_getreg(bas, REG_RBR));
+	return (uart_getreg(bas, REG_DATA));
 }
 
 /*
@@ -250,32 +298,28 @@
  */
 struct ns8250_softc {
 	struct uart_softc base;
+	uint8_t		fcr;
+	uint8_t		mcr;
 };
 
-static int ns8250_bus_describe(struct uart_softc *);
+static int ns8250_bus_attach(struct uart_softc *);
+static int ns8250_bus_detach(struct uart_softc *);
+static int ns8250_bus_flush(struct uart_softc *, int);
 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_attach,		ns8250_bus_attach),
+	KOBJMETHOD(uart_detach,		ns8250_bus_detach),
+	KOBJMETHOD(uart_flush,		ns8250_bus_flush),
 	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 }
 };
 
@@ -288,53 +332,28 @@
 };
 
 static int
-ns8250_bus_describe(struct uart_softc *sc)
+ns8250_bus_attach(struct uart_softc *sc)
 {
 
-	if (sc->sc_hasfifo) {
-		/*
-		 * NS16550 or higher. The minimum FIFO size is 16 bytes for
-		 * the NS16550. The ST16C650 has 32-byte FIFOs, the ST16750
-		 * has 64-byte FIFOs and the ST16950 has 128-byte FIFOs.
-		 */
-		switch (sc->sc_rxfifosz) {
-		case 16:
-			device_set_desc(sc->sc_dev, "16550 or compatible");
-			break;
-		case 32:
-			device_set_desc(sc->sc_dev, "16650 or compatible");
-			break;
-		case 64:
-			device_set_desc(sc->sc_dev, "16750 or compatible");
-			break;
-		case 128:
-			device_set_desc(sc->sc_dev, "16950 or compatible");
-			break;
-		default:
-			device_set_desc(sc->sc_dev,
-			    "Non-standard UART with FIFOs");
-			break;
-		}
-	} else {
-		/*
-		 * NS16450 or INS8250. We don't bother to differentiate
-		 * between them. They're too old to be interesting.
-		 */
-		device_set_desc(sc->sc_dev, "8250 or 16450 or compatible");
-	}
+	return (0);
+}
+
+static int
+ns8250_bus_detach(struct uart_softc *sc)
+{
 
 	return (0);
 }
 
 static int
-ns8250_bus_getsig(struct uart_softc *sc)
+ns8250_bus_flush(struct uart_softc *sc, int what)
 {
 
-	return (0);
+	return (ns8250_flush(&sc->sc_bas, what));
 }
 
 static int
-ns8250_bus_initfifo(struct uart_softc *sc)
+ns8250_bus_getsig(struct uart_softc *sc)
 {
 
 	return (0);
@@ -350,48 +369,144 @@
 static int
 ns8250_bus_probe(struct uart_softc *sc)
 {
+	struct ns8250_softc *ns8250 = (struct ns8250_softc *)sc;
+	struct uart_bas *bas;
+	int count, delay, error, limit;
+
+	uart_debug(sc, "%s\n", __func__);
 
-	return (ns8250_probe(&sc->sc_bas));
-}
+	bas = &sc->sc_bas;
+
+	error = ns8250_probe(bas);
+	if (error)
+		return (error);
+
+	ns8250->mcr = MCR_IENABLE;
+	if (!sc->sc_console && !sc->sc_dbgport) {
+		/* By using ns8250_init() we also set DTR and RTS. */
+		ns8250_init(bas, 9600, 8, 1, UART_PARITY_NONE);
+	} else
+		ns8250->mcr |= MCR_DTR | MCR_RTS;
+
+	error = ns8250_flush(bas, UART_FLUSH_TRANSMITTER);
+	if (error)
+		return (error);
+
+	/*
+	 * Set loopback mode. This avoids having garbage on the wire and
+	 * also allows us send and receive data. We set DTR and RTS to
+	 * avoid the possibility that automatic flow-control prevents
+	 * any data from being sent. We clear IENABLE to avoid raising
+	 * interrupts.
+	 */
+	uart_setreg(bas, REG_MCR, MCR_LOOPBACK | MCR_DTR | MCR_RTS);
+	uart_barrier(bas);
+
+	/*
+	 * Enable FIFOs. And check that the UART has them. If not, we're
+	 * done. Otherwise we set DMA mode with the highest trigger level
+	 * so that we can determine the FIFO size. Since this is the first
+	 * time we enable the FIFOs, we reset them.
+	 */
+	uart_setreg(bas, REG_FCR, FCR_ENABLE);
+	uart_barrier(bas);
+	sc->sc_hasfifo = (uart_getreg(bas, REG_IIR) & IIR_FIFO_MASK) ? 1 : 0;
+	if (!sc->sc_hasfifo) {
+		/*
+		 * NS16450 or INS8250. We don't bother to differentiate
+		 * between them. They're too old to be interesting.
+		 */
+		uart_setreg(bas, REG_MCR, ns8250->mcr);
+		uart_barrier(bas);
+		device_set_desc(sc->sc_dev, "8250 or 16450 or compatible");
+		return (0);
+	}
+
+	uart_setreg(bas, REG_FCR, FCR_ENABLE | FCR_DMA_MODE | FCR_RX_HIGH |
+	    FCR_XMT_RST | FCR_RCV_RST);
+	uart_barrier(bas);
+
+	count = 0;
+	delay = ns8250_delay(bas);
+
+	/* We have FIFOs. Flush the transmitter and receiver. */
+	error = ns8250_flush(bas, UART_FLUSH_RECEIVER|UART_FLUSH_TRANSMITTER);
+	if (error) {
+		uart_setreg(bas, REG_MCR, ns8250->mcr);
+		uart_setreg(bas, REG_FCR, 0);
+		uart_barrier(bas);
+		goto describe;
+	}
 
-static int
-ns8250_bus_receive(struct uart_softc *sc)
-{
+	uart_setreg(bas, REG_IER, IER_ERXRDY);
+	uart_barrier(bas);
 
-	return (0);
-}
+	/*
+	 * We should have a sufficiently clean "pipe" to determine the
+	 * size of the FIFOs. We send as much characters as is reasonable
+	 * and wait for the the RX interrupt to be asserted, counting the
+	 * characters as we send them. Based on that count we know the
+	 * FIFO size.
+	 */
+	while ((uart_getreg(bas, REG_IIR) & IIR_RXRDY) == 0 && count < 1030) {
+		uart_setreg(bas, REG_DATA, 0);
+		uart_barrier(bas);
+		count++;
 
-static int
-ns8250_bus_reset(struct uart_softc *sc)
-{
+		limit = 30;
+		while ((uart_getreg(bas, REG_LSR) & LSR_TEMT) == 0 && --limit)
+			DELAY(delay);
+		if (limit == 0) {
+			uart_setreg(bas, REG_IER, 0);
+			uart_setreg(bas, REG_MCR, ns8250->mcr);
+			uart_setreg(bas, REG_FCR, 0);
+			uart_barrier(bas);
+			count = 0;
+			goto describe;
+		}
+	}
 
-	ns8250_init(&sc->sc_bas, 9600, 8, 1, UART_PARITY_NONE);
-	return (0);
-}
+	uart_setreg(bas, REG_IER, 0);
+	uart_setreg(bas, REG_MCR, ns8250->mcr);
 
-static int
-ns8250_bus_rxflush(struct uart_softc *sc)
-{
+	/* Reset FIFOs. */
+	ns8250->fcr = FCR_ENABLE;
+	uart_setreg(bas, REG_FCR, ns8250->fcr | FCR_XMT_RST | FCR_RCV_RST);
+	uart_barrier(bas);
 
-	return (0);
-}
+ describe:
+	if (count >= 14 && count < 16) {
+		sc->sc_rxfifosz = 16;
+		device_set_desc(sc->sc_dev, "16550 or compatible");
+	} else if (count >= 28 && count < 32) {
+		sc->sc_rxfifosz = 32;
+		device_set_desc(sc->sc_dev, "16650 or compatible");
+	} else if (count >= 56 && count < 64) {
+		sc->sc_rxfifosz = 64;
+		device_set_desc(sc->sc_dev, "16750 or compatible");
+	} else if (count >= 112 && count < 128) {
+		sc->sc_rxfifosz = 128;
+		device_set_desc(sc->sc_dev, "16950 or compatible");
+	} else {
+		sc->sc_rxfifosz = 1;
+		device_set_desc(sc->sc_dev,
+		    "Non-standard ns8250 class UART with FIFOs");
+	}
 
-static int
-ns8250_bus_shutdown(struct uart_softc *sc)
-{
+	sc->sc_txfifosz = sc->sc_rxfifosz;
 
 	return (0);
 }
 
 static int
-ns8250_bus_transmit(struct uart_softc *sc)
+ns8250_bus_receive(struct uart_softc *sc)
 {
 
 	return (0);
 }
 
 static int
-ns8250_bus_txflush(struct uart_softc *sc)
+ns8250_bus_transmit(struct uart_softc *sc)
 {
 
 	return (0);

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

@@ -114,30 +114,24 @@
 	struct uart_softc base;
 };
 
-static int sab82532_bus_describe(struct uart_softc *);
+static int sab82532_bus_attach(struct uart_softc *);
+static int sab82532_bus_detach(struct uart_softc *);
+static int sab82532_bus_flush(struct uart_softc *, int);
 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_attach,		sab82532_bus_attach),
+	KOBJMETHOD(uart_detach,		sab82532_bus_detach),
+	KOBJMETHOD(uart_flush,		sab82532_bus_flush),
 	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 }
 };
 
@@ -150,78 +144,71 @@
 };
 
 static int
-sab82532_bus_describe(struct uart_softc *sc)
+sab82532_bus_attach(struct uart_softc *sc)
 {
-	char buf[80];
-	const char *ch, *vstr;
-
-	/* Assume the address range is naturally aligned. */
-	ch = ((sc->sc_bas.bsh & 0x40) == 0) ? "A" : "B";
-
-	switch (uart_getreg(&sc->sc_bas, SAB_VSTR) & SAB_VSTR_VMASK) {
-	case SAB_VSTR_V_1:	vstr = "v1"; break;
-	case SAB_VSTR_V_2:	vstr = "v2"; break;
-	case SAB_VSTR_V_32:	vstr = "v3.2"; break;
-        default:		vstr = "v4?"; break;
-	}
 
-	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)
+sab82532_bus_detach(struct uart_softc *sc)
 {
 
 	return (0);
 }
 
 static int
-sab82532_bus_initfifo(struct uart_softc *sc)
+sab82532_bus_flush(struct uart_softc *sc, int what)
 {
 
 	return (0);
 }
 
 static int
-sab82532_bus_ipend(struct uart_softc *sc)
+sab82532_bus_getsig(struct uart_softc *sc)
 {
 
 	return (0);
 }
 
 static int
-sab82532_bus_probe(struct uart_softc *sc)
+sab82532_bus_ipend(struct uart_softc *sc)
 {
 
-	return (sab82532_probe(&sc->sc_bas));
+	return (0);
 }
 
 static int
-sab82532_bus_receive(struct uart_softc *sc)
+sab82532_bus_probe(struct uart_softc *sc)
 {
+	char buf[80];
+	const char *ch, *vstr;
+	int error;
 
-	return (0);
-}
+	error = sab82532_probe(&sc->sc_bas);
+	if (error)
+		return (error);
 
-static int
-sab82532_bus_reset(struct uart_softc *sc)
-{
+	if (!sc->sc_console && !sc->sc_dbgport)
+		sab82532_init(&sc->sc_bas, 9600, 8, 1, UART_PARITY_NONE);
 
-	sab82532_init(&sc->sc_bas, 9600, 8, 1, UART_PARITY_NONE);
-	return (0);
-}
+	/* Assume the address range is naturally aligned. */
+	ch = ((sc->sc_bas.bsh & 0x40) == 0) ? "A" : "B";
 
-static int
-sab82532_bus_rxflush(struct uart_softc *sc)
-{
+	switch (uart_getreg(&sc->sc_bas, SAB_VSTR) & SAB_VSTR_VMASK) {
+	case SAB_VSTR_V_1:	vstr = "v1"; break;
+	case SAB_VSTR_V_2:	vstr = "v2"; break;
+	case SAB_VSTR_V_32:	vstr = "v3.2"; break;
+        default:		vstr = "v4?"; break;
+	}
 
+	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_shutdown(struct uart_softc *sc)
+sab82532_bus_receive(struct uart_softc *sc)
 {
 
 	return (0);
@@ -233,10 +220,3 @@
 
 	return (0);
 }
-
-static int
-sab82532_bus_txflush(struct uart_softc *sc)
-{
-
-	return (0);
-}

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

@@ -34,28 +34,28 @@
 
 INTERFACE uart;
 
-# 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
-# obtain the information it needs, but should not permanently disrupt console
-# or debug port operation.
-METHOD int describe {
+# attach()
+# XXX needs explanation.
+METHOD int attach {
+	struct uart_softc *this;
+};
+
+# detach()
+# XXX needs explanation.
+METHOD int detach {
 	struct uart_softc *this;
 };
 
-# getsig() - get line and modem signals.
+# flush()
 # XXX needs explanation.
-METHOD int getsig {
+METHOD int flush {
 	struct uart_softc *this;
+	int what;
 };
 
-# 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
-# port operation.
-METHOD int initfifo {
+# getsig() - get line and modem signals.
+# XXX needs explanation.
+METHOD int getsig {
 	struct uart_softc *this;
 };
 
@@ -72,10 +72,8 @@
 	struct uart_softc *this;
 }
 
-# probe() - first level device probing.
-# The intend of probe() is to perform a non-destructive probe that's simple
-# in nature and does not (in theory) program the device in order to find out
-# more about it. This method is used on console devices and debug ports.
+# probe()
+# XXX needs explanation.
 METHOD int probe {
 	struct uart_softc *this;
 };
@@ -87,34 +85,8 @@
 	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
-# not used on console devices and debug ports. More details will follow...
-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#3 (text+ko) ====

@@ -162,7 +162,8 @@
 	sc->sc_tty = tp;
 
 	sc->sc_si = make_dev(&uart_cdevsw, device_get_unit(sc->sc_dev),
-	    UID_ROOT, GID_WHEEL, 0600, "%s", device_get_desc(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;
 


More information about the p4-projects mailing list