Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 15 Dec 2002 16:27:39 -0800 (PST)
From:      Marcel Moolenaar <marcel@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 22362 for review
Message-ID:  <200212160027.gBG0Rd7V041052@repoman.freebsd.org>

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

Change 22362 by marcel@marcel_nfs on 2002/12/15 16:27:12

	This too starts to look like a NextGen project:
	o  Remove inclusion of <machine/sio_pio.h>,
	o  Reorganize struct com_s so that I can see what I've touched
	   and/or used in new or modified code,
	o  Introduce regshft to allow interleaved multi-IO cards.
	   Shamelessly taken from Linux. Not used ATM,
	o  Remove inclusion of <dev/ic/ns16550.h>. The register names
	   are inconsistent and the comments are wrong. Instead, add
	   register names to sioreg.h,
	o  Add sioprobe1() to do some non-destructive checking to make
	   sure we have something at the given address and that it has
	   a high chance of actually being an UART. Used by siocnprobe()
	   and can (should) be used by sioprobe() as well.
	o  Flesh-out struct consdata to include regshft, data, stop and
	   parity. We get that from the HCDP table so we'd better use
	   it. This will probably grow in the future,
	o  Rewrite sio_machdep.c so that it's easier to add alternatives
	   to the HCDP table. We can use the ACPI defined SPCR table
	   and even plain old hints. Fix a bug where we were testing
	   if the HCDP table address was non-NULL after making the
	   address virtual. The latter makes it a tautology.
	
	We now have a serial console on the HP box. This was mostly
	not working because of the inclusion of bus_pio.h, but we
	had (and have) some nasty TR mapping issues as well.
	
	The removal of the pio include also helped the probed Diva
	(multi-IO board), but I haven't tried it actually...
	
	There's one gotcha: We never find the UART we use as the
	console, so we never have a device_t for it. Currently
	cp->cn_dev is explicitly set to NULL so that we segfault
	when we try to go multi-user. There are a couple of ways
	to approach this problem:
	o  Allow cn_dev to be NULL and ignore the consdev when we
	   try to open /dev/console, but this may cause the situation
	   when there's no consdev left,
	o  Fake a device_t, like we do for syscons. This seems to
	   be the safest solution.
	More on this subject later...

Affected files ...

.. //depot/projects/ia64/sys/dev/sio/sio.c#21 edit
.. //depot/projects/ia64/sys/dev/sio/sio_cons.c#3 edit
.. //depot/projects/ia64/sys/dev/sio/sioreg.h#5 edit
.. //depot/projects/ia64/sys/dev/sio/siovar.h#7 edit
.. //depot/projects/ia64/sys/ia64/ia64/sio_machdep.c#3 edit

Differences ...

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

@@ -64,7 +64,6 @@
 #include <sys/sysctl.h>
 #include <sys/syslog.h>
 #include <sys/tty.h>
-#include <machine/bus_pio.h>
 #include <machine/bus.h>
 #include <sys/rman.h>
 #include <sys/timepps.h>
@@ -81,7 +80,6 @@
 #ifdef COM_ESP
 #include <dev/ic/esp.h>
 #endif
-#include <dev/ic/ns16550.h>
 
 #define	LOTS_OF_EVENTS	64	/* helps separate urgent events from input */
 
@@ -216,13 +214,15 @@
 	/* kqfilter */	ttykqfilter,
 };
 
-int	comconsole = -1;
-static	volatile speed_t	comdefaultrate = CONSPEED;
-static	u_long			comdefaultrclk = DEFAULT_RCLK;
+volatile speed_t comdefaultrate = CONSPEED;
+
+u_long comdefaultrclk = DEFAULT_RCLK;
 SYSCTL_ULONG(_machdep, OID_AUTO, conrclk, CTLFLAG_RW, &comdefaultrclk, 0, "");
-static	speed_t			gdbdefaultrate = GDBSPEED;
-SYSCTL_UINT(_machdep, OID_AUTO, gdbspeed, CTLFLAG_RW,
-	    &gdbdefaultrate, GDBSPEED, "");
+
+static speed_t gdbdefaultrate = GDBSPEED;
+SYSCTL_ULONG(_machdep, OID_AUTO, gdbspeed, CTLFLAG_RW, &gdbdefaultrate,
+    GDBSPEED, "");
+
 static	u_int	com_events;	/* input chars + weighted output completions */
 static	void	*sio_slow_ih;
 static	void	*sio_fast_ih;
@@ -265,13 +265,10 @@
 
 	comdefaultrate = newspeed;
 
-	if (comconsole < 0)		/* serial console not selected? */
+	com = &sio_console;
+	if (com->consdev == NULL)
 		return (0);
 
-	com = com_addr(comconsole);
-	if (com == NULL)
-		return (ENXIO);
-
 	/*
 	 * set the initial and lock rates for /dev/ttydXX and /dev/cuaXX
 	 * (note, the lock rates really are boolean -- if non-zero, disallow
@@ -300,8 +297,66 @@
 	    0, 0, sysctl_machdep_comdefaultrate, "I", "");
 /* TUNABLE_INT("machdep.conspeed", &comdefaultrate); */
 
