Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 24 Dec 2002 01:13:00 -0800 (PST)
From:      Marcel Moolenaar <marcel@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 22700 for review
Message-ID:  <200212240913.gBO9D0up023337@repoman.freebsd.org>

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

Change 22700 by marcel@marcel_nfs on 2002/12/24 01:12:53

	o  Initialize the FIFOs at the end of sioprobe. Set loopback
	   prior to enabling the FIFOs so that we don't send garbage
	   and clear the RHR after resetting the FIFOs. With loopback
	   enabled we should be able to determine the size of the FIFO.
	   This we don't do yet. We assume a regular 16 byte FIFO for
	   now.
	o  Move UART identification after FIFO initialization in
	   sioprobe. Only set the device description if it hasn't been
	   set yet. This allows bus specific front-end code to give
	   a more detailed or a more relevant description. A generic
	   ACPI defined UART will now yield:
		sio0: <16550 or compatible> port 0x3f8-0x3ff irq 4 on acpi0
	   Recognize the newer 16650 and 16750 based on the FIFO size.
	   We avoid fiddling with the SPR when we know we have a FIFO.
	   This avoids potential problems with multi-port cards. The
	   fiddling is only needed to differentiate between the INS8250
	   and the NS16450 and both are not current devices.
	o  Don't reinitialize the FIFOs when we open the device. The
	   code appears to be broken and unnecessary and was probably
	   added to work around some weirdness. Keep it, but wrap it
	   inside #if 0 / #endif. 

Affected files ...

.. //depot/projects/ia64/sys/dev/sio/sio.c#26 edit
.. //depot/projects/ia64/sys/dev/sio/siovar.h#12 edit

Differences ...

==== //depot/projects/ia64/sys/dev/sio/sio.c#26 (text+ko) ====

@@ -263,6 +263,104 @@
 	    0, 0, sysctl_machdep_comdefaultrate, "I", "");
 /* TUNABLE_INT("machdep.conspeed", &comdefaultrate); */
 
