PERFORCE change 78066 for review
Marcel Moolenaar
marcel at FreeBSD.org
Mon Jun 6 03:41:57 GMT 2005
http://perforce.freebsd.org/chv.cgi?CH=78066
Change 78066 by marcel at marcel_nfs on 2005/06/06 03:41:48
Submit a bunch of changes I have for a while now. I haven't
been working on this for some time and won't in the near
future. I'm not sure this even compiles...
Affected files ...
.. //depot/projects/uart/dev/scc/scc_bfe.h#7 edit
.. //depot/projects/uart/dev/scc/scc_core.c#5 edit
.. //depot/projects/uart/dev/scc/scc_dev_sab82532.c#3 edit
.. //depot/projects/uart/dev/scc/scc_dev_z8530.c#3 edit
.. //depot/projects/uart/dev/scc/scc_if.m#2 edit
.. //depot/projects/uart/dev/uart/uart_core.c#39 edit
.. //depot/projects/uart/sys/serial.h#3 edit
Differences ...
==== //depot/projects/uart/dev/scc/scc_bfe.h#7 (text+ko) ====
@@ -30,6 +30,31 @@
#define _DEV_SCC_BFE_H_
/*
+ * Bus access structure. This structure holds the minimum information needed
+ * to access the SCC. The rclk field, although not important to actually
+ * access the SCC, is important for baudrate programming, delay loops and
+ * other timing related computations.
+ */
+struct scc_bas {
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+ u_int range;
+ u_int rclk;
+ u_int regshft;
+};
+
+#define scc_regofs(bas, reg) ((reg) << (bas)->regshft)
+
+#define scc_getreg(bas, reg) \
+ bus_space_read_1((bas)->bst, (bas)->bsh, scc_regofs(bas, reg))
+#define scc_setreg(bas, reg, value) \
+ bus_space_write_1((bas)->bst, (bas)->bsh, scc_regofs(bas, reg), value)
+
+#define scc_barrier(bas) \
+ bus_space_barrier((bas)->bst, (bas)->bsh, 0, (bas)->range, \
+ BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE)
+
+/*
* SCC mode (child) and channel control structures.
*/
struct scc_chan;
@@ -48,6 +73,8 @@
driver_intr_t *ih_rxready;
driver_intr_t *ih_sigchg;
driver_intr_t *ih_txidle;
+ void *ih_arg;
+ void *softih;
};
struct scc_chan {
@@ -78,6 +105,7 @@
struct scc_softc {
KOBJ_FIELDS;
struct scc_class *sc_class;
+ struct scc_bas sc_bas;
device_t sc_dev;
struct mtx sc_hwmtx; /* Spinlock protecting hardware. */
@@ -92,7 +120,10 @@
STAILQ_HEAD(, scc_chan) sc_chan;
int sc_fastintr:1;
+ int sc_leaving:1;
int sc_polled:1;
+
+ uint32_t sc_hwsig; /* Signal state. Used by HW driver. */
};
extern devclass_t scc_devclass;
==== //depot/projects/uart/dev/scc/scc_core.c#5 (text+ko) ====
@@ -44,6 +44,8 @@
#include <dev/scc/scc_bfe.h>
#include <dev/scc/scc_bus.h>
+#include "scc_if.h"
+
devclass_t scc_devclass;
char scc_driver_name[] = "scc";
@@ -52,6 +54,23 @@
static void
scc_bfe_intr(void *arg)
{
+ struct scc_softc *sc = arg;
+ int ipend;
+
+ while (!sc->sc_leaving && (ipend = SCC_IPEND(sc)) != 0) {
+#if 0
+ if (ipend & SER_INT_OVERRUN)
+ uart_intr_overrun(sc);
+ if (ipend & SER_INT_BREAK)
+ uart_intr_break(sc);
+ if (ipend & SER_INT_RXREADY)
+ uart_intr_rxready(sc);
+ if (ipend & SER_INT_SIGCHG)
+ uart_intr_sigchg(sc);
+ if (ipend & SER_INT_TXIDLE)
+ uart_intr_txidle(sc);
+#endif
+ }
}
int
@@ -61,18 +80,46 @@
struct scc_chan *ch;
struct scc_class *cl;
struct scc_mode *m;
- struct scc_softc *sc;
+ struct scc_softc *sc, *sc0;
+ const char *sep;
bus_space_handle_t bh;
u_long size, start;
int c, error, i, mode;
- sc = device_get_softc(dev);
- cl = sc->sc_class;
+ /*
+ * The sc_class field defines the type of SCC we're going to work
+ * with and thus the size of the softc. Replace the generic softc
+ * with one that matches the SCC now that we're certain we handle
+ * the device.
+ */
+ sc0 = device_get_softc(dev);
+ cl = sc0->sc_class;
+ if (cl->size > sizeof(*sc)) {
+ sc = malloc(cl->size, M_SCC, M_WAITOK|M_ZERO);
+ bcopy(sc0, sc, sizeof(*sc));
+ device_set_softc(dev, sc);
+ } else
+ sc = sc0;
+
+ /*
+ * Protect ourselves against interrupts while we're not completely
+ * finished attaching and initializing. We don't expect interrupts
+ * until after SCC_ATTACH() though.
+ */
+ sc->sc_leaving = 1;
+
+ mtx_init(&sc->sc_hwmtx, "scc_hwmtx", NULL, MTX_SPIN);
+ /*
+ * Re-allocate. We expect that the softc contains the information
+ * collected by scc_bfe_probe() intact.
+ */
sc->sc_rres = bus_alloc_resource(dev, sc->sc_rtype, &sc->sc_rrid,
- 0, ~0, cl->cl_range, RF_ACTIVE);
+ 0, ~0, cl->cl_channels * cl->cl_range, RF_ACTIVE);
if (sc->sc_rres == NULL)
return (ENXIO);
+ sc->sc_bas.bsh = rman_get_bushandle(sc->sc_rres);
+ sc->sc_bas.bst = rman_get_bustag(sc->sc_rres);
sc->sc_irid = 0;
sc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irid,
@@ -100,8 +147,29 @@
sc->sc_polled = 1;
}
+ error = SCC_ATTACH(sc);
+ if (error)
+ goto fail;
+
+ if (bootverbose && (sc->sc_fastintr || sc->sc_polled)) {
+ sep = "";
+ device_print_prettyname(dev);
+ if (sc->sc_fastintr) {
+ printf("%sfast interrupt", sep);
+ sep = ", ";
+ }
+ if (sc->sc_polled) {
+ printf("%spolled mode", sep);
+ sep = ", ";
+ }
+ printf("\n");
+ }
+
+ sc->sc_leaving = 0;
+ scc_bfe_intr(sc);
+
STAILQ_INIT(&sc->sc_chan);
- size = cl->cl_range / cl->cl_channels;
+ size = cl->cl_range;
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);
@@ -146,8 +214,16 @@
start += size >> cl->cl_regshft;
}
+ return (0);
- return (0);
+ fail:
+ 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 (error);
}
int
@@ -161,6 +237,9 @@
scc_bfe_probe(device_t dev)
{
struct scc_softc *sc;
+ struct scc_class *cl;
+ u_long size;
+ int error;
/*
* Initialize the instance. Note that the instance (=softc) does
@@ -170,10 +249,11 @@
* while probing.
*/
sc = device_get_softc(dev);
- kobj_init((kobj_t)sc, (kobj_class_t)sc->sc_class);
+ cl = sc->sc_class;
+ kobj_init((kobj_t)sc, (kobj_class_t)cl);
sc->sc_dev = dev;
if (device_get_desc(dev) == NULL)
- device_set_desc(dev, sc->sc_class->name);
+ device_set_desc(dev, cl->name);
/*
* Allocate the register resource. We assume that all SCCs have a
@@ -183,20 +263,32 @@
* first to satisfy the EBus code.
*/
sc->sc_rrid = 0;
- sc->sc_rtype = SYS_RES_IOPORT;
+ sc->sc_rtype = SYS_RES_MEMORY;
+ size = cl->cl_channels * cl->cl_range;
sc->sc_rres = bus_alloc_resource(dev, sc->sc_rtype, &sc->sc_rrid,
- 0, ~0, sc->sc_class->cl_range, RF_ACTIVE);
+ 0, ~0, size, RF_ACTIVE);
if (sc->sc_rres == NULL) {
sc->sc_rrid = 0;
- sc->sc_rtype = SYS_RES_MEMORY;
+ sc->sc_rtype = SYS_RES_IOPORT;
sc->sc_rres = bus_alloc_resource(dev, sc->sc_rtype,
- &sc->sc_rrid, 0, ~0, sc->sc_class->cl_range, RF_ACTIVE);
+ &sc->sc_rrid, 0, ~0, size, RF_ACTIVE);
if (sc->sc_rres == NULL)
return (ENXIO);
}
+ /*
+ * Fill in the bus access structure and call the hardware specific
+ * probe method.
+ */
+ sc->sc_bas.bsh = rman_get_bushandle(sc->sc_rres);
+ sc->sc_bas.bst = rman_get_bustag(sc->sc_rres);
+ sc->sc_bas.range = sc->sc_class->cl_range;
+ sc->sc_bas.rclk = sc->sc_class->cl_rclk;
+ sc->sc_bas.regshft = sc->sc_class->cl_regshft;
+
+ error = SCC_PROBE(sc);
bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid, sc->sc_rres);
- return (0);
+ return (error);
}
struct resource *
==== //depot/projects/uart/dev/scc/scc_dev_sab82532.c#3 (text+ko) ====
@@ -32,13 +32,25 @@
#include <sys/bus.h>
#include <sys/conf.h>
#include <machine/bus.h>
+#include <sys/serial.h>
#include <dev/scc/scc_bfe.h>
#include <dev/scc/scc_bus.h>
+#include <dev/ic/sab82532.h>
+
+#include "scc_if.h"
+
#define DEFAULT_RCLK 29491200
+static int sab82532_bfe_attach(struct scc_softc *);
+static int sab82532_bfe_ipend(struct scc_softc *);
+static int sab82532_bfe_probe(struct scc_softc *);
+
static kobj_method_t sab82532_methods[] = {
+ KOBJMETHOD(scc_attach, sab82532_bfe_attach),
+ KOBJMETHOD(scc_ipend, sab82532_bfe_ipend),
+ KOBJMETHOD(scc_probe, sab82532_bfe_probe),
{ 0, 0 }
};
@@ -46,10 +58,63 @@
"sab82532 class",
sab82532_methods,
sizeof(struct scc_softc),
- .cl_channels = 2,
+ .cl_channels = SAB_NCHAN,
.cl_class = SCC_CLASS_SAB82532,
.cl_modes = SCC_MODE_ASYNC | SCC_MODE_BISYNC | SCC_MODE_HDLC,
- .cl_range = 64,
+ .cl_range = SAB_CHANLEN,
.cl_rclk = DEFAULT_RCLK,
.cl_regshft = 0
};
+
+static int
+sab82532_bfe_attach(struct scc_softc *sc)
+{
+ struct scc_bas *bas;
+
+ bas = &sc->sc_bas;
+ return (0);
+}
+
+static int
+sab82532_bfe_ipend(struct scc_softc *sc)
+{
+ struct scc_bas *bas;
+ int ipend;
+ uint8_t isr0, isr1;
+
+ bas = &sc->sc_bas;
+ mtx_lock_spin(&sc->sc_hwmtx);
+ isr0 = scc_getreg(bas, SAB_ISR0);
+ isr1 = scc_getreg(bas, SAB_ISR1);
+ scc_barrier(bas);
+ if (isr0 & SAB_ISR0_TIME) {
+ while (scc_getreg(bas, SAB_STAR) & SAB_STAR_CEC)
+ ;
+ scc_setreg(bas, SAB_CMDR, SAB_CMDR_RFRD);
+ scc_barrier(bas);
+ }
+ mtx_unlock_spin(&sc->sc_hwmtx);
+
+ ipend = 0;
+ if (isr1 & SAB_ISR1_BRKT)
+ ipend |= SER_INT_BREAK;
+ if (isr0 & SAB_ISR0_RFO)
+ ipend |= SER_INT_OVERRUN;
+ if (isr0 & (SAB_ISR0_TCD|SAB_ISR0_RPF))
+ ipend |= SER_INT_RXREADY;
+ if ((isr0 & SAB_ISR0_CDSC) || (isr1 & SAB_ISR1_CSC))
+ ipend |= SER_INT_SIGCHG;
+ if (isr1 & SAB_ISR1_ALLS)
+ ipend |= SER_INT_TXIDLE;
+
+ return (ipend);
+}
+
+static int
+sab82532_bfe_probe(struct scc_softc *sc)
+{
+ struct scc_bas *bas;
+
+ bas = &sc->sc_bas;
+ return (0);
+}
==== //depot/projects/uart/dev/scc/scc_dev_z8530.c#3 (text+ko) ====
@@ -32,13 +32,25 @@
#include <sys/bus.h>
#include <sys/conf.h>
#include <machine/bus.h>
+#include <sys/serial.h>
#include <dev/scc/scc_bfe.h>
#include <dev/scc/scc_bus.h>
+#include <dev/ic/z8530.h>
+
+#include "scc_if.h"
+
#define DEFAULT_RCLK 307200
+static int z8530_bfe_attach(struct scc_softc *);
+static int z8530_bfe_ipend(struct scc_softc *);
+static int z8530_bfe_probe(struct scc_softc *);
+
static kobj_method_t z8530_methods[] = {
+ KOBJMETHOD(scc_attach, z8530_bfe_attach),
+ KOBJMETHOD(scc_ipend, z8530_bfe_ipend),
+ KOBJMETHOD(scc_probe, z8530_bfe_probe),
{ 0, 0 }
};
@@ -49,7 +61,53 @@
.cl_channels = 2,
.cl_class = SCC_CLASS_Z8530,
.cl_modes = SCC_MODE_ASYNC | SCC_MODE_BISYNC | SCC_MODE_HDLC,
- .cl_range = 2,
+ .cl_range = CHAN_A - CHAN_B,
.cl_rclk = DEFAULT_RCLK,
.cl_regshft = 1,
};
+
+/* Multiplexed I/O. */
+static __inline void
+scc_setmreg(struct scc_bas *bas, int ch, int reg, int val)
+{
+
+ scc_setreg(bas, ch + REG_CTRL, reg);
+ scc_barrier(bas);
+ scc_setreg(bas, ch + REG_CTRL, val);
+}
+
+static __inline uint8_t
+scc_getmreg(struct scc_bas *bas, int ch, int reg)
+{
+
+ scc_setreg(bas, ch + REG_CTRL, reg);
+ scc_barrier(bas);
+ return (scc_getreg(bas, ch + REG_CTRL));
+}
+
+static int
+z8530_bfe_attach(struct scc_softc *sc)
+{
+ struct scc_bas *bas;
+
+ bas = &sc->sc_bas;
+ return (0);
+}
+
+static int
+z8530_bfe_ipend(struct scc_softc *sc)
+{
+ struct scc_bas *bas;
+
+ bas = &sc->sc_bas;
+ return (0);
+}
+
+static int
+z8530_bfe_probe(struct scc_softc *sc)
+{
+ struct scc_bas *bas;
+
+ bas = &sc->sc_bas;
+ return (0);
+}
==== //depot/projects/uart/dev/scc/scc_if.m#2 (text+ko) ====
@@ -36,6 +36,14 @@
INTERFACE scc;
+# attach() - attach hardware.
+# This method is called when the device is being attached. All resources
+# have been allocated. The intend of this method is to setup the hardware
+# for normal operation.
+METHOD int attach {
+ struct scc_softc *this;
+};
+
# ipend() - query SCC for pending interrupts.
# When an interrupt is signalled, the handler will call this method to find
# out which of the interrupt sources needs attention. The handler will use
@@ -48,3 +56,11 @@
METHOD int ipend {
struct scc_softc *this;
}
+
+# probe() - detect hardware.
+# This method is called as part of the bus probe to make sure the
+# hardware exists. This function should also set the device description
+# to something that represents the hardware.
+METHOD int probe {
+ struct scc_softc *this;
+};
==== //depot/projects/uart/dev/uart/uart_core.c#39 (text+ko) ====
@@ -1,4 +1,4 @@
-/*
+/*-
* Copyright (c) 2003 Marcel Moolenaar
* All rights reserved.
*
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/uart/uart_core.c,v 1.11 2004/11/14 23:12:14 marcel Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/uart/uart_core.c,v 1.13 2005/03/02 11:30:14 marius Exp $");
#ifndef KLD_MODULE
#include "opt_comconsole.h"
@@ -90,10 +90,8 @@
return;
}
#endif
- if (sc->sc_opened) {
+ if (sc->sc_opened)
atomic_set_32(&sc->sc_ttypend, SER_INT_BREAK);
- swi_sched(sc->sc_softih, 0);
- }
}
/*
@@ -121,7 +119,6 @@
if (uart_rx_put(sc, UART_STAT_OVERRUN))
sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN;
atomic_set_32(&sc->sc_ttypend, SER_INT_RXREADY);
- swi_sched(sc->sc_softih, 0);
}
UART_FLUSH(sc, UART_FLUSH_RECEIVER);
}
@@ -147,10 +144,9 @@
}
}
#endif
- if (sc->sc_opened) {
+ if (sc->sc_opened)
atomic_set_32(&sc->sc_ttypend, SER_INT_RXREADY);
- swi_sched(sc->sc_softih, 0);
- } else
+ else
sc->sc_rxput = sc->sc_rxget; /* Ignore received data. */
}
@@ -190,8 +186,6 @@
new |= sig & SER_INT_SIGMASK;
new |= SER_INT_SIGCHG;
} while (!atomic_cmpset_32(&sc->sc_ttypend, old, new));
- if (sc->sc_opened)
- swi_sched(sc->sc_softih, 0);
}
/*
@@ -204,10 +198,7 @@
if (sc->sc_txbusy) {
sc->sc_txbusy = 0;
- if (sc->sc_opened) {
- atomic_set_32(&sc->sc_ttypend, SER_INT_TXIDLE);
- swi_sched(sc->sc_softih, 0);
- }
+ atomic_set_32(&sc->sc_ttypend, SER_INT_TXIDLE);
}
}
@@ -229,6 +220,9 @@
if (ipend & SER_INT_TXIDLE)
uart_intr_txidle(sc);
}
+
+ if (sc->sc_opened && sc->sc_ttypend != 0)
+ swi_sched(sc->sc_softih, 0);
}
int
@@ -334,14 +328,16 @@
*/
sc->sc_rres = bus_alloc_resource(dev, sc->sc_rtype, &sc->sc_rrid,
0, ~0, sc->sc_class->uc_range, RF_ACTIVE);
- if (sc->sc_rres == NULL)
+ if (sc->sc_rres == NULL) {
+ mtx_destroy(&sc->sc_hwmtx);
return (ENXIO);
+ }
sc->sc_bas.bsh = rman_get_bushandle(sc->sc_rres);
sc->sc_bas.bst = rman_get_bustag(sc->sc_rres);
sc->sc_irid = 0;
sc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irid,
- RF_ACTIVE);
+ RF_ACTIVE | RF_SHAREABLE);
if (sc->sc_ires != NULL) {
error = BUS_SETUP_INTR(device_get_parent(dev), dev,
sc->sc_ires, INTR_TYPE_TTY | INTR_FAST, uart_intr,
@@ -451,6 +447,8 @@
}
bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid, sc->sc_rres);
+ mtx_destroy(&sc->sc_hwmtx);
+
return (error);
}
@@ -480,6 +478,8 @@
}
bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid, sc->sc_rres);
+ mtx_destroy(&sc->sc_hwmtx);
+
if (sc->sc_class->size > sizeof(*sc)) {
device_set_softc(dev, NULL);
free(sc, M_UART);
==== //depot/projects/uart/sys/serial.h#3 (text+ko) ====
@@ -40,26 +40,30 @@
* that identity is enforced with CTASSERT at the bottom of kern/tty.c
* Both the modem bits and delta bits must fit in 16 bit.
*/
-#define SER_DTR 0x0001 /* data terminal ready */
-#define SER_RTS 0x0002 /* request to send */
-#define SER_STX 0x0004 /* secondary transmit */
-#define SER_SRX 0x0008 /* secondary receive */
-#define SER_CTS 0x0010 /* clear to send */
-#define SER_DCD 0x0020 /* data carrier detect */
-#define SER_RI 0x0040 /* ring indicate */
-#define SER_DSR 0x0080 /* data set ready */
+#define SER_DTR 0x0001 /* data terminal ready */
+#define SER_RTS 0x0002 /* request to send */
+#define SER_STX 0x0004 /* secondary transmit */
+#define SER_SRX 0x0008 /* secondary receive */
+#define SER_CTS 0x0010 /* clear to send */
+#define SER_DCD 0x0020 /* data carrier detect */
+#define SER_RI 0x0040 /* ring indicate */
+#define SER_DSR 0x0080 /* data set ready */
+
+#define SER_MASK_STATE 0x00ff
/* Delta bits, used to indicate which signals should/was affected */
-#define SER_DELTA(x) ((x) << 8)
+#define SER_DELTA(x) ((x) << 8)
+
+#define SER_DDTR SER_DELTA(SER_DTR)
+#define SER_DRTS SER_DELTA(SER_RTS)
+#define SER_DSTX SER_DELTA(SER_STX)
+#define SER_DSRX SER_DELTA(SER_SRX)
+#define SER_DCTS SER_DELTA(SER_CTS)
+#define SER_DDCD SER_DELTA(SER_DCD)
+#define SER_DRI SER_DELTA(SER_RI)
+#define SER_DDSR SER_DELTA(SER_DSR)
-#define SER_DDTR SER_DELTA(SER_DTR)
-#define SER_DRTS SER_DELTA(SER_RTS)
-#define SER_DSTX SER_DELTA(SER_STX)
-#define SER_DSRX SER_DELTA(SER_SRX)
-#define SER_DCTS SER_DELTA(SER_CTS)
-#define SER_DDCD SER_DELTA(SER_DCD)
-#define SER_DRI SER_DELTA(SER_RI)
-#define SER_DDSR SER_DELTA(SER_DSR)
+#define SER_MASK_DELTA SER_DELTA(SER_MASK_STATE)
/*
* Specification of interrupt sources typical for serial ports. These are
@@ -69,13 +73,13 @@
* resource for which inferior drivers can install handlers. The lower 16
* bits are kept free for the signals above.
*/
-#define SER_INT_OVERRUN 0x010000
-#define SER_INT_BREAK 0x020000
-#define SER_INT_RXREADY 0x040000
-#define SER_INT_SIGCHG 0x080000
-#define SER_INT_TXIDLE 0x100000
+#define SER_INT_OVERRUN 0x010000
+#define SER_INT_BREAK 0x020000
+#define SER_INT_RXREADY 0x040000
+#define SER_INT_SIGCHG 0x080000
+#define SER_INT_TXIDLE 0x100000
-#define SER_INT_MASK 0xff0000
-#define SER_INT_SIGMASK 0x00ffff
+#define SER_INT_MASK 0xff0000
+#define SER_INT_SIGMASK (SER_MASK_DELTA | SER_MASK_STATE)
#endif /* !_SYS_SERIAL_H_ */
More information about the p4-projects
mailing list