Date: Sun, 7 Nov 2004 02:42:22 GMT From: Marcel Moolenaar <marcel@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 64479 for review Message-ID: <200411070242.iA72gMJ4047703@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=64479 Change 64479 by marcel@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, };
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200411070242.iA72gMJ4047703>