-#define SET_FLAG(dev, bit) device_set_flags(dev, device_get_flags(dev) | (bit))
-#define CLR_FLAG(dev, bit) device_set_flags(dev, device_get_flags(dev) & ~(bit))
+u_int
+siodivisor(u_long rclk, u_long speed)
+{
+	long	actual_speed;
+	u_int	divisor;
+	int	error;
+
+	if (speed == 0 || speed > (ULONG_MAX - 1) / 8)
+		return (0);
+	divisor = (rclk / (8UL * speed) + 1) / 2;
+	if (divisor == 0 || divisor >= 65536)
+		return (0);
+	actual_speed = rclk / (16UL * divisor);
+
+	/* 10 times error in percent: */
+	error = ((actual_speed - (long)speed) * 2000 / (long)speed + 1) / 2;
+
+	/* 3.0% maximum error tolerance: */
+	if (error < -30 || error > 30)
+		return (0);
+
+	return (divisor);
+}
+
+/*
+ * Do some non-destructive (for this device that is) tests
+ * to make sure we have something that looks like an UART.
+ * 
+ */
+int sioprobe1(struct com_s *sc)
+{
+	u_char lcr, val;
+
+	lcr = sio_getreg(sc, com_lcr);
+	sio_setreg(sc, com_lcr, lcr & ~LCR_DLAB);
+
+	/* Check known 0 bits that don't depend on DLAB. */
+	val = sio_getreg(sc, com_iir);
+	if (val & 0x30)
+		goto fail;
+	val = sio_getreg(sc, com_mcr);
+	if (val & 0xe0)
+		goto fail;
+
+	/* Check known 0 bits that depend on ~DLAB. */
+	val = sio_getreg(sc, com_ier);
+	if (val & 0xf0)
+		goto fail;
+
+	/* XXX we can do more. */
+
+	sio_setreg(sc, com_lcr, lcr);
+	/* XXX barrier */
+	return (0);
+
+ fail:
+	sio_setreg(sc, com_lcr, lcr);
+	/* XXX barrier */
+	return (ENXIO);
+}
 
 /*
  *	Unload the driver and clear the table.
@@ -379,25 +434,35 @@
 	if (!port)
 		return (ENXIO);
 
-	/* XXX - Grab static struct setup by siocnprobe. */
-	com = malloc(sizeof(*com), M_DEVBUF, M_NOWAIT | M_ZERO);
-	if (com == NULL)
-		return (ENOMEM);
+	if (rman_get_bustag(port) != sio_console.bst ||
+	    rman_get_bushandle(port) != sio_console.bsh) {
+		com = malloc(sizeof(*com), M_DEVBUF, M_NOWAIT | M_ZERO);
+		if (com == NULL)
+			return (ENOMEM);
+		bzero(com, sizeof *com);
+		com->bst = rman_get_bustag(port);
+		com->bsh = rman_get_bushandle(port);
+		if (rclk == 0)
+			rclk = DEFAULT_RCLK;
+		com->rclk = rclk;
+	} else
+		com = &sio_console;
+
 	device_set_softc(dev, com);
-	com->bst = rman_get_bustag(port);
-	com->bsh = rman_get_bushandle(port);
-	if (rclk == 0)
-		rclk = DEFAULT_RCLK;
-	com->rclk = rclk;
 
 	while (sio_inited != 2)
 		if (atomic_cmpset_int(&sio_inited, 0, 1)) {
 			mtx_init(&sio_lock, sio_driver_name, NULL,
-			    (comconsole != -1) ?
+			    (sio_console.consdev != NULL) ?
 			    MTX_SPIN | MTX_QUIET : MTX_SPIN);
 			atomic_store_rel_int(&sio_inited, 2);
 		}
 
