PERFORCE change 64479 for review

Marcel Moolenaar marcel at FreeBSD.org
Sat Nov 6 18:42:24 PST 2004


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

Change 64479 by marcel at marcel_nfs on 2004/11/07 02:42:00

	o  define structures to represent the SCC channels and modes.
	o  have scc_bfe_attach() create the channels and modes and
	   associate an unnamed device_t to each node.
	o  s/sc/cl/g for the prefix of fields of struct scc_class.
	o  add cl_class and cl_modes to struct scc_class.
	o  implement scc_bus_read_ivar().

Affected files ...

.. //depot/projects/uart/dev/scc/scc_bfe.h#5 edit
.. //depot/projects/uart/dev/scc/scc_core.c#3 edit
.. //depot/projects/uart/dev/scc/scc_dev_sab82532.c#2 edit
.. //depot/projects/uart/dev/scc/scc_dev_z8530.c#2 edit

Differences ...

==== //depot/projects/uart/dev/scc/scc_bfe.h#5 (text+ko) ====

@@ -45,14 +45,46 @@
 #define	SCC_IPEND_SIGMASK	0x00ffff
 
 /*
+ * SCC mode (child) and channel control structures.
+ */
+struct scc_chan;
+
+struct scc_mode {
+	STAILQ_ENTRY(scc_mode) m_link;
+	struct scc_chan	*m_chan;
+	device_t	m_dev;
+
+	int		m_mode;
+	int		m_alloc_rres:1;
+
+	driver_intr_t	*ih;
+	driver_intr_t	*ih_ovrrun;
+	driver_intr_t	*ih_break;
+	driver_intr_t	*ih_rxready;
+	driver_intr_t	*ih_sigchg;
+	driver_intr_t	*ih_txidle;
+};
+
+struct scc_chan {
+	STAILQ_ENTRY(scc_chan) ch_link;
+	struct resource_list ch_rlist;
+
+	STAILQ_HEAD(, scc_mode) ch_mode;
+
+	u_int		ch_nr;
+};
+
+/*
  * SCC class & instance (=softc)
  */
 struct scc_class {
 	KOBJ_CLASS_FIELDS;
-	u_int	sc_channels;
-	u_int	sc_range;
-	u_int	sc_rclk;
-	u_int	sc_regshft;
+	int		cl_channels;	/* Number of independent channels. */
+	int		cl_class;	/* SCC bus class ID. */
+	int		cl_modes;	/* Supported modes (bitset). */
+	int		cl_range;
+	int		cl_rclk;
+	int		cl_regshft;
 };
 
 extern struct scc_class scc_sab82532_class;
@@ -71,6 +103,11 @@
 	struct resource *sc_ires;	/* Interrupt resource. */
 	void		*sc_icookie;
 	int		sc_irid;
+
+	STAILQ_HEAD(, scc_chan) sc_chan;
+
+	int		sc_fastintr:1;
+	int		sc_polled:1;
 };
 
 extern devclass_t scc_devclass;

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

@@ -33,6 +33,7 @@
 #include <sys/conf.h>
 #include <sys/kernel.h>
 #include <sys/malloc.h>
+#include <sys/queue.h>
 
 #include <machine/bus.h>
 #include <machine/resource.h>
@@ -44,18 +45,90 @@
 devclass_t scc_devclass;
 char scc_driver_name[] = "scc";
 
+MALLOC_DEFINE(M_SCC, "SCC", "SCC driver");
+
+static void
+scc_bfe_intr(void *arg)
+{
+}
+
 int
 scc_bfe_attach(device_t dev)
 {
+	struct scc_chan *ch;
+	struct scc_class *cl;
+	struct scc_mode *m;
 	struct scc_softc *sc;
+	u_long size, start;
+	int c, error, i, mode;
 
 	sc = device_get_softc(dev);
+	cl = sc->sc_class;
+
 	sc->sc_rres = bus_alloc_resource(dev, sc->sc_rtype, &sc->sc_rrid,
-	    0, ~0, sc->sc_class->sc_range, RF_ACTIVE);
+	    0, ~0, cl->cl_range, RF_ACTIVE);
 	if (sc->sc_rres == NULL)
 		return (ENXIO);
 