+/*
+ * Initialize FIFOs. We cannot simple enable the FIFOs because that may cause
+ * garbage to appear on the wire (non-empty transmit FIFO) or garbage to be
+ * received (non-empty receive FIFO). The former is prevented by enabling
+ * loopback prior to enabling the FIFOs. The latter is prevented by ignoring
+ * any data in the RHR after we have reset the FIFOs.
+ */
+static void
+sioinitfifo(struct com_s *sc)
+{
+
+	sio_setreg(sc, com_mcr, sc->reg_mcr | MCR_LOOPBACK);
+	/* XXX barrier */
+	sio_setreg(sc, com_fcr, FCR_ENABLE);
+	/* XXX barrier */
+	sio_setreg(sc, com_fcr, FCR_ENABLE | FCR_RCV_RST | FCR_XMT_RST);
+	/* XXX barrier */
+	DELAY(100);
+	sc->reg_fcr = 0;
+	sc->hasfifo = (sio_getreg(sc, com_iir) & IIR_FIFO_MASK) ? 1 : 0;
+	if (sc->hasfifo) {
+		while (sio_getreg(sc, com_lsr) & LSR_RXRDY) {
+			(void)sio_getreg(sc, com_data);
+			/* XXX barrier */
+		}
+		sc->reg_fcr = FCR_ENABLE | FCR_RX_HIGH;
+		sio_setreg(sc, com_mcr, sc->reg_fcr);
+		/* XXX barrier */
+
+		sc->fifosize = 16;		/* Minimal FIFO size. */
+		/*
+		 * XXX count the number of characters we can send before
+		 * we have a receive interrupt. This tells us how large
+		 * the FIFOs are.
+		 */
+	}
+	sio_setreg(sc, com_mcr, sc->reg_mcr);
+	/* XXX barrier */
+}
+
+static void
+siodescribe(device_t dev, struct com_s *sc)
+{
+	int has_spr;
+	u_char spr;
+
+	if (sc->hasfifo) {
+		/*
+		 * NS16550 or higher. The minimum FIFO size is 16 bytes for
+		 * the NS16550. The ST16C650 has 32 bytes FIFOs and the
+		 * NS16750 has 64 bytes FIFOs.
+		 */
+		switch (sc->fifosize) {
+		case 16:
+			/*
+			 * XXX Should we try to see if we have a broken
+			 * 16550 or a fixed 16550A?
+			 */
+			device_set_desc(dev, "16550 or compatible");
+			break;
+		case 32:
+			/*
+			 * XXX Should we check that features like automatic
+			 * flow control exist?
+			 */
+			device_set_desc(dev, "16650 or compatible");
+			break;
+		case 64:
+			/*
+			 * XXX Should we check that features like automatic
+			 * flow control exist?
+			 */
+			device_set_desc(dev, "16750 or compatible");
+			break;
+		default:
+			/* XXX Probably not right. */
+			device_set_desc(dev, "16550 with non-standard FIFO");
+			break;
+		}
+	} else {
+		/*
+		 * NS16450 or lower. Use the Scratch Pad Register (SPR) to
+		 * differentiate the NS16450 from the INS8250.
+		 */
+		spr = sio_getreg(sc, com_scr);
+		sio_setreg(sc, com_scr, ~spr);
+		/* XXX barrier */
+		has_spr = (sio_getreg(sc, com_scr) == ~spr) ? 1 : 0;
+		/* XXX barrier */
+		sio_setreg(sc, com_scr, spr);
+		/* XXX barrier */
+		if (!has_spr)
+			device_set_desc(dev, "8250 or compatible");
+		else
+			device_set_desc(dev, "16450 or compatible");
+	}
+}
+
 u_int
 siodivisor(u_long rclk, u_long speed)
 {
@@ -313,6 +411,8 @@
 
 	/* XXX we can do more. */
 
+	sio_setreg(sc, com_ier, 0);
+	/* XXX barrier */
 	sio_setreg(sc, com_lcr, lcr);
 	/* XXX barrier */
 	return (0);
@@ -377,13 +477,27 @@
 
 	com = (struct com_s *)device_get_softc(dev);
 
-	/* Check if we're probing the console. */
+	/* Check if we're probing what could be the console. */
 	if (com->bst == sio_console.bst && com->bsh == sio_console.bsh) {
 		com = &sio_console;
 		device_set_softc(dev, com);
-		return (0);
+	}
+
+	if (com->consdev == NULL) {
+		/* Perform rudimentary sanity checking. */
+		if (sioprobe1(com))
+			return (ENXIO);
+
+		if (com->rclk == 0)
+			com->rclk = DEFAULT_RCLK;
 	}
 
+	/* Initialize the FIFOs. */
+	sioinitfifo(com);
+
+	if (device_get_desc(dev) == NULL)
+		siodescribe(dev, com);
+
 	flags = device_get_flags(dev);
 
 	if (COM_LLCONSOLE(flags)) {
@@ -391,16 +505,6 @@
 		return (ENXIO);
 	}
 
-	/* Perform rudimentary sanity checking. */
-	if (sioprobe1(com))
-		return (ENXIO);
-
-	if (com->rclk == 0)
-		com->rclk = DEFAULT_RCLK;
-
-	sio_setreg(com, com_ier, 0);
-	/* XXX barrier */
-
 	return (0);
 }
 
@@ -440,7 +544,6 @@
 	com->dtr_wait = 3 * hz;
 	com->loses_outints = COM_LOSESOUTINTS(flags) != 0;
 	com->no_irq = bus_get_resource(dev, SYS_RES_IRQ, 0, NULL, NULL) != 0;
-	com->tx_fifo_size = 1;
 	com->obufs[0].l_head = com->obuf1;
 	com->obufs[1].l_head = com->obuf2;
 
@@ -478,80 +581,8 @@
 	termioschars(&com->it_in);
 	com->it_out = com->it_in;
 