+	if (com->consdev != NULL) {
+		bus_release_resource(dev, space, rid, port);
+		return (0);
+	}
+
 	if (COM_LLCONSOLE(flags)) {
 		printf("sio%d: reserved for low-level i/o\n",
 		       device_get_unit(dev));
@@ -464,14 +529,12 @@
 	 * XXX what about the UART bug avoided by waiting in comparam()?
 	 * We don't want to to wait long enough to drain at 2 bps.
 	 */
-	if (!com->is_console) {
-		sio_setreg(com, com_cfcr, CFCR_DLAB | CFCR_8BITS);
-		divisor = siodivisor(rclk, SIO_TEST_SPEED);
-		sio_setreg(com, com_dlbl, divisor & 0xff);
-		sio_setreg(com, com_dlbh, divisor >> 8);
-		sio_setreg(com, com_cfcr, CFCR_8BITS);
-		DELAY((16 + 1) * 1000000 / (SIO_TEST_SPEED / 10));
-	}
+	sio_setreg(com, com_lcr, LCR_DLAB | LCR_8BITS);
+	divisor = siodivisor(rclk, SIO_TEST_SPEED);
+	sio_setreg(com, com_dlbl, divisor & 0xff);
+	sio_setreg(com, com_dlbh, divisor >> 8);
+	sio_setreg(com, com_lcr, LCR_8BITS);
+	DELAY((16 + 1) * 1000000 / (SIO_TEST_SPEED / 10));
 
 	/*
 	 * Enable the interrupt gate and disable device interupts.  This
@@ -518,13 +581,13 @@
 	 */
 /* EXTRA DELAY? */
 	sio_setreg(com, com_mcr, mcr_image);
- 
+
 	/*
 	 * It seems my Xircom CBEM56G Cardbus modem wants to be reset
 	 * to 8 bits *again*, or else probe test 0 will fail.
 	 * gwk@sgi.com, 4/19/2001
 	 */
-	sio_setreg(com, com_cfcr, CFCR_8BITS);
+	sio_setreg(com, com_lcr, LCR_8BITS);
 
 	/*
 	 * Some pcmcia cards have the "TXRDY bug", so we check everyone
@@ -554,11 +617,9 @@
 			CLR_FLAG(dev, COM_C_IIR_TXRDYBUG);
 		}
 		sio_setreg(com, com_ier, 0);
-		sio_setreg(com, com_cfcr, CFCR_8BITS);
+		sio_setreg(com, com_lcr, LCR_8BITS);
 		mtx_unlock_spin(&sio_lock);
 		bus_release_resource(dev, space, rid, port);
-		if (com->is_console)
-			result = 0;
 		if (result != 0) {
 			device_set_softc(dev, NULL);
 			free(com, M_DEVBUF);
@@ -575,7 +636,7 @@
 	 *	o the interrupt goes away when the IIR in the UART is read.
 	 */
 /* EXTRA DELAY? */
-	failures[0] = sio_getreg(com, com_cfcr) - CFCR_8BITS;
+	failures[0] = sio_getreg(com, com_lcr) - LCR_8BITS;
 	failures[1] = sio_getreg(com, com_ier) - IER_ETXRDY;
 	failures[2] = sio_getreg(com, com_mcr) - mcr_image;
 	DELAY(10000);		/* Some internal modems need this time */
@@ -593,7 +654,7 @@
 	 * and gives a (masked) interrupt as soon as the gate is closed.)
 	 */
 	sio_setreg(com, com_ier, 0);
-	sio_setreg(com, com_cfcr, CFCR_8BITS);	/* dummy to avoid bus echo */
+	sio_setreg(com, com_lcr, LCR_8BITS);	/* dummy to avoid bus echo */
 	failures[7] = sio_getreg(com, com_ier);
 	DELAY(1000);		/* XXX */
 	failures[9] = (sio_getreg(com, com_iir) & IIR_IMASK) - IIR_NOPEND;
@@ -615,9 +676,8 @@
 			}
 			break;
 		}
+
 	bus_release_resource(dev, space, rid, port);
