From owner-p4-projects@FreeBSD.ORG Mon Jun 6 03:41:56 2005 Return-Path: X-Original-To: p4-projects@freebsd.org Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 44DBA16A420; Mon, 6 Jun 2005 03:41:56 +0000 (GMT) X-Original-To: perforce@freebsd.org Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 050F316A41C for ; Mon, 6 Jun 2005 03:41:56 +0000 (GMT) (envelope-from marcel@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id BFB0643D49 for ; Mon, 6 Jun 2005 03:41:55 +0000 (GMT) (envelope-from marcel@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.1/8.13.1) with ESMTP id j563ftQo021796 for ; Mon, 6 Jun 2005 03:41:55 GMT (envelope-from marcel@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.1/8.13.1/Submit) id j563ftMB021793 for perforce@freebsd.org; Mon, 6 Jun 2005 03:41:55 GMT (envelope-from marcel@freebsd.org) Date: Mon, 6 Jun 2005 03:41:55 GMT Message-Id: <200506060341.j563ftMB021793@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to marcel@freebsd.org using -f From: Marcel Moolenaar To: Perforce Change Reviews Cc: Subject: PERFORCE change 78066 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 06 Jun 2005 03:41:57 -0000 http://perforce.freebsd.org/chv.cgi?CH=78066 Change 78066 by marcel@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 #include +#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 #include #include +#include #include #include +#include + +#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 #include #include +#include #include #include +#include + +#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 -__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_ */