diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/sparc/conf/GENERIC | 7 | ||||
-rw-r--r-- | sys/arch/sparc/conf/GENERIC_SCSI3 | 9 | ||||
-rw-r--r-- | sys/arch/sparc/dev/spif.c | 1047 | ||||
-rw-r--r-- | sys/arch/sparc/dev/spifreg.h | 298 | ||||
-rw-r--r-- | sys/arch/sparc/dev/spifvar.h | 81 | ||||
-rw-r--r-- | sys/arch/sparc/include/conf.h | 5 | ||||
-rw-r--r-- | sys/arch/sparc/sparc/conf.c | 8 |
7 files changed, 1449 insertions, 6 deletions
diff --git a/sys/arch/sparc/conf/GENERIC b/sys/arch/sparc/conf/GENERIC index a929a8d42ac..4994961f9ba 100644 --- a/sys/arch/sparc/conf/GENERIC +++ b/sys/arch/sparc/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.35 1998/12/29 09:33:35 deraadt Exp $ +# $OpenBSD: GENERIC,v 1.36 1999/02/01 00:30:42 jason Exp $ # $NetBSD: GENERIC,v 1.48 1997/08/23 19:19:01 mjacob Exp $ # Machine architecture; required by config(8) @@ -99,6 +99,11 @@ magma* at sbus? slot ? offset ? # magma serial cards mtty* at magma? mbpp* at magma? +# SUNW,spif serial/parallel port devices +spif* at sbus? slot ? offset ? # spif serial cards +stty* at spif? +sbpp* at spif? + bpp* at sbus? slot ? offset ? # parallel port # diff --git a/sys/arch/sparc/conf/GENERIC_SCSI3 b/sys/arch/sparc/conf/GENERIC_SCSI3 index 882c83b569e..c382efd8390 100644 --- a/sys/arch/sparc/conf/GENERIC_SCSI3 +++ b/sys/arch/sparc/conf/GENERIC_SCSI3 @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC_SCSI3,v 1.24 1998/10/19 05:43:29 jason Exp $ +# $OpenBSD: GENERIC_SCSI3,v 1.25 1999/02/01 00:30:42 jason Exp $ # $NetBSD: GENERIC,v 1.28.2.1 1996/07/02 23:55:22 jtc Exp $ # Machine architecture; required by config(8) @@ -95,6 +95,13 @@ magma* at sbus? slot ? offset ? # magma serial cards mtty* at magma? mbpp* at magma? +# SUNW,spif serial/parallel port devices +spif* at sbus? slot ? offset ? # spif serial cards +stty* at spif? +sbpp* at spif? + +bpp* at sbus? slot ? offset ? # parallel port + # # Note the flags on the esp entries below, that work around # deficiencies in the current driver: diff --git a/sys/arch/sparc/dev/spif.c b/sys/arch/sparc/dev/spif.c new file mode 100644 index 00000000000..72463efa2ff --- /dev/null +++ b/sys/arch/sparc/dev/spif.c @@ -0,0 +1,1047 @@ +/* $OpenBSD: spif.c,v 1.1 1999/02/01 00:30:42 jason Exp $ */ + +/* + * Copyright (c) 1999 Jason L. Wright (jason@thought.net) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Jason L. Wright + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Driver for the SUNW,spif: 8 serial, 1 parallel sbus board + * based heavily on Iain Hibbert's driver for the MAGMA driver + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/proc.h> +#include <sys/device.h> +#include <sys/kernel.h> +#include <sys/file.h> +#include <sys/errno.h> +#include <sys/ioctl.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <sys/syslog.h> +#include <sys/malloc.h> +#include <sys/tty.h> +#include <sys/conf.h> + +#include <machine/autoconf.h> +#include <sparc/cpu.h> +#include <sparc/sparc/cpuvar.h> +#include <sparc/dev/sbusvar.h> +#include <sparc/dev/spifreg.h> +#include <sparc/dev/spifvar.h> + +#if PIL_TTY == 1 +# define IE_MSOFT IE_L1 +#elif PIL_TTY == 4 +# define IE_MSOFT IE_L4 +#elif PIL_TTY == 6 +# define IE_MSOFT IE_L6 +#else +# error "no suitable software interrupt bit" +#endif + +/* + * useful macros + */ +#define SET(t, f) ((t) |= (f)) +#define CLR(t, f) ((t) &= ~(f)) +#define ISSET(t, f) ((t) & (f)) + +int spifmatch __P((struct device *, void *, void *)); +void spifattach __P((struct device *, struct device *, void *)); + +int sttymatch __P((struct device *, void *, void *)); +void sttyattach __P((struct device *, struct device *, void *)); +int sttyopen __P((dev_t, int, int, struct proc *)); +int sttyclose __P((dev_t, int, int, struct proc *)); +int sttyread __P((dev_t, struct uio *, int)); +int sttywrite __P((dev_t, struct uio *, int)); +int sttyioctl __P((dev_t, u_long, caddr_t, int, struct proc *)); +int sttystop __P((struct tty *, int)); +int spifstcintr __P((void *)); +int spifsoftintr __P((void *)); +int stty_param __P((struct tty *, struct termios *)); +struct tty *sttytty __P((dev_t)); +int stty_modem_control __P((struct stty_port *, int, int)); +static __inline void spif_write_ccr __P((struct stcregs *, u_int8_t)); +int spif_compute_baud __P((speed_t, int, u_int8_t *, u_int8_t *)); +void stty_start __P((struct tty *)); + +int sbppmatch __P((struct device *, void *, void *)); +void sbppattach __P((struct device *, struct device *, void *)); +int sbppopen __P((dev_t, int, int, struct proc *)); +int sbppclose __P((dev_t, int, int, struct proc *)); +int sbppread __P((dev_t, struct uio *, int)); +int sbppwrite __P((dev_t, struct uio *, int)); +int sbpp_rw __P((dev_t, struct uio *)); +int spifppcintr __P((void *)); +int sbppselect __P((dev_t, int, struct proc *)); +int sbppioctl __P((dev_t, u_long, caddr_t, int, struct proc *)); + +struct cfattach spif_ca = { + sizeof (struct spif_softc), spifmatch, spifattach +}; + +struct cfdriver spif_cd = { + NULL, "spif", DV_IFNET +}; + +struct cfattach stty_ca = { + sizeof(struct stty_softc), sttymatch, sttyattach +}; + +struct cfdriver stty_cd = { + NULL, "stty", DV_TTY +}; + +struct cfattach sbpp_ca = { + sizeof(struct sbpp_softc), sbppmatch, sbppattach +}; + +struct cfdriver sbpp_cd = { + NULL, "sbpp", DV_DULL +}; + +int +spifmatch(parent, vcf, aux) + struct device *parent; + void *vcf, *aux; +{ + struct cfdata *cf = vcf; + struct confargs *ca = aux; + register struct romaux *ra = &ca->ca_ra; + + if (strcmp(cf->cf_driver->cd_name, ra->ra_name) && + strcmp("SUNW,spif", ra->ra_name)) + return (0); + return (1); +} + +void +spifattach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct spif_softc *sc = (struct spif_softc *)self; + struct confargs *ca = aux; + int stcpri, ppcpri; + + if (ca->ca_ra.ra_nintr != 2) { + printf(": expected 2 interrupts, got %d\n", + ca->ca_ra.ra_nintr); + return; + } + stcpri = ca->ca_ra.ra_intr[SERIAL_INTR].int_pri; + ppcpri = ca->ca_ra.ra_intr[PARALLEL_INTR].int_pri; + + if (ca->ca_ra.ra_nreg != 1) { + printf(": expected %d registers, got %d\n", + 1, ca->ca_ra.ra_nreg); + return; + } + sc->sc_regs = mapiodev(ca->ca_ra.ra_reg, 0, ca->ca_ra.ra_len); + + sc->sc_node = ca->ca_ra.ra_node; + + sc->sc_rev = getpropint(sc->sc_node, "revlev", 0); + + sc->sc_osc = getpropint(sc->sc_node, "verosc", 0); + switch (sc->sc_osc) { + case SPIF_OSC10: + sc->sc_osc = 10; + break; + case SPIF_OSC9: + default: + sc->sc_osc = 9; + break; + } + + sc->sc_nser = 8; + sc->sc_npar = 1; + + sc->sc_rev2 = sc->sc_regs->stc.gfrcr; + sc->sc_regs->stc.gsvr = 0; + + spif_write_ccr(&sc->sc_regs->stc, CD180_CCR_RESET | CD180_CCR_RESETALL); + while (sc->sc_regs->stc.gsvr != 0xff); + while (sc->sc_regs->stc.gfrcr != sc->sc_rev2); + + sc->sc_regs->stc.gsvr = 0; + sc->sc_regs->stc.msmr = SPIF_MSMR; + sc->sc_regs->stc.tsmr = SPIF_TSMR; + sc->sc_regs->stc.rsmr = SPIF_RSMR; + sc->sc_regs->stc.pprh = SPIF_PPRH; + sc->sc_regs->stc.pprl = SPIF_PPRL; + + printf(": rev %d chiprev %d osc %dMhz stcpri %d ppcpri %d softpri %d\n", + sc->sc_rev, sc->sc_rev2, sc->sc_osc, stcpri, ppcpri, PIL_TTY); + + if (sc->sc_osc == 10) + sc->sc_osc = 10000000; + else + sc->sc_osc = 9830400; + + (void)config_found(self, sttymatch, NULL); + (void)config_found(self, sbppmatch, NULL); + + sc->sc_ppcih.ih_fun = spifppcintr; + sc->sc_ppcih.ih_arg = sc; + intr_establish(ppcpri, &sc->sc_ppcih); + + sc->sc_stcih.ih_fun = spifstcintr; + sc->sc_stcih.ih_arg = sc; + intr_establish(stcpri, &sc->sc_stcih); + + sc->sc_softih.ih_fun = spifsoftintr; + sc->sc_softih.ih_arg = sc; + intr_establish(PIL_TTY, &sc->sc_softih); +} + +int +sttymatch(parent, vcf, aux) + struct device *parent; + void *vcf, *aux; +{ + struct spif_softc *sc = (struct spif_softc *)parent; + + return (aux == sttymatch && sc->sc_ttys == NULL); +} + +void +sttyattach(parent, dev, aux) + struct device *parent, *dev; + void *aux; +{ + struct spif_softc *sc = (struct spif_softc *)parent; + struct stty_softc *ssc = (struct stty_softc *)dev; + int port; + + sc->sc_ttys = ssc; + + for (port = 0; port < sc->sc_nser; port++) { + struct stty_port *sp = &ssc->sc_port[port]; + struct tty *tp; + + tp = ttymalloc(); + if (tp == NULL) + break; + tty_attach(tp); + + tp->t_oproc = stty_start; + tp->t_param = stty_param; + + sp->sp_tty = tp; + sp->sp_sc = sc; + sp->sp_channel = port; + + sp->sp_rbuf = malloc(STTY_RBUF_SIZE, M_DEVBUF, M_NOWAIT); + if(sp->sp_rbuf == NULL) + break; + + sp->sp_rend = sp->sp_rbuf + STTY_RBUF_SIZE; + } + + ssc->sc_nports = port; + + printf(": %d tty%s\n", port, port == 1 ? "" : "s"); +} + +int +sttyopen(dev, flags, mode, p) + dev_t dev; + int flags; + int mode; + struct proc *p; +{ + struct spif_softc *csc; + struct stty_softc *sc; + struct stty_port *sp; + struct tty *tp; + int card = SPIF_CARD(dev); + int port = SPIF_PORT(dev); + int s; + + if (card >= stty_cd.cd_ndevs || card >= spif_cd.cd_ndevs) + return (ENXIO); + + sc = stty_cd.cd_devs[card]; + csc = spif_cd.cd_devs[card]; + if (sc == NULL) + return (ENXIO); + + if (port >= sc->sc_nports) + return (ENXIO); + + sp = &sc->sc_port[port]; + tp = sp->sp_tty; + tp->t_dev = dev; + + if (!ISSET(tp->t_state, TS_ISOPEN)) { + SET(tp->t_state, TS_WOPEN); + + ttychars(tp); + tp->t_iflag = TTYDEF_IFLAG; + tp->t_oflag = TTYDEF_OFLAG; + tp->t_cflag = TTYDEF_CFLAG; + if (ISSET(sp->sp_openflags, TIOCFLAG_CLOCAL)) + SET(tp->t_cflag, CLOCAL); + if (ISSET(sp->sp_openflags, TIOCFLAG_CRTSCTS)) + SET(tp->t_cflag, CRTSCTS); + if (ISSET(sp->sp_openflags, TIOCFLAG_MDMBUF)) + SET(tp->t_cflag, MDMBUF); + tp->t_lflag = TTYDEF_LFLAG; + tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; + + sp->sp_rput = sp->sp_rget = sp->sp_rbuf; + + s = spltty(); + + csc->sc_regs->stc.car = sp->sp_channel; + spif_write_ccr(&csc->sc_regs->stc, + CD180_CCR_RESET | CD180_CCR_RESETCHAN); + + stty_param(tp, &tp->t_termios); + + ttsetwater(tp); + + csc->sc_regs->stc.srer = CD180_SRER_DSR | CD180_SRER_RXD; + + if (ISSET(sp->sp_openflags, TIOCFLAG_SOFTCAR) || sp->sp_carrier) + SET(tp->t_state, TS_CARR_ON); + else + CLR(tp->t_state, TS_CARR_ON); + } + else if (ISSET(tp->t_state, TS_XCLUDE) && p->p_ucred->cr_uid != 0) { + return (EBUSY); + } else { + s = spltty(); + } + + if (!ISSET(flags, O_NONBLOCK)) { + while (!ISSET(tp->t_cflag, CLOCAL) && + !ISSET(tp->t_state, TS_CARR_ON)) { + int error; + + SET(tp->t_state, TS_WOPEN); + error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH, + "sttycd", 0); + if (error != 0) { + splx(s); + CLR(tp->t_state, TS_WOPEN); + return (error); + } + } + } + + splx(s); + + return ((*linesw[tp->t_line].l_open)(dev, tp)); +} + +int +sttyclose(dev, flags, mode, p) + dev_t dev; + int flags; + int mode; + struct proc *p; +{ + struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(dev)]; + struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)]; + struct spif_softc *csc = sp->sp_sc; + struct tty *tp = sp->sp_tty; + int port = SPIF_PORT(dev); + int s; + + (*linesw[tp->t_line].l_close)(tp, flags); + s = spltty(); + + if (ISSET(tp->t_cflag, HUPCL) || !ISSET(tp->t_state, TS_ISOPEN)) { + csc->sc_regs->stc.car = port; + csc->sc_regs->stc.ccr = CD180_CCR_RESET | CD180_CCR_RESETCHAN; + } + + splx(s); + ttyclose(tp); + return (0); +} + +int +sttyioctl(dev, cmd, data, flags, p) + dev_t dev; + u_long cmd; + caddr_t data; + int flags; + struct proc *p; +{ + struct stty_softc *stc = stty_cd.cd_devs[SPIF_CARD(dev)]; + struct stty_port *sp = &stc->sc_port[SPIF_PORT(dev)]; + struct spif_softc *sc = sp->sp_sc; + struct tty *tp = sp->sp_tty; + int error; + + error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flags, p); + if (error >= 0) + return (error); + + error = ttioctl(tp, cmd, data, flags, p); + if (error >= 0) + return (error); + + error = 0; + + switch (cmd) { + case TIOCSBRK: + SET(sp->sp_flags, STTYF_SET_BREAK); + sc->sc_regs->stc.car = sp->sp_channel; + sc->sc_regs->stc.srer |= CD180_SRER_TXD; + break; + case TIOCCBRK: + SET(sp->sp_flags, STTYF_CLR_BREAK); + sc->sc_regs->stc.car = sp->sp_channel; + sc->sc_regs->stc.srer |= CD180_SRER_TXD; + break; + case TIOCSDTR: + stty_modem_control(sp, TIOCM_DTR, DMBIS); + break; + case TIOCCDTR: + stty_modem_control(sp, TIOCM_DTR, DMBIC); + break; + case TIOCMBIS: + stty_modem_control(sp, *((int *)data), DMBIS); + break; + case TIOCMBIC: + stty_modem_control(sp, *((int *)data), DMBIC); + break; + case TIOCMGET: + *((int *)data) = stty_modem_control(sp, 0, DMGET); + break; + case TIOCGFLAGS: + *((int *)data) = sp->sp_openflags; + break; + case TIOCSFLAGS: + if (suser(p->p_ucred, &p->p_acflag)) + error = EPERM; + else + sp->sp_openflags = *((int *)data) & + (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL | + TIOCFLAG_CRTSCTS | TIOCFLAG_MDMBUF); + break; + default: + error = ENOTTY; + } + + return (error); +} + +int +stty_modem_control(sp, bits, how) + struct stty_port *sp; + int bits, how; +{ + struct spif_softc *csc = sp->sp_sc; + struct tty *tp = sp->sp_tty; + int s, msvr; + + s = spltty(); + csc->sc_regs->stc.car = sp->sp_channel; + + switch (how) { + case DMGET: + bits = TIOCM_LE; + if (sp->sp_dtr) + bits |= TIOCM_DTR; + msvr = csc->sc_regs->stc.msvr; + if (ISSET(msvr, CD180_MSVR_DSR)) + bits |= TIOCM_DSR; + if (ISSET(msvr, CD180_MSVR_CD)) + bits |= TIOCM_CD; + if (ISSET(msvr, CD180_MSVR_CTS)) + bits |= TIOCM_CTS; + if (ISSET(msvr, CD180_MSVR_RTS)) + bits |= TIOCM_RTS; + break; + case DMSET: + if (ISSET(bits, TIOCM_DTR)) { + sp->sp_dtr = 1; + csc->sc_regs->dtrlatch[sp->sp_channel] = 1; + } + else { + sp->sp_dtr = 0; + csc->sc_regs->dtrlatch[sp->sp_channel] = 0; + } + if (ISSET(bits, TIOCM_RTS)) + csc->sc_regs->stc.msvr &= ~CD180_MSVR_RTS; + else + csc->sc_regs->stc.msvr |= CD180_MSVR_RTS; + break; + case DMBIS: + if (ISSET(bits, TIOCM_DTR)) { + sp->sp_dtr = 1; + csc->sc_regs->dtrlatch[sp->sp_channel] = 1; + } + if (ISSET(bits, TIOCM_RTS) && !ISSET(tp->t_cflag, CRTSCTS)) + csc->sc_regs->stc.msvr &= ~CD180_MSVR_RTS; + break; + case DMBIC: + if (ISSET(bits, TIOCM_DTR)) { + sp->sp_dtr = 0; + csc->sc_regs->dtrlatch[sp->sp_channel] = 0; + } + if (ISSET(bits, TIOCM_RTS)) + csc->sc_regs->stc.msvr |= CD180_MSVR_RTS; + break; + } + + splx(s); + return (bits); +} + +int +stty_param(tp, t) + struct tty *tp; + struct termios *t; +{ + struct stty_softc *st = stty_cd.cd_devs[SPIF_CARD(tp->t_dev)]; + struct stty_port *sp = &st->sc_port[SPIF_PORT(tp->t_dev)]; + struct spif_softc *sc = sp->sp_sc; + u_int8_t rbprl, rbprh, tbprl, tbprh; + int s, opt; + + if (t->c_ospeed && + spif_compute_baud(t->c_ospeed, sc->sc_osc, &tbprl, &tbprh)) + return (EINVAL); + + if (t->c_ispeed && + spif_compute_baud(t->c_ispeed, sc->sc_osc, &rbprl, &rbprh)) + return (EINVAL); + + s = spltty(); + + /* hang up line if ospeed is zero, otherwise raise DTR */ + stty_modem_control(sp, TIOCM_DTR, + (t->c_ospeed == 0 ? DMBIC : DMBIS)); + + sc->sc_regs->stc.car = sp->sp_channel; + + opt = 0; + if (ISSET(t->c_cflag, PARENB)) { + opt |= CD180_COR1_PARMODE_NORMAL; + opt |= (ISSET(t->c_cflag, PARODD) ? + CD180_COR1_ODDPAR : + CD180_COR1_EVENPAR); + } + else + opt |= CD180_COR1_PARMODE_NO; + + if (!ISSET(t->c_iflag, INPCK)) + opt |= CD180_COR1_IGNPAR; + + if (ISSET(t->c_cflag, CSTOPB)) + opt |= CD180_COR1_STOP2; + + switch (t->c_cflag & CSIZE) { + case CS5: + opt |= CD180_COR1_CS5; + break; + case CS6: + opt |= CD180_COR1_CS6; + break; + case CS7: + opt |= CD180_COR1_CS7; + break; + default: + opt |= CD180_COR1_CS8; + break; + } + sc->sc_regs->stc.cor1 = opt; + + opt = CD180_COR2_ETC; + if (ISSET(t->c_cflag, CRTSCTS)) + opt |= CD180_COR2_CTSAE; + sc->sc_regs->stc.cor2 = opt; + + sc->sc_regs->stc.cor3 = STTY_RX_FIFO_THRESHOLD; + + spif_write_ccr(&sc->sc_regs->stc, CD180_CCR_CORCHG | + CD180_CCR_CORCHG1 | CD180_CCR_CORCHG2 | CD180_CCR_CORCHG3); + + sc->sc_regs->stc.schr1 = 0x11; + sc->sc_regs->stc.schr2 = 0x13; + sc->sc_regs->stc.schr3 = 0x11; + sc->sc_regs->stc.schr4 = 0x13; + sc->sc_regs->stc.rtpr = 0x28; + + sc->sc_regs->stc.mcor1 = CD180_MCOR1_CDZD | STTY_RX_DTR_THRESHOLD; + sc->sc_regs->stc.mcor2 = CD180_MCOR2_CDOD; + + if (t->c_ospeed) { + sc->sc_regs->stc.tbprh = tbprh; + sc->sc_regs->stc.tbprl = tbprl; + } + + if (t->c_ispeed) { + sc->sc_regs->stc.rbprh = rbprh; + sc->sc_regs->stc.rbprl = rbprl; + } + + spif_write_ccr(&sc->sc_regs->stc, CD180_CCR_CHANCTL | + CD180_CCR_CHAN_TXEN | CD180_CCR_CHAN_RXEN); + + splx(s); + return (0); +} + +int +sttyread(dev, uio, flags) + dev_t dev; + struct uio *uio; + int flags; +{ + struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(dev)]; + struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)]; + struct tty *tp = sp->sp_tty; + + return ((*linesw[tp->t_line].l_read)(tp, uio, flags)); +} + +int +sttywrite(dev, uio, flags) + dev_t dev; + struct uio *uio; + int flags; +{ + struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(dev)]; + struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)]; + struct tty *tp = sp->sp_tty; + + return ((*linesw[tp->t_line].l_write)(tp, uio, flags)); +} + +struct tty * +sttytty(dev) + dev_t dev; +{ + struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(dev)]; + struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)]; + + return (sp->sp_tty); +} + +int +sttystop(tp, flags) + struct tty *tp; + int flags; +{ + struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(tp->t_dev)]; + struct stty_port *sp = &sc->sc_port[SPIF_PORT(tp->t_dev)]; + int s; + + s = spltty(); + if (ISSET(tp->t_state, TS_BUSY)) { + if (!ISSET(tp->t_state, TS_TTSTOP)) + SET(tp->t_state, TS_FLUSH); + SET(sp->sp_flags, STTYF_STOP); + } + splx(s); + return (0); +} + +void +stty_start(tp) + struct tty *tp; +{ + struct stty_softc *stc = stty_cd.cd_devs[SPIF_CARD(tp->t_dev)]; + struct stty_port *sp = &stc->sc_port[SPIF_PORT(tp->t_dev)]; + struct spif_softc *sc = sp->sp_sc; + int s; + + s = spltty(); + + if (!ISSET(tp->t_state, TS_TTSTOP | TS_TIMEOUT | TS_BUSY)) { + if (tp->t_outq.c_cc <= tp->t_lowat) { + if (ISSET(tp->t_state, TS_ASLEEP)) { + CLR(tp->t_state, TS_ASLEEP); + wakeup(&tp->t_outq); + } + selwakeup(&tp->t_wsel); + } + if (tp->t_outq.c_cc) { + sp->sp_txc = ndqb(&tp->t_outq, 0); + sp->sp_txp = tp->t_outq.c_cf; + SET(tp->t_state, TS_BUSY); + sc->sc_regs->stc.car = sp->sp_channel; + sc->sc_regs->stc.srer |= CD180_SRER_TXD; + } + } + + splx(s); +} + +int +spifstcintr(vsc) + void *vsc; +{ + struct spif_softc *sc = (struct spif_softc *)vsc; + struct stty_port *sp; + u_int8_t channel, ar, *ptr; + int needsoft = 0, r = 0, i; + + /* + * Receive data service request + * (also Receive error service request) + */ + ar = sc->sc_regs->istc.rrar & 7; + + switch (ar) { + case CD180_GSVR_RXGOOD: + r = 1; + channel = (sc->sc_regs->stc.gscr1 >> 2) & 7; + sp = &sc->sc_ttys->sc_port[channel]; + ptr = sp->sp_rput; + for (i = sc->sc_regs->stc.rdcr; i > 0; i--) { + *ptr++ = 0; + *ptr++ = sc->sc_regs->stc.rdr; + if (ptr == sp->sp_rend) + ptr = sp->sp_rbuf; + if (ptr == sp->sp_rget) { + if (ptr == sp->sp_rbuf) + ptr = sp->sp_rend; + ptr -= 2; + SET(sp->sp_flags, STTYF_RING_OVERFLOW); + break; + } + } + sp->sp_rput = ptr; + needsoft = 1; + break; + case CD180_GSVR_RXEXCEPTION: + r = 1; + channel = (sc->sc_regs->stc.gscr1 >> 2) & 7; + sp = &sc->sc_ttys->sc_port[channel]; + ptr = sp->sp_rput; + *ptr++ = sc->sc_regs->stc.rcsr; + *ptr++ = sc->sc_regs->stc.rdr; + if (ptr == sp->sp_rend) + ptr = sp->sp_rbuf; + if (ptr == sp->sp_rget) { + if (ptr == sp->sp_rbuf) + ptr = sp->sp_rend; + ptr -= 2; + SET(sp->sp_flags, STTYF_RING_OVERFLOW); + break; + } + sp->sp_rput = ptr; + needsoft = 1; + break; + } + sc->sc_regs->stc.eosrr = 0; + + /* + * Transmit service request + */ + ar = sc->sc_regs->istc.trar & 7; + if (ar == 2) { + int cnt = 0; + + r = 1; + channel = (sc->sc_regs->stc.gscr1 >> 2) & 7; + sp = &sc->sc_ttys->sc_port[channel]; + + if (!ISSET(sp->sp_flags, STTYF_STOP)) { + if (ISSET(sp->sp_flags, STTYF_SET_BREAK)) { + sc->sc_regs->stc.tdr = 0; + sc->sc_regs->stc.tdr = 0x81; + CLR(sp->sp_flags, STTYF_SET_BREAK); + cnt += 2; + } + if (ISSET(sp->sp_flags, STTYF_CLR_BREAK)) { + sc->sc_regs->stc.tdr = 0; + sc->sc_regs->stc.tdr = 0x83; + CLR(sp->sp_flags, STTYF_CLR_BREAK); + cnt += 2; + } + + while (sp->sp_txc > 0 && cnt < (CD180_TX_FIFO_SIZE-1)) { + u_int8_t ch; + + ch = *sp->sp_txp; + sp->sp_txc--; + sp->sp_txp++; + + if (ch == 0) { + sc->sc_regs->stc.tdr = ch; + cnt++; + } + sc->sc_regs->stc.tdr = ch; + cnt++; + } + + if (sp->sp_txc == 0 || + ISSET(sp->sp_flags, STTYF_STOP)) { + sc->sc_regs->stc.srer &= ~CD180_SRER_TXD; + CLR(sp->sp_flags, STTYF_STOP); + SET(sp->sp_flags, STTYF_DONE); + needsoft = 1; + } + } + } + sc->sc_regs->stc.eosrr = 0; + +#if 0 + /* + * Modem signal service request + */ + ar = sc->sc_regs->istc.mrar & 7; + sc->sc_regs->stc.eosrr = 0; +#endif + + if (needsoft) { +#if defined(SUN4M) + if (CPU_ISSUN4M) + raise(0, PIL_TTY); + else +#endif + ienab_bis(IE_MSOFT); + } + return (r); +} + +int +spifsoftintr(vsc) + void *vsc; +{ + struct spif_softc *sc = (struct spif_softc *)vsc; + struct stty_softc *stc = sc->sc_ttys; + int r = 0, i, data, s, flags; + u_int8_t stat; + struct stty_port *sp; + struct tty *tp; + + if (stc != NULL) { + for (i = 0; i < stc->sc_nports; i++) { + sp = &stc->sc_port[i]; + tp = sp->sp_tty; + + if (!ISSET(tp->t_state, TS_ISOPEN)) + continue; + + while (sp->sp_rget != sp->sp_rput) { + stat = sp->sp_rget[0]; + data = sp->sp_rget[1]; + if ((sp->sp_rget + 2) == sp->sp_rend) + sp->sp_rget = sp->sp_rbuf; + else + sp->sp_rget = sp->sp_rget + 2; + + if (stat & (CD180_RCSR_BE | CD180_RCSR_FE)) + data |= TTY_FE; + + if (stat & CD180_RCSR_PE) + data |= TTY_PE; + + if (stat & CD180_RCSR_OE) + log(LOG_WARNING, + "%s%x: fifo overflow\n", + stc->sc_dev, i); + (*linesw[tp->t_line].l_rint)(data, tp); + r = 1; + } + + s = splhigh(); + flags = sp->sp_flags; + CLR(sp->sp_flags, STTYF_DONE | STTYF_CDCHG | + STTYF_RING_OVERFLOW); + splx(s); + + if (ISSET(flags, STTYF_CDCHG)) { + (*linesw[tp->t_line].l_modem)(tp, + sp->sp_carrier); + r = 1; + } + + if (ISSET(flags, STTYF_RING_OVERFLOW)) { + log(LOG_WARNING, "%s%x: ring overflow\n", + stc->sc_dev, i); + r = 1; + } + + if (ISSET(flags, STTYF_DONE)) { + ndflush(&tp->t_outq, + sp->sp_txp - tp->t_outq.c_cf); + CLR(tp->t_state, TS_BUSY); + (*linesw[tp->t_line].l_start)(tp); + r = 1; + } + } + } + + return (r); +} + +int +spif_compute_baud(speed, clock, bprlp, bprhp) + speed_t speed; + int clock; + u_int8_t *bprlp, *bprhp; +{ + u_int32_t rate; + + rate = (2 * clock) / (16 * speed); + if (rate & 1) + rate = (rate >> 1) + 1; + else + rate = rate >> 1; + + if (rate > 0xffff || rate == 0) + return (1); + + *bprlp = rate & 0xff; + *bprhp = (rate >> 8) & 0xff; + return (0); +} + +int +sbppmatch(parent, vcf, aux) + struct device *parent; + void *vcf, *aux; +{ + struct spif_softc *sc = (struct spif_softc *)parent; + + return (aux == sbppmatch && sc->sc_bpps == NULL); +} + +void +sbppattach(parent, dev, aux) + struct device *parent, *dev; + void *aux; +{ + struct spif_softc *sc = (struct spif_softc *)parent; + struct sbpp_softc *psc = (struct sbpp_softc *)dev; + int port; + + sc->sc_bpps = psc; + + for (port = 0; port < sc->sc_npar; port++) { + } + + psc->sc_nports = port; + printf(": %d port%s\n", port, port == 1 ? "" : "s"); +} + +int +sbppopen(dev, flags, mode, p) + dev_t dev; + int flags; + int mode; + struct proc *p; +{ + return (ENXIO); +} + +int +sbppclose(dev, flags, mode, p) + dev_t dev; + int flags; + int mode; + struct proc *p; +{ + return (ENXIO); +} + +int +spifppcintr(v) + void *v; +{ + return (0); +} + +int +sbppread(dev, uio, flags) + dev_t dev; + struct uio *uio; + int flags; +{ + return (sbpp_rw(dev, uio)); +} + +int +sbppwrite(dev, uio, flags) + dev_t dev; + struct uio *uio; + int flags; +{ + return (sbpp_rw(dev, uio)); +} + +int +sbpp_rw(dev, uio) + dev_t dev; + struct uio *uio; +{ + return (ENXIO); +} + +int +sbppselect(dev, rw, p) + dev_t dev; + int rw; + struct proc *p; +{ + return (ENODEV); +} + +int +sbppioctl(dev, cmd, data, flags, p) + dev_t dev; + u_long cmd; + caddr_t data; + int flags; + struct proc *p; +{ + int error; + + error = ENOTTY; + + return (error); +} + +static __inline void +spif_write_ccr(stc, val) + struct stcregs *stc; + u_int8_t val; +{ + int tries = 100000; + + while (stc->ccr && tries--); + if (tries == 0) + printf("CCR: timeout\n"); + stc->ccr = val; +} diff --git a/sys/arch/sparc/dev/spifreg.h b/sys/arch/sparc/dev/spifreg.h new file mode 100644 index 00000000000..f255bbd367c --- /dev/null +++ b/sys/arch/sparc/dev/spifreg.h @@ -0,0 +1,298 @@ +/* $OpenBSD: spifreg.h,v 1.1 1999/02/01 00:30:42 jason Exp $ */ + +/* + * Copyright (c) 1999 Jason L. Wright (jason@thought.net) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Jason L. Wright + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#define SERIAL_INTR 0 +#define PARALLEL_INTR 1 + +struct ppcregs { + volatile u_int8_t in_pdata; /* input data reg */ + volatile u_int8_t in_pstat; /* input status reg */ + volatile u_int8_t in_pctrl; /* input control reg */ + volatile u_int8_t in_pweird; /* input weird reg */ + volatile u_int8_t out_pdata; /* output data reg */ + volatile u_int8_t out_pstat; /* output status reg */ + volatile u_int8_t out_pctrl; /* output control reg */ + volatile u_int8_t out_pweird; /* output weird reg */ + volatile u_int8_t _unused[500]; /* unused space */ + volatile u_int8_t iack_pdata; /* intr-ack data reg */ + volatile u_int8_t iack_pstat; /* intr-ack status reg */ + volatile u_int8_t iack_pctrl; /* intr-ack control reg */ + volatile u_int8_t iack_pweird; /* intr-ack weird reg */ +}; + +struct stcregs { + volatile u_int8_t _unused0[1]; /* 0x00 unused */ + volatile u_int8_t ccr; /* channel command reg */ + volatile u_int8_t srer; /* service req enable reg */ + volatile u_int8_t cor1; /* channel option reg 1 */ + volatile u_int8_t cor2; /* channel option reg 2 */ + volatile u_int8_t cor3; /* channel option reg 3 */ + volatile u_int8_t ccsr; /* channel cntrl status reg */ + volatile u_int8_t rdcr; /* rx data count reg */ + volatile u_int8_t _unused1[1]; /* 0x08 unused */ + volatile u_int8_t schr1; /* special char reg 1 */ + volatile u_int8_t schr2; /* special char reg 2 */ + volatile u_int8_t schr3; /* special char reg 3 */ + volatile u_int8_t schr4; /* special char reg 4 */ + volatile u_int8_t _unused2[3]; /* 0x0d - 0x0f unused */ + + volatile u_int8_t mcor1; /* modem change option reg 1 */ + volatile u_int8_t mcor2; /* modem change option reg 2 */ + volatile u_int8_t mcr; /* modem change reg */ + volatile u_int8_t _unused3[5]; /* 0x13 - 0x17 unused */ + volatile u_int8_t rtpr; /* rx timeout period reg */ + volatile u_int8_t _unused4[7]; + + volatile u_int8_t _unused5[8]; /* 0x19 - 0x27 unused */ + volatile u_int8_t msvr; /* modem signal value reg */ + volatile u_int8_t msvrts; /* modem sig value rts reg */ + volatile u_int8_t msvdtr; /* modem sig value dtr reg */ + volatile u_int8_t _unused6[5]; /* 0x2b - 0x2f unused */ + + volatile u_int8_t _unused7[1]; /* 0x30 unused */ + volatile u_int8_t rbprh; /* rx bit rate period reg hi */ + volatile u_int8_t rbprl; /* rx bit rate period reg lo */ + volatile u_int8_t rbr; /* rx bit reg */ + volatile u_int8_t _unused8[5]; /* 0x34 - 0x38 unused */ + volatile u_int8_t tbprh; /* tx bit rate period reg hi */ + volatile u_int8_t tbprl; /* tx bit rate period reg lo */ + volatile u_int8_t _unused9[5]; /* 0x34 - 0x38 unused */ + + volatile u_int8_t gsvr; /* global service vector reg */ + volatile u_int8_t gscr1; /* global service chan reg 1 */ + volatile u_int8_t gscr2; /* global service chan reg 2 */ + volatile u_int8_t gscr3; /* global service chan reg 3 */ + volatile u_int8_t _unused10[12]; /* 0x44 - 0x4f unused */ + + volatile u_int8_t _unused11[16]; /* 0x50 - 0x5f unused */ + + volatile u_int8_t _unused12[1]; /* 0x60 unused */ + volatile u_int8_t msmr; /* modem service match reg */ + volatile u_int8_t tsmr; /* tx service match reg */ + volatile u_int8_t rsmr; /* rx service match reg */ + volatile u_int8_t car; /* channel access reg */ + volatile u_int8_t srsr; /* service request stat reg */ + volatile u_int8_t srcr; /* service request conf reg */ + volatile u_int8_t _unused13[4]; /* 0x67 - 0x6a unused */ + volatile u_int8_t gfrcr; /* global firmwr rev code reg */ + volatile u_int8_t _unused14[4]; /* 0x6c - 0x6f unused */ + + volatile u_int8_t pprh; /* prescalar period reg hi */ + volatile u_int8_t pprl; /* prescalar period reg lo */ + volatile u_int8_t _unused15[3]; /* 0x72 - 0x74 unused */ + volatile u_int8_t mrar; /* modem request ack reg */ + volatile u_int8_t trar; /* tx request ack reg */ + volatile u_int8_t rrar; /* rx request ack reg */ + volatile u_int8_t rdr; /* rx data reg */ + volatile u_int8_t _unused16[1]; /* 0x79 unused */ + volatile u_int8_t rcsr; /* rx char status reg */ + volatile u_int8_t tdr; /* tx data reg */ + volatile u_int8_t _unused17[3]; /* 0x7c - 0x7e unused */ + volatile u_int8_t eosrr; /* end of service req reg */ +}; + +/* + * The register for the SUNW,spif looks something like: + * Offset: Function: + * 0000 - 03ff unused + * 0400 - 0408 dtr latches (one per port) + * 0409 - 07ff unused + * 0800 - 087f CD180 registers (normal mapping) + * 0880 - 0bff unused + * 0c00 - 0c7f CD180 registers (*iack mapping) + * 0c80 - 0dff unused + * 0e00 - 1fff PPC registers + */ +struct spifregs { + volatile u_int8_t _unused1[1024]; /* 0x000-0x3ff unused */ + volatile u_int8_t dtrlatch[8]; /* per port dtr latch */ + volatile u_int8_t _unused2[1016]; /* 0x409-0x7ff unused */ + struct stcregs stc; /* regular cd-180 regs */ + volatile u_int8_t _unused3[896]; /* 0x880-0xbff unused */ + struct stcregs istc; /* *iack cd-180 regs */ + volatile u_int8_t _unused4[384]; /* 0xc80-0xdff unused */ + struct ppcregs ppc; /* parallel port regs */ +}; + +/* The mapping of minor device number -> card and port is done as + * follows by default: + * + * +---+---+---+---+---+---+---+---+ + * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | + * +---+---+---+---+---+---+---+---+ + * | | | | | | | | + * | | | | | +---+---+---> port number + * | | | | | + * | | | | +---------------> unused + * | | | | + * | | | +-------------------> dialout (on tty ports) + * | | | + * | | +-----------------------> unused + * | | + * +---+---------------------------> card number + * + */ + +#define CD180_SRCR_PKGTYP 0x80 /* chip package type */ +#define CD180_SRCR_REGACKEN 0x40 +#define CD180_SRCR_DAISYEN 0x20 +#define CD180_SRCR_GLOBPRI 0x10 +#define CD180_SRCR_UNFAIR 0x08 +#define CD180_SRCR_AUTOPRI 0x04 +#define CD180_SRCR_reserved 0x02 +#define CD180_SRCR_PRISEL 0x01 + +#define CD180_CCR_RESET 0x80 /* chip/channel reset */ +#define CD180_CCR_RESETALL 0x01 /* global reset */ +#define CD180_CCR_RESETCHAN 0x00 /* current channel reset */ + +#define CD180_CCR_CORCHG 0x40 /* channel option reg has changed */ +#define CD180_CCR_CORCHG1 0x02 /* cor1 has changed */ +#define CD180_CCR_CORCHG2 0x04 /* cor2 has changed */ +#define CD180_CCR_CORCHG3 0x08 /* cor3 has changed */ + +#define CD180_CCR_SENDSPCHG 0x20 +#define CD180_CCR_SSPC0 0x01 +#define CD180_CCR_SSPC1 0x02 +#define CD180_CCR_SSPC2 0x04 + +#define CD180_CCR_CHANCTL 0x10 /* channel control command */ +#define CD180_CCR_CHAN_TXEN 0x08 /* enable channel tx */ +#define CD180_CCR_CHAN_TXDIS 0x04 /* disable channel tx */ +#define CD180_CCR_CHAN_RXEN 0x02 /* enable channel rx */ +#define CD180_CCR_CHAN_RXDIS 0x01 /* disable channel rx */ + +#define CD180_COR1_EVENPAR 0x00 /* even parity */ +#define CD180_COR1_ODDPAR 0x80 /* odd parity */ +#define CD180_COR1_PARMODE_NO 0x00 /* no parity */ +#define CD180_COR1_PARMODE_FORCE 0x20 /* force (odd=1, even=0) */ +#define CD180_COR1_PARMODE_NORMAL 0x40 /* normal parity mode */ +#define CD180_COR1_PARMODE_NA 0x60 /* notused */ +#define CD180_COR1_IGNPAR 0x10 /* ignore parity */ +#define CD180_COR1_STOP1 0x00 /* 1 stop bit */ +#define CD180_COR1_STOP15 0x04 /* 1.5 stop bits */ +#define CD180_COR1_STOP2 0x08 /* 2 stop bits */ +#define CD180_COR1_STOP25 0x0c /* 2.5 stop bits */ +#define CD180_COR1_CS5 0x00 /* 5 bit characters */ +#define CD180_COR1_CS6 0x01 /* 6 bit characters */ +#define CD180_COR1_CS7 0x02 /* 7 bit characters */ +#define CD180_COR1_CS8 0x03 /* 8 bit characters */ + +#define CD180_COR2_IXM 0x80 /* implied xon mode */ +#define CD180_COR2_TXIBE 0x40 /* tx in-band flow control */ +#define CD180_COR2_ETC 0x20 /* embedded tx command enbl */ +#define CD180_COR2_LLM 0x10 /* local loopback mode */ +#define CD180_COR2_RLM 0x08 /* remote loopback mode */ +#define CD180_COR2_RTSAO 0x04 /* RTS automatic output enbl */ +#define CD180_COR2_CTSAE 0x02 /* CTS automatic enable */ +#define CD180_COR2_DSRAE 0x01 /* DSR automatic enable */ + +#define CD180_MCOR1_DSRZD 0x80 /* catch 0->1 DSR changes */ +#define CD180_MCOR1_CDZD 0x40 /* catch 0->1 CD changes */ +#define CD180_MCOR1_CTSZD 0x40 /* catch 0->1 CTS changes */ +#define CD180_MCOR1_DTRTHRESH 0x0f /* DTR threshold mask */ + +#define CD180_MCOR2_DSROD 0x80 /* catch 1->0 DSR changes */ +#define CD180_MCOR2_CDOD 0x40 /* catch 1->0 CD changes */ +#define CD180_MCOR2_CTSOD 0x20 /* catch 1->0 CTS changes */ + +#define CD180_SRER_DSR 0x80 /* DSR service request */ +#define CD180_SRER_CD 0x40 /* CD service request */ +#define CD180_SRER_CTS 0x20 /* CTS service request */ +#define CD180_SRER_RXD 0x10 /* RXD service request */ +#define CD180_SRER_RXSCD 0x08 /* RX special char request */ +#define CD180_SRER_TXD 0x04 /* TX ready service request */ +#define CD180_SRER_TXE 0x02 /* TX empty service request */ +#define CD180_SRER_NNDT 0x01 /* No new data timeout req */ + +#define CD180_MSVR_DSR 0x80 /* DSR input state */ +#define CD180_MSVR_CD 0x40 /* CD input state */ +#define CD180_MSVR_CTS 0x20 /* CTS input state */ +#define CD180_MSVR_DTR 0x02 /* DTR output state */ +#define CD180_MSVR_RTS 0x01 /* RTS output state */ + +#define CD180_GSVR_IMASK 0x07 /* interrupt type mask */ +#define CD180_GSVR_NOREQUEST 0x00 /* no request pending */ +#define CD180_GSVR_STATCHG 0x01 /* modem signal change */ +#define CD180_GSVR_TXDATA 0x02 /* tx service request */ +#define CD180_GSVR_RXGOOD 0x03 /* rx service request */ +#define CD180_GSVR_reserved1 0x04 +#define CD180_GSVR_reserved2 0x05 +#define CD180_GSVR_reserved3 0x06 +#define CD180_GSVR_RXEXCEPTION 0x07 /* rx exception request */ + +#define STTY_RX_FIFO_THRESHOLD 6 +#define STTY_RX_DTR_THRESHOLD 9 + +#define CD180_RCSR_TO 0x80 /* time out */ +#define CD180_RCSR_SCD2 0x40 /* special char detect 2 */ +#define CD180_RCSR_SCD1 0x20 /* special char detect 1 */ +#define CD180_RCSR_SCD0 0x10 /* special char detect 0 */ +#define CD180_RCSR_BE 0x08 /* break exception */ +#define CD180_RCSR_PE 0x04 /* parity exception */ +#define CD180_RCSR_FE 0x02 /* framing exception */ +#define CD180_RCSR_OE 0x01 /* overrun exception */ + +#define CD180_TX_FIFO_SIZE 8 /* 8 chars of fifo */ +/* + * These are the offsets of the MRAR,TRAR, and RRAR in *IACK space. + * The high bit must be set as per specs for the MSMR, TSMR, and RSMR. + */ +#define SPIF_MSMR 0xf5 /* offset of MRAR | 0x80 */ +#define SPIF_TSMR 0xf6 /* offset of TRAR | 0x80 */ +#define SPIF_RSMR 0xf7 /* offset of RRAR | 0x80 */ + +#define SPIF_MAX_CARDS 4 +#define SPIF_MAX_TTY 8 +#define SPIF_MAX_BPP 1 + +#define SPIF_CARD(x) ((minor(x) >> 6) & 0x03) +#define SPIF_PORT(x) (minor(x) & 0x0f) + +#define STTY_DIALOUT(x) (minor(x) & 0x10) + +/* "verosc" node tells which oscillator we have. */ +#define SPIF_OSC9 1 /* 9.8304 Mhz */ +#define SPIF_OSC10 2 /* 10Mhz */ + +#define SPIF_PPRH 0xf0 +#define SPIF_PPRL 0x00 + +#define STTYF_CDCHG 0x01 /* carrier changed */ +#define STTYF_RING_OVERFLOW 0x02 /* ring buffer overflowed */ +#define STTYF_DONE 0x04 /* done... flush buffers */ +#define STTYF_SET_BREAK 0x08 /* set break signal */ +#define STTYF_CLR_BREAK 0x10 /* clear break signal */ +#define STTYF_STOP 0x20 /* stopped */ + +#define STTY_RBUF_SIZE (2 * 512) diff --git a/sys/arch/sparc/dev/spifvar.h b/sys/arch/sparc/dev/spifvar.h new file mode 100644 index 00000000000..1db8c16cab5 --- /dev/null +++ b/sys/arch/sparc/dev/spifvar.h @@ -0,0 +1,81 @@ +/* $OpenBSD: spifvar.h,v 1.1 1999/02/01 00:30:42 jason Exp $ */ + +/* + * Copyright (c) 1999 Jason L. Wright (jason@thought.net) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Jason L. Wright + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#define SPIF_MAX_SERIAL 8 +#define SPIF_MAX_PARALLEL 1 + +struct stty_port { + struct tty *sp_tty; /* tty device */ + struct spif_softc *sp_sc; /* pointer back to registers */ + int sp_channel; /* channel number */ + u_char *sp_rbuf; /* ring buffer start */ + u_char *sp_rend; /* ring buffer end */ + u_char *sp_rget; /* ring buffer read pointer */ + u_char *sp_rput; /* ring buffer write pointer */ + u_char *sp_txp; /* transmit character pointer */ + int sp_txc; /* transmit character counter */ + + int sp_openflags; + int sp_carrier; + int sp_flags; + char sp_dtr; /* software dtr status */ +}; + +struct stty_softc { + struct device sc_dev; /* base device */ + int sc_nports; /* number of serial ports */ + struct stty_port sc_port[SPIF_MAX_SERIAL]; +}; + +struct sbpp_softc { + struct device sc_dev; /* base device */ + int sc_nports; /* number of parallel ports */ +}; + +struct spif_softc { + struct device sc_dev; /* base device */ + struct sbusdev sc_sd; /* sbus device */ + struct intrhand sc_stcih; /* stc interrupt vectoring */ + struct intrhand sc_ppcih; /* ppc interrupt vectoring */ + struct intrhand sc_softih; /* hard interrupt vectoring */ + int sc_rev; /* revision level */ + int sc_osc; /* oscillator speed (mhz) */ + int sc_node; /* which sbus node */ + int sc_nser; /* number of serial ports */ + int sc_npar; /* number of parallel ports */ + unsigned sc_rev2; /* onboard chip revision */ + struct spifregs *sc_regs; /* registers */ + struct stty_softc *sc_ttys; /* our ttys */ + struct sbpp_softc *sc_bpps; /* our ttys */ +}; + diff --git a/sys/arch/sparc/include/conf.h b/sys/arch/sparc/include/conf.h index f378b2ffdf2..77039f962ca 100644 --- a/sys/arch/sparc/include/conf.h +++ b/sys/arch/sparc/include/conf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: conf.h,v 1.8 1998/12/29 09:33:36 deraadt Exp $ */ +/* $OpenBSD: conf.h,v 1.9 1999/02/01 00:30:43 jason Exp $ */ /* $NetBSD: conf.h,v 1.8 1996/12/31 07:12:43 mrg Exp $ */ /* @@ -106,4 +106,7 @@ cdev_decl(bpp); cdev_decl(mtty); cdev_decl(mbpp); +cdev_decl(stty); +cdev_decl(sbpp); + cdev_decl(ksyms); diff --git a/sys/arch/sparc/sparc/conf.c b/sys/arch/sparc/sparc/conf.c index e19be3c2471..9860c9de645 100644 --- a/sys/arch/sparc/sparc/conf.c +++ b/sys/arch/sparc/sparc/conf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: conf.c,v 1.20 1998/12/29 09:33:36 deraadt Exp $ */ +/* $OpenBSD: conf.c,v 1.21 1999/02/01 00:30:43 jason Exp $ */ /* $NetBSD: conf.c,v 1.40 1996/04/11 19:20:03 thorpej Exp $ */ /* @@ -83,6 +83,8 @@ #include "xy.h" #include "bpp.h" #include "magma.h" /* has NMTTY and NMBPP */ +#include "spif.h" /* has NSTTY and NSBPP */ + #ifdef XFS #include <xfs/nxfs.h> cdev_decl(xfs_dev); @@ -227,8 +229,8 @@ struct cdevsw cdevsw[] = cdev_fb_init(NCGFOURTEEN,cgfourteen), /* 99: /dev/cgfourteen */ cdev_tty_init(NMTTY,mtty), /* 100 */ cdev_gen_init(NMBPP,mbpp), /* 101 */ - cdev_notdef(), /* 102 */ - cdev_notdef(), /* 103 */ + cdev_tty_init(NSTTY,stty), /* 102 */ + cdev_gen_init(NSBPP,sbpp), /* 103 */ cdev_bpp_init(NBPP,bpp), /* 104: bpp */ cdev_bpftun_init(NBPFILTER,bpf),/* 105: packet filter */ cdev_disk_init(NRD,rd), /* 106: ram disk driver */ |