-	if (com->is_console)
-		result = 0;
 	if (result != 0) {
 		device_set_softc(dev, NULL);
 		free(com, M_DEVBUF);
@@ -722,8 +782,8 @@
 		sio_numunits = unit + 1;
 	/*
 	 * sioprobe() has initialized the device registers as follows:
-	 *	o cfcr = CFCR_8BITS.
-	 *	  It is most important that CFCR_DLAB is off, so that the
+	 *	o cfcr = LCR_8BITS.
+	 *	  It is most important that LCR_DLAB is off, so that the
 	 *	  data port is not hidden when we enable interrupts.
 	 *	o ier = 0.
 	 *	  Interrupts are only enabled when the line is open.
@@ -732,13 +792,12 @@
 	 *	  Keeping MCR_DTR and MCR_RTS off might stop the external
 	 *	  device from sending before we are ready.
 	 */
-	bzero(com, sizeof *com);
 	com->unit = unit;
 	com->ioportres = port;
 	com->ioportspace = space;
 	com->bst = rman_get_bustag(port);
 	com->bsh = rman_get_bushandle(port);
-	com->cfcr_image = CFCR_8BITS;
+	com->cfcr_image = LCR_8BITS;
 	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;
@@ -762,7 +821,7 @@
 	com->it_in.c_oflag = 0;
 	com->it_in.c_cflag = TTYDEF_CFLAG;
 	com->it_in.c_lflag = 0;
-	if (unit == comconsole) {
+	if (com->consdev != NULL) {
 		com->it_in.c_iflag = TTYDEF_IFLAG;
 		com->it_in.c_oflag = TTYDEF_OFLAG;
 		com->it_in.c_cflag = TTYDEF_CFLAG | CLOCAL;
@@ -779,7 +838,7 @@
 		 * Leave i/o resources allocated if this is a `cn'-level
 		 * console, so that other devices can't snarf them.
 		 */
-		if (!com->is_console)
+		if (com->consdev == NULL)
 			bus_release_resource(dev, space, rid, port);
 		return (ENOMEM);
 	}
@@ -790,7 +849,6 @@
 	/* attempt to determine UART type */
 	printf("sio%d: type", unit);
 
-
 	if (!COM_ISMULTIPORT(flags) &&
 	    !COM_IIR_TXRDYBUG(flags) && !COM_NOSCR(flags)) {
 		u_char	scr;
@@ -808,20 +866,20 @@
 			goto determined_type;
 		}
 	}
-	sio_setreg(com, com_fifo, FIFO_ENABLE | FIFO_RX_HIGH);
+	sio_setreg(com, com_fcr, FCR_ENABLE | FCR_RX_HIGH);
 	DELAY(100);
 	com->st16650a = 0;
 	switch (sio_getreg(com, com_iir) & IIR_FIFO_MASK) {
-	case FIFO_RX_LOW:
+	case FCR_RX_LOW:
 		printf(" 16450");
 		break;
-	case FIFO_RX_MEDL:
+	case FCR_RX_MEDL:
 		printf(" 16450?");
 		break;
-	case FIFO_RX_MEDH:
+	case FCR_RX_MEDH:
 		printf(" 16550?");
 		break;
-	case FIFO_RX_HIGH:
+	case FCR_RX_HIGH:
 		if (COM_NOFIFO(flags)) {
 			printf(" 16550A fifo disabled");
 		} else {
@@ -878,7 +936,7 @@
 		outb(com->esp_port + ESP_CMD2, LOBYTE(512));
 	}
 #endif /* COM_ESP */
-	sio_setreg(com, com_fifo, 0);
+	sio_setreg(com, com_fcr, 0);
 determined_type: ;
 
 #ifdef COM_MULTIPORT
@@ -896,7 +954,7 @@
 		    SYS_RES_IRQ, 0, NULL, NULL) != 0);
 	 }
 #endif /* COM_MULTIPORT */
-	if (unit == comconsole)
+	if (com->consdev != NULL)
 		printf(", console");
 	if (COM_IIR_TXRDYBUG(flags))
 		printf(" with a bogus IIR_TXRDY register");
@@ -949,7 +1007,7 @@
 		 * Enable interrupts for early break-to-debugger support
 		 * on the console.
 		 */
-		if (ret == 0 && unit == comconsole)
+		if (ret == 0 && com->consdev != NULL)
 			sio_setreg(com, com_ier, IER_ERXRDY | IER_ERLS |
 			    IER_EMSC);
 #endif
@@ -1063,9 +1121,9 @@
 			 * input.
 			 */
 			for (i = 0; i < 500; i++) {
-				sio_setreg(com, com_fifo,
-					   FIFO_RCV_RST | FIFO_XMT_RST
-					   | com->fifo_image);
+				sio_setreg(com, com_fcr,
+					   FCR_RCV_RST | FCR_XMT_RST
+					   | com->reg_fcr);
 				/*
 				 * XXX the delays are for superstitious
 				 * historical reasons.  It must be less than
@@ -1080,7 +1138,7 @@
 				DELAY(50);
 				if (!(sio_getreg(com, com_lsr) & LSR_RXRDY))
 					break;
-				sio_setreg(com, com_fifo, 0);
+				sio_setreg(com, com_fcr, 0);
 				DELAY(50);
 				(void) sio_getreg(com, com_data);
 			}
@@ -1198,7 +1256,7 @@
 	com->do_timestamp = FALSE;
 	com->do_dcd_timestamp = FALSE;
 	com->pps.ppsparam.mode = 0;
-	sio_setreg(com, com_cfcr, com->cfcr_image &= ~CFCR_SBREAK);
+	sio_setreg(com, com_lcr, com->cfcr_image &= ~LCR_SBREAK);
 	tp = com->tp;
 
 #if defined(DDB) && (defined(BREAK_TO_DEBUGGER) || \
@@ -1208,7 +1266,7 @@
 	 * console. This allows us to detect break-to-debugger events
 	 * while the console device is closed.
 	 */
-	if (com->unit != comconsole)
+	if (com->consdev == NULL)
 #endif
 	{
 		sio_setreg(com, com_ier, 0);
@@ -1237,7 +1295,7 @@
 		 * reboots.  Some BIOSes fail to detect 16550s when the
 		 * fifos are enabled.
 		 */
-		sio_setreg(com, com_fifo, 0);
+		sio_setreg(com, com_fcr, 0);
 	}
 	com->active_out = FALSE;
 	wakeup(&com->active_out);
@@ -1287,7 +1345,7 @@
 	 * is not the console.  In that situation we don't need/want the X
 	 * server taking over the console.
 	 */
-	if (constty != NULL && unit == comconsole)
+	if (constty != NULL && com->consdev != NULL)
 		constty = NULL;
 	return ((*linesw[com->tp->t_line].l_write)(com->tp, uio, flag));
 }
@@ -1322,30 +1380,6 @@
 	splx(s);
 }
 
-u_int
-siodivisor(u_long rclk, u_long speed)
-{
-	long	actual_speed;
-	u_int	divisor;
-	int	error;
-
-	if (speed == 0 || speed > (ULONG_MAX - 1) / 8)
-		return (0);
-	divisor = (rclk / (8UL * speed) + 1) / 2;
-	if (divisor == 0 || divisor >= 65536)
-		return (0);
-	actual_speed = rclk / (16UL * divisor);
-
-	/* 10 times error in percent: */
-	error = ((actual_speed - (long)speed) * 2000 / (long)speed + 1) / 2;
-
-	/* 3.0% maximum error tolerance: */
-	if (error < -30 || error > 30)
-		return (0);
-
-	return (divisor);
-}
-
 static void
 siodtrwakeup(chan)
 	void	*chan;
@@ -1575,7 +1609,7 @@
 #define	KEY_CR		13	/* CR '\r' */
 #define	KEY_TILDE	126	/* ~ */
 
-			if (com->unit == comconsole) {
+			if (com->consdev != NULL) {
 				static int brk_state1 = 0, brk_state2 = 0;
 				if (recv_data == KEY_CR) {
 					brk_state1 = recv_data;
@@ -1612,7 +1646,7 @@
 				 */
 				if (line_status & LSR_BI) {
 #if defined(DDB) && defined(BREAK_TO_DEBUGGER)
-					if (com->unit == comconsole) {
+					if (com->consdev != NULL) {
 						breakpoint();
 						goto cont;
 					}
@@ -1856,10 +1890,10 @@
 	}
 	switch (cmd) {
 	case TIOCSBRK:
-		sio_setreg(com, com_cfcr, com->cfcr_image |= CFCR_SBREAK);
+		sio_setreg(com, com_lcr, com->cfcr_image |= LCR_SBREAK);
 		break;
 	case TIOCCBRK:
-		sio_setreg(com, com_cfcr, com->cfcr_image &= ~CFCR_SBREAK);
+		sio_setreg(com, com_lcr, com->cfcr_image &= ~LCR_SBREAK);
 		break;
 	case TIOCSDTR:
 		(void)commctl(com, TIOCM_DTR, DMBIS);
@@ -2029,25 +2063,25 @@
 	cflag = t->c_cflag;
 	switch (cflag & CSIZE) {
 	case CS5:
-		cfcr = CFCR_5BITS;
+		cfcr = LCR_5BITS;
 		break;
 	case CS6:
-		cfcr = CFCR_6BITS;
+		cfcr = LCR_6BITS;
 		break;
 	case CS7:
-		cfcr = CFCR_7BITS;
+		cfcr = LCR_7BITS;
 		break;
 	default:
-		cfcr = CFCR_8BITS;
+		cfcr = LCR_8BITS;
 		break;
 	}
 	if (cflag & PARENB) {
-		cfcr |= CFCR_PENAB;
+		cfcr |= LCR_PENAB;
 		if (!(cflag & PARODD))
-			cfcr |= CFCR_PEVEN;
+			cfcr |= LCR_PEVEN;
 	}
 	if (cflag & CSTOPB)
-		cfcr |= CFCR_STOPB;
+		cfcr |= LCR_STOPB;
 
 	if (com->hasfifo && divisor != 0) {
 		/*
@@ -2063,9 +2097,9 @@
 		 * interrupt disablement times in other parts of the system,
 		 * without producing silo overflow errors.
 		 */
-		com->fifo_image = com->unit == siotsunit ? 0
+		com->reg_fcr = com->unit == siotsunit ? 0
 				  : t->c_ospeed <= 4800
-				  ? FIFO_ENABLE : FIFO_ENABLE | FIFO_RX_MEDH;
+				  ? FCR_ENABLE : FCR_ENABLE | FCR_RX_MEDH;
 #ifdef COM_ESP
 		/*
 		 * The Hayes ESP card needs the fifo DMA mode bit set
@@ -2073,9 +2107,9 @@
 		 * for each character received.
 		 */
 		if (com->esp)
-			com->fifo_image |= FIFO_DMA_MODE;
+			com->reg_fcr |= FCR_DMA_MODE;
 #endif
-		sio_setreg(com, com_fifo, com->fifo_image);
+		sio_setreg(com, com_fcr, com->reg_fcr);
 	}
 
 	/*
@@ -2086,7 +2120,7 @@
 	(void) siosetwater(com, t->c_ispeed);
 
 	if (divisor != 0) {
-		sio_setreg(com, com_cfcr, cfcr | CFCR_DLAB);
+		sio_setreg(com, com_lcr, cfcr | LCR_DLAB);
 		/*
 		 * Only set the divisor registers if they would change,
 		 * since on some 16550 incompatibles (UMC8669F), setting
@@ -2101,16 +2135,16 @@
 			sio_setreg(com, com_dlbh, dlbh);
 	}
 
-	sio_setreg(com, com_cfcr, com->cfcr_image = cfcr);
+	sio_setreg(com, com_lcr, com->cfcr_image = cfcr);
 
 	if (!(tp->t_state & TS_TTSTOP))
 		com->state |= CS_TTGO;
 
 	if (cflag & CRTS_IFLOW) {
 		if (com->st16650a) {
-			sio_setreg(com, com_cfcr, 0xbf);
-			sio_setreg(com, com_fifo,
-				   sio_getreg(com, com_fifo) | 0x40);
+			sio_setreg(com, com_lcr, 0xbf);
+			sio_setreg(com, com_fcr,
+				   sio_getreg(com, com_fcr) | 0x40);
 		}
 		com->state |= CS_RTS_IFLOW;
 		/*
@@ -2127,9 +2161,9 @@
 		 */
 		sio_setreg(com, com_mcr, com->mcr_image |= MCR_RTS);
 		if (com->st16650a) {
-			sio_setreg(com, com_cfcr, 0xbf);
-			sio_setreg(com, com_fifo,
-				   sio_getreg(com, com_fifo) & ~0x40);
+			sio_setreg(com, com_lcr, 0xbf);
+			sio_setreg(com, com_fcr,
+				   sio_getreg(com, com_fcr) & ~0x40);
 		}
 	}
 
@@ -2146,19 +2180,19 @@
 		if (!(com->last_modem_status & MSR_CTS))
 			com->state &= ~CS_ODEVREADY;
 		if (com->st16650a) {
-			sio_setreg(com, com_cfcr, 0xbf);
-			sio_setreg(com, com_fifo,
-				   sio_getreg(com, com_fifo) | 0x80);
+			sio_setreg(com, com_lcr, 0xbf);
+			sio_setreg(com, com_fcr,
+				   sio_getreg(com, com_fcr) | 0x80);
 		}
 	} else {
 		if (com->st16650a) {
-			sio_setreg(com, com_cfcr, 0xbf);
-			sio_setreg(com, com_fifo,
-				   sio_getreg(com, com_fifo) & ~0x80);
+			sio_setreg(com, com_lcr, 0xbf);
+			sio_setreg(com, com_fcr,
+				   sio_getreg(com, com_fcr) & ~0x80);
 		}
 	}
 
-	sio_setreg(com, com_cfcr, com->cfcr_image);
+	sio_setreg(com, com_lcr, com->cfcr_image);
 
 	/* XXX shouldn't call functions while intrs are disabled. */
 	disc_optim(tp, t, com);
@@ -2357,8 +2391,8 @@
 		    /* XXX avoid h/w bug. */
 		    if (!com->esp)
 #endif
-			sio_setreg(com, com_fifo,
-				   FIFO_XMT_RST | com->fifo_image);
+			sio_setreg(com, com_fcr,
+				   FCR_XMT_RST | com->reg_fcr);
 		com->obufs[0].l_queued = FALSE;
 		com->obufs[1].l_queued = FALSE;
 		if (com->state & CS_ODONE)
@@ -2372,8 +2406,8 @@
 		    /* XXX avoid h/w bug. */
 		    if (!com->esp)
 #endif
-			sio_setreg(com, com_fifo,
-				   FIFO_RCV_RST | com->fifo_image);
+			sio_setreg(com, com_fcr,
+				   FCR_RCV_RST | com->reg_fcr);
 		com_events -= (com->iptr - com->ibuf);
 		com->iptr = com->ibuf;
 	}

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

@@ -54,7 +54,6 @@
 #include <sys/sysctl.h>
 #include <sys/syslog.h>
 #include <sys/tty.h>
-#include <machine/bus_pio.h>
 #include <machine/bus.h>
 #include <sys/rman.h>
 #include <sys/timepps.h>
@@ -68,8 +67,6 @@
 #include <dev/sio/sioreg.h>
 #include <dev/sio/siovar.h>
 
-#include <dev/ic/ns16550.h>
-
 #include <sys/cons.h>
 
 /*
@@ -84,81 +81,137 @@
 static cn_term_t siocnterm;
 static cn_getc_t siocngetc;
 static cn_checkc_t siocncheckc;
-static cn_putc_t siocnputc;
+cn_putc_t siocnputc;
 
 CONS_DRIVER(sio, siocnprobe, siocninit, siocnterm, siocngetc, siocncheckc,
 	siocnputc, NULL);
 
+/* Sloppily translate databits, stopbits and parity to LCR register bits. */
+static u_char
+siocnlcr(struct sio_consdata *cd)
+{
+	u_char lcr;
+
+	lcr = 0;
+
+	if (cd->databits >= 8)
+		lcr |= LCR_8BITS;
+	else if (cd->databits == 7)
+		lcr |= LCR_7BITS;
+	else if (cd->databits == 6)
+		lcr |= LCR_6BITS;
+	else
+		lcr |= LCR_5BITS;
+
+	if (cd->stopbits > 1)
+		lcr |= LCR_STOPB;
+
+	/* XXX set parity */
+
+	return (lcr);
+}
+
 static void
 siocnprobe(struct consdev *cp)
 {
 	struct sio_consdata cd;
 	u_int divisor;
-	u_char cfcr;
+	u_char lcr;
 
 	bzero(&sio_console, sizeof(sio_console));
 
+	cp->cn_dev = NULL;		/* How do we know. */
 	cp->cn_pri = CN_DEAD;
 
 	if (sio_get_console(&cd) != 0)
 		return;
 
-	sio_console.bst = cd.type;
-	sio_console.bsh = cd.addr;
-	sio_console.rclk = cd.rclk;
+	/* Minimum fields needed for rudimentary checks. */
+	sio_console.bst = cd.bst;
+	sio_console.bsh = cd.bsh;
+	sio_console.regshft = cd.regshft;
+
+	if (sioprobe1(&sio_console))
+		return;
+
+	sio_console.rclk = (cd.rclk != 0) ? cd.rclk : DEFAULT_RCLK;
 
-	cfcr = sio_getreg(&sio_console, com_cfcr);
-	sio_setreg(&sio_console, com_cfcr, CFCR_DLAB | cfcr);
+	/* Set DL and LCR. */
+	lcr = siocnlcr(&cd);
+	sio_setreg(&sio_console, com_lcr, lcr | LCR_DLAB);
+	/* XXX barrier */
 	if (cd.baud != 0) {
 		divisor = siodivisor(cd.rclk, cd.baud);
-		sio_setreg(&sio_console, com_dlbl, divisor & 0xff);
-		sio_setreg(&sio_console, com_dlbh, divisor >> 8);
-	} else {
-		divisor = sio_getreg(&sio_console, com_dlbh);
-		divisor = (divisor << 8) | sio_getreg(&sio_console, com_dlbl);
-		/* XXX there should be more sanity checking. */
-		cd.baud = (divisor != 0)
-		    ? cd.rclk / (16UL * divisor) : CONSPEED;
-	}
-	sio_setreg(&sio_console, com_cfcr, cfcr);
+		sio_setdreg(&sio_console, com_dl, divisor);
+	} else
+		divisor = sio_getdreg(&sio_console, com_dl);
+	/* XXX barrier */
+	sio_setreg(&sio_console, com_lcr, lcr);
+	/* XXX barrier */
 
-	cp->cn_dev = makedev(28, 0);
 	cp->cn_pri = (boothowto & RB_SERIAL) ? CN_REMOTE : CN_NORMAL;
 }
 
 static void
 siocninit(struct consdev *cp)
 {
-	u_char mcr;
+	u_char fcr, iir;
 
+	/* Disable all interrupt sources. */
 	sio_setreg(&sio_console, com_ier, 0);
-	sio_setreg(&sio_console, com_cfcr, CFCR_8BITS);
-	mcr = sio_getreg(&sio_console, com_mcr);
-	sio_setreg(&sio_console, com_mcr,
-	    (mcr & MCR_IENABLE) | MCR_DTR | MCR_RTS);
-	(void)sio_getreg(&sio_console, com_iir);
-	sio_console.is_console = 1;
+	/* XXX barrier */
+
+	/* Set FCR. */
+	fcr = FCR_RX_MEDH | FCR_ENABLE;
+	sio_setreg(&sio_console, com_fcr, fcr);
+	/* XXX barrier */
+	sio_setreg(&sio_console, com_fcr, fcr | FCR_RCV_RST | FCR_XMT_RST);
+	/* XXX barrier */
+	sio_console.reg_fcr = fcr;
+
+	/* Set MCR. */
+	sio_setreg(&sio_console, com_mcr, MCR_IENABLE | MCR_DTR);
+	/* XXX barrier */
+
+	/*
+	 * Clear pending interrupts. THRE is cleared by reading IIR. Data
+	 * that may have been received gets lost here.
+	 */
+	iir = sio_getreg(&sio_console, com_iir);
+	while ((iir & IIR_NOPEND) == 0) {
+		iir &= IIR_IMASK;
+		if (iir == IIR_RLS)
+			sio_getreg(&sio_console, com_lsr);
+		else if (iir == IIR_RXRDY || iir == IIR_RXTOUT)
+			sio_getreg(&sio_console, com_rbr);
+		else if (iir == IIR_MLSC)
+			sio_getreg(&sio_console, com_msr);
+		/* XXX barrier */
+		iir = sio_getreg(&sio_console, com_iir);
+	}
+	/* XXX barrier */
+
+	/* It's official... */
+	sio_console.consdev = cp;
 }
 
 static void
 siocnterm(struct consdev *cp)
 {
 
-	sio_console.is_console = 0;
+	/* XXX - What to do here? */
 }
 
-static void
+void
 siocnputc(dev_t dev, int c)
 {
 	int s, to;
 
 	s = spltty();
 	to = 100000;
-	while ((sio_getreg(&sio_console, com_lsr) & (LSR_TSRE | LSR_TXRDY))
-	    != (LSR_TSRE | LSR_TXRDY) && --to != 0)
+	while ((sio_getreg(&sio_console, com_lsr) & LSR_TSRE) == 0 && --to)
 		;
 	sio_setreg(&sio_console, com_data, c);
-	/* XXX bus_space_barrier */
 	splx(s);
 }
 

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

@@ -37,6 +37,22 @@
 /* Receiver clock frequency for "standard" pc serial ports. */
 #define	DEFAULT_RCLK	1843200
 
+/* Register names. */
+#define	com_data	0		/* Data. */
+#define	com_rbr		com_data	/* Receiver Buffer Reg. (R). */
+#define	com_thr		com_data	/* Transmitter Holding Reg. (W). */
+#define	com_dlbl	0		/* Divisor Latch (LSB). */
+#define	com_dlbh	1		/* Divisor Latch (MSB). */
+#define	com_dl		com_dlbl	/* Divisor Latch (16-bit I/O). */
+#define	com_ier		1		/* Interrupt Enable Reg. */
+#define	com_iir		2		/* Interrupt Identification Reg. (R) */
+#define	com_fcr		2		/* FIFO Control Reg. (W) */
+#define	com_lcr		3		/* Line Control Reg. */
+#define	com_mcr		4		/* MODEM Control Reg. */
+#define	com_lsr		5		/* Line Status Reg. */
+#define	com_msr		6		/* MODEM Status Reg. */
+#define	com_scr		7		/* Scratch Reg. (16450 and up). */
+
 /* interrupt enable register */
 #define	IER_ERXRDY	0x1
 #define	IER_ETXRDY	0x2
@@ -54,28 +70,28 @@
 #define	IIR_FIFO_MASK	0xc0	/* set if FIFOs are enabled */
 
 /* fifo control register */
-#define	FIFO_ENABLE	0x01
-#define	FIFO_RCV_RST	0x02
-#define	FIFO_XMT_RST	0x04
-#define	FIFO_DMA_MODE	0x08
-#define	FIFO_RX_LOW	0x00
-#define	FIFO_RX_MEDL	0x40
-#define	FIFO_RX_MEDH	0x80
-#define	FIFO_RX_HIGH	0xc0
+#define	FCR_ENABLE	0x01
+#define	FCR_RCV_RST	0x02
+#define	FCR_XMT_RST	0x04
+#define	FCR_DMA_MODE	0x08
+#define	FCR_RX_LOW	0x00
+#define	FCR_RX_MEDL	0x40
+#define	FCR_RX_MEDH	0x80
+#define	FCR_RX_HIGH	0xc0
 
 /* character format control register */
-#define	CFCR_DLAB	0x80
-#define	CFCR_SBREAK	0x40
-#define	CFCR_PZERO	0x30
-#define	CFCR_PONE	0x20
-#define	CFCR_PEVEN	0x10
-#define	CFCR_PODD	0x00
-#define	CFCR_PENAB	0x08
-#define	CFCR_STOPB	0x04
-#define	CFCR_8BITS	0x03
-#define	CFCR_7BITS	0x02
-#define	CFCR_6BITS	0x01
-#define	CFCR_5BITS	0x00
+#define	LCR_DLAB	0x80
+#define	LCR_SBREAK	0x40
+#define	LCR_PZERO	0x30
+#define	LCR_PONE	0x20
+#define	LCR_PEVEN	0x10
+#define	LCR_PODD	0x00
+#define	LCR_PENAB	0x08
+#define	LCR_STOPB	0x04
+#define	LCR_8BITS	0x03
+#define	LCR_7BITS	0x02
+#define	LCR_6BITS	0x01
+#define	LCR_5BITS	0x00
 
 /* modem control register */
 #define	MCR_LOOPBACK	0x10
@@ -117,16 +133,16 @@
 #endif
 
 /* speed to initialize to during chip tests */
-#define SIO_TEST_SPEED	9600
+#define	SIO_TEST_SPEED	9600
 
 /* default serial console speed if not set with sysctl or probed from boot */
 #ifndef CONSPEED
-#define CONSPEED 9600
+#define	CONSPEED	9600
 #endif
 
 /* default serial gdb speed if not set with sysctl or probed from boot */
 #ifndef GDBSPEED
-#define GDBSPEED CONSPEED
+#define	GDBSPEED	CONSPEED
 #endif
 
 #define	IO_COMSIZE	8		/* 8250, 16x50 com controllers */

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

@@ -58,12 +58,9 @@
 
 #define GET_IFTYPE(type)	(((type) >> 24) & 0x1f)
 #define SET_IFTYPE(type)	((type) << 24)
-
-#define SET_FLAG(dev, bit) device_set_flags(dev, device_get_flags(dev) | (bit))
-#define CLR_FLAG(dev, bit) device_set_flags(dev, device_get_flags(dev) & ~(bit))
 #endif /* PC98 */
 
-#define	CE_NTYPES			3
+#define	CE_NTYPES		3
 
 typedef u_char	bool_t;		/* boolean */
 
@@ -77,6 +74,16 @@
 
 /* com device structure */
 struct com_s {
+	/* SIO/ng blessed. */
+	struct consdev	*consdev;		/* Set for SIO console. */
+	int		unit;
+	bus_space_tag_t bst;
+	bus_space_handle_t bsh;
+	u_long		rclk;			/* Receiver clock (bin 9) */
+	u_int		regshft;		/* Interleaved multi-port. */
+	u_char		reg_fcr;		/* Copy of FCR. */
+
+	/* Old SIO fields. Need auditing. */
 	u_int	flags;		/* Copy isa device flags */
 	u_char	state;		/* miscellaneous flag bits */
 	bool_t  active_out;	/* nonzero if the callout device is open */
@@ -85,11 +92,9 @@
 	bool_t	esp;		/* is this unit a hayes esp board? */
 #endif
 	u_char	extra_state;	/* more flag bits, separate for order trick */
-	u_char	fifo_image;	/* copy of value written to FIFO */
 	bool_t	hasfifo;	/* nonzero for 16550 UARTs */

>>> TRUNCATED FOR MAIL (1000 lines) <<<

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?200212160027.gBG0Rd7V041052>