-	return (ENXIO);
+	sc->sc_irid = 0;
+	sc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irid,
+	    RF_ACTIVE);
+	if (sc->sc_ires != NULL) {
+		error = BUS_SETUP_INTR(device_get_parent(dev), dev,
+		    sc->sc_ires, INTR_TYPE_TTY | INTR_FAST, scc_bfe_intr,
+		    sc, &sc->sc_icookie);
+		if (error)
+			error = BUS_SETUP_INTR(device_get_parent(dev), dev,
+			    sc->sc_ires, INTR_TYPE_TTY | INTR_MPSAFE,
+			    scc_bfe_intr, sc, &sc->sc_icookie);
+		else
+			sc->sc_fastintr = 1;
+
+		if (error) {
+			device_printf(dev, "could not activate interrupt\n");
+			bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid,
+			    sc->sc_ires);
+			sc->sc_ires = NULL;
+		}
+	}
+	if (sc->sc_ires == NULL) {
+		/* XXX no interrupt resource. Force polled mode. */
+		sc->sc_polled = 1;
+	}
+
+	STAILQ_INIT(&sc->sc_chan);
+	size = cl->cl_range / cl->cl_channels;
+	start = rman_get_start(sc->sc_rres);
+	for (c = 1; c <= cl->cl_channels; c++) {
+		ch = malloc(sizeof(struct scc_chan), M_SCC, M_WAITOK | M_ZERO);
+		STAILQ_INSERT_TAIL(&sc->sc_chan, ch, ch_link);
+		ch->ch_nr = c;
+
+		resource_list_init(&ch->ch_rlist);
+		resource_list_add(&ch->ch_rlist, sc->sc_rtype, sc->sc_rrid,
+		    start, start + size - 1, size);
+		resource_list_add(&ch->ch_rlist, SYS_RES_IRQ, sc->sc_irid,
+		    rman_get_start(sc->sc_ires), rman_get_end(sc->sc_ires), 1);
+
+		STAILQ_INIT(&ch->ch_mode);
+		mode = cl->cl_modes;
+		while (mode != 0) {
+			m = malloc(sizeof(struct scc_mode), M_SCC,
+			    M_WAITOK | M_ZERO);
+			STAILQ_INSERT_TAIL(&ch->ch_mode, m, m_link);
+			m->m_chan = ch;
+			m->m_dev = device_add_child(dev, NULL, -1);
+			device_set_ivars(m->m_dev, (void *)m);
+			i = ffs(mode) - 1;
+			m->m_mode = 1 << i;
+			mode &= ~m->m_mode;
+			device_probe_and_attach(m->m_dev);
+		}
+
+		start += size >> cl->cl_regshft;
+	}
+
+	return (0);
 }
 
 int
@@ -93,12 +166,12 @@
 	sc->sc_rrid = 0;
 	sc->sc_rtype = SYS_RES_IOPORT;
 	sc->sc_rres = bus_alloc_resource(dev, sc->sc_rtype, &sc->sc_rrid,
-	    0, ~0, sc->sc_class->sc_range, RF_ACTIVE);
+	    0, ~0, sc->sc_class->cl_range, RF_ACTIVE);
 	if (sc->sc_rres == NULL) {
 		sc->sc_rrid = 0;
 		sc->sc_rtype = SYS_RES_MEMORY;
 		sc->sc_rres = bus_alloc_resource(dev, sc->sc_rtype,
-		    &sc->sc_rrid, 0, ~0, sc->sc_class->sc_range, RF_ACTIVE);
+		    &sc->sc_rrid, 0, ~0, sc->sc_class->cl_range, RF_ACTIVE);
 		if (sc->sc_rres == NULL)
 			return (ENXIO);
 	}
@@ -111,7 +184,7 @@
 scc_bus_alloc_resource(device_t dev, device_t child, int type, int *rid,
     u_long start, u_long end, u_long count, u_int flags)
 {
-
+	device_printf(dev, "%s\n", __func__);
 	return (NULL);
 }
 
@@ -126,20 +199,36 @@
 int
 scc_bus_read_ivar(device_t dev, device_t child, int index, uintptr_t *result)
 {
+	struct scc_chan *ch;
+	struct scc_class *cl;
+	struct scc_mode *m;
+	struct scc_softc *sc;
 
+	sc = device_get_softc(dev);
+	cl = sc->sc_class;
+	m = device_get_ivars(child);
+	ch = m->m_chan;
+
 	switch (index) {
 	case SCC_IVAR_CHANNEL:
+		*result = ch->ch_nr;
 		break;
 	case SCC_IVAR_CLASS:
+		*result = cl->cl_class;
 		break;
 	case SCC_IVAR_CLOCK:
+		*result = cl->cl_rclk;
 		break;
+	case SCC_IVAR_MODE:
+		*result = m->m_mode;
+		break;
 	case SCC_IVAR_REGSHFT:
+		*result = cl->cl_regshft;
 		break;
 	default:
 		return (EINVAL);
 	}
-	return (ENXIO);
+	return (0);
 }
 
 int

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

@@ -34,6 +34,7 @@
 #include <machine/bus.h>
 
 #include <dev/scc/scc_bfe.h>
+#include <dev/scc/scc_bus.h>
 
 #define	DEFAULT_RCLK	29491200
 
@@ -45,8 +46,10 @@
 	"sab82532 class",
 	sab82532_methods,
 	sizeof(struct scc_softc),
-	.sc_channels = 2,
-	.sc_range = 64,
-	.sc_rclk = DEFAULT_RCLK,
-	.sc_regshft = 0
+	.cl_channels = 2,
+	.cl_class = SCC_CLASS_SAB82532,
+	.cl_modes = SCC_MODE_ASYNC | SCC_MODE_BISYNC | SCC_MODE_HDLC,
+	.cl_range = 64,
+	.cl_rclk = DEFAULT_RCLK,
+	.cl_regshft = 0
 };

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

@@ -34,6 +34,7 @@
 #include <machine/bus.h>
 
 #include <dev/scc/scc_bfe.h>
+#include <dev/scc/scc_bus.h>
 
 #define	DEFAULT_RCLK	307200
 
@@ -45,8 +46,10 @@
 	"z8530 class",
 	z8530_methods,
 	sizeof(struct scc_softc),
-	.sc_channels = 2,
-	.sc_range = 2,
-	.sc_rclk = DEFAULT_RCLK,
-	.sc_regshft = 1,
+	.cl_channels = 2,
+	.cl_class = SCC_CLASS_Z8530,
+	.cl_modes = SCC_MODE_ASYNC | SCC_MODE_BISYNC | SCC_MODE_HDLC,
+	.cl_range = 2,
+	.cl_rclk = DEFAULT_RCLK,
+	.cl_regshft = 1,
 };


More information about the p4-projects mailing list