-	/* attempt to determine UART type */
-	device_printf(dev, "type ");
-
-	if (!COM_IIR_TXRDYBUG(flags) && !COM_NOSCR(flags)) {
-		u_char	scr;
-		u_char	scr1;
-		u_char	scr2;
-
-		scr = sio_getreg(com, com_scr);
-		/* XXX barrier */
-		sio_setreg(com, com_scr, 0xa5);
-		/* XXX barrier */
-		scr1 = sio_getreg(com, com_scr);
-		/* XXX barrier */
-		sio_setreg(com, com_scr, 0x5a);
-		/* XXX barrier */
-		scr2 = sio_getreg(com, com_scr);
-		/* XXX barrier */
-		sio_setreg(com, com_scr, scr);
-		/* XXX barrier */
-		if (scr1 != 0xa5 || scr2 != 0x5a) {
-			printf("8250");
-			goto determined_type;
-		}
-	}
-
-	sio_setreg(com, com_fcr, FCR_ENABLE | FCR_RX_HIGH);
-	/* XXX barrier with SYNC semantics */
-	DELAY(100);
-
-	com->st16650a = 0;
-	switch (sio_getreg(com, com_iir) & IIR_FIFO_MASK) {
-	case FCR_RX_LOW:
-		printf("16450");
-		break;
-	case FCR_RX_MEDL:
-		printf("16450?");
-		break;
-	case FCR_RX_MEDH:
-		printf("16550?");
-		break;
-	case FCR_RX_HIGH:
-		if (COM_NOFIFO(flags)) {
-			printf("16550A fifo disabled");
-		} else {
-			com->hasfifo = TRUE;
-			if (COM_ST16650A(flags)) {
-				com->st16650a = 1;
-				com->tx_fifo_size = 32;
-				printf("ST16650A");
-			} else {
-				com->tx_fifo_size = COM_FIFOSIZE(flags);
-				printf("16550A");
-			}
-		}
-		if (!com->st16650a) {
-			if (!com->tx_fifo_size)
-				com->tx_fifo_size = 16;
-			else
-				printf("lookalike with %d bytes FIFO",
-				    com->tx_fifo_size);
-		}
-
-		break;
-	}
-	
-	sio_setreg(com, com_fcr, 0);
-determined_type: ;
-
 	if (com->consdev != NULL)
-		printf(", console");
-	if (COM_IIR_TXRDYBUG(flags))
-		printf(" with a bogus IIR_TXRDY register");
-	printf("\n");
+		device_printf(dev, "console\n");
 
 	if (sio_fast_ih == NULL) {
 		swi_add(&tty_ithd, "tty:sio", siopoll, NULL, SWI_TTY, 0,
@@ -697,6 +728,7 @@
 		--com->wopeners;
 		if (error != 0)
 			goto out;
+#if 0
 		/*
 		 * XXX we should goto open_top if comparam() slept.
 		 */
@@ -740,6 +772,7 @@
 				goto out;
 			}
 		}
+#endif
 
 		mtx_lock_spin(&sio_lock);
 		(void) sio_getreg(com, com_lsr);
@@ -1291,12 +1324,12 @@
 		if (line_status & LSR_TXRDY
 		    && com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) {
 			ioptr = com->obufq.l_head;
-			if (com->tx_fifo_size > 1 && com->unit != siotsunit) {
+			if (com->hasfifo && com->unit != siotsunit) {
 				u_int	ocount;
 
 				ocount = com->obufq.l_tail - ioptr;
-				if (ocount > com->tx_fifo_size)
-					ocount = com->tx_fifo_size;
+				if (ocount > com->fifosize)
+					ocount = com->fifosize;
 				com->bytes_out += ocount;
 				do
 					sio_setreg(com, com_data, *ioptr++);

==== //depot/projects/ia64/sys/dev/sio/siovar.h#12 (text+ko) ====

@@ -83,6 +83,8 @@
 	bus_space_handle_t bsh;
 	u_long		rclk;			/* Receiver clock (bin 9) */
 	u_int		regshft;		/* Interleaved multi-port. */
+	u_int		hasfifo:1;
+	u_int		fifosize;
 	u_short		reg_dl;			/* Copy of DL. */
 	u_char		reg_fcr;		/* Copy of FCR. */
 	u_char		reg_lcr;		/* Copy of LCR. */
@@ -93,7 +95,6 @@
 	u_char	state;		/* miscellaneous flag bits */
 	bool_t  active_out;	/* nonzero if the callout device is open */
 	u_char	extra_state;	/* more flag bits, separate for order trick */
-	bool_t	hasfifo;	/* nonzero for 16550 UARTs */
 	bool_t	st16650a;	/* Is a Startech 16650A or RTS/CTS compat */
 	bool_t	loses_outints;	/* nonzero if device loses output interrupts */
 	bool_t	no_irq;		/* nonzero if irq is not attached */
@@ -101,7 +102,6 @@
 	bool_t	poll;		/* nonzero if polling is required */
 	bool_t	poll_output;	/* nonzero if polling for output is required */
 	int	dtr_wait;	/* time to hold DTR down on close (* 1/hz) */
-	u_int	tx_fifo_size;
 	u_int	wopeners;	/* # processes waiting for DCD in open() */
 
 	/*

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe p4-projects" in the body of the message




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