diff options
Diffstat (limited to 'sys/arch/vax/uba')
-rw-r--r-- | sys/arch/vax/uba/dhu.c | 858 | ||||
-rw-r--r-- | sys/arch/vax/uba/dhureg.h | 140 | ||||
-rw-r--r-- | sys/arch/vax/uba/dz.c | 819 | ||||
-rw-r--r-- | sys/arch/vax/uba/dzreg.h | 116 | ||||
-rw-r--r-- | sys/arch/vax/uba/tmscp.c | 171 | ||||
-rw-r--r-- | sys/arch/vax/uba/ts.c | 140 | ||||
-rw-r--r-- | sys/arch/vax/uba/uba.c | 476 | ||||
-rw-r--r-- | sys/arch/vax/uba/ubareg.h | 8 | ||||
-rw-r--r-- | sys/arch/vax/uba/ubavar.h | 48 | ||||
-rw-r--r-- | sys/arch/vax/uba/uda.c | 82 |
10 files changed, 2440 insertions, 418 deletions
diff --git a/sys/arch/vax/uba/dhu.c b/sys/arch/vax/uba/dhu.c new file mode 100644 index 00000000000..807cbb3aec8 --- /dev/null +++ b/sys/arch/vax/uba/dhu.c @@ -0,0 +1,858 @@ +/* $NetBSD: dhu.c,v 1.4 1996/04/08 18:37:28 ragge Exp $ */ +/* + * Copyright (c) 1996 Ken C. Wellsch. All rights reserved. + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Ralph Campbell and Rick Macklem. + * + * 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 the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. + */ + +#include "dhu.h" + +#if NDHU > 0 + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/ioctl.h> +#include <sys/tty.h> +#include <sys/proc.h> +#include <sys/map.h> +#include <sys/buf.h> +#include <sys/conf.h> +#include <sys/file.h> +#include <sys/uio.h> +#include <sys/kernel.h> +#include <sys/syslog.h> +#include <sys/device.h> + +#include <machine/trap.h> + +#include <vax/uba/ubavar.h> + +#include <vax/uba/dhureg.h> + +/* A DHU has 16 ports while a DHV has only 8 */ + +#define NDHULINE (NDHU*16) + +/* This is an experiment to try and fake DHU behavior with a DHV. + * The DHV does not have any programmable delay on input silo level + * but interrupts immediately when the first character enters. + * This is really kludgy and so I doubt it will stay. From what could + * be measured, doing a timeout() delay reduced the input interrupt + * rate by an order of magnitude (from over 700 to at most 30) with + * heavy input (e.g. via kermit). Input performance increased 5% too + * as more CPU cycles were available for the application to consume input. + */ + +#define RX_DELAY 0 /* ticks to delay RX intr handling */ + +struct dhu_softc +{ + dhuregs * sc_addr; /* controller reg address */ + struct tty * sc_tty; /* what we work on */ + unsigned sc_txaddr; /* UBA map address to TX buf */ + u_char sc_type; /* controller type, DHU or DHV */ + u_char sc_state; /* to manage TX output status */ + u_short sc_cc; /* character count on TX */ + u_short sc_modem; /* modem bits state */ +}; + +struct dhu_softc dhu_softc[NDHULINE]; + +#define IS_DHU 0 /* cntlr is a DHU */ +#define IS_DHV 1 /* cntlr is a DHV */ + +#define STATE_IDLE 000 /* no current output in progress */ +#define STATE_DMA_RUNNING 001 /* DMA TX in progress */ +#define STATE_DMA_STOPPED 002 /* DMA TX was aborted */ +#define STATE_TX_ONE_CHAR 004 /* did a single char directly */ + +/* Flags used to monitor modem bits, make them understood outside driver */ + +#define DML_DTR TIOCM_DTR +#define DML_RTS TIOCM_RTS +#define DML_CTS TIOCM_CTS +#define DML_DCD TIOCM_CD +#define DML_RI TIOCM_RI +#define DML_DSR TIOCM_DSR +#define DML_BRK 0100000 /* no equivalent, we will mask */ + +/* On a stock DHV, channel pairs (0/1, 2/3, etc.) must use */ +/* a baud rate from the same group. So limiting to B is likely */ +/* best, although clone boards like the ABLE QHV allow all settings. */ + +static struct speedtab dhuspeedtab[] = +{ + { 0, 0 }, /* Groups */ + { 50, DHU_LPR_B50 }, /* A */ + { 75, DHU_LPR_B75 }, /* B */ + { 110, DHU_LPR_B110 }, /* A and B */ + { 134, DHU_LPR_B134 }, /* A and B */ + { 150, DHU_LPR_B150 }, /* B */ + { 300, DHU_LPR_B300 }, /* A and B */ + { 600, DHU_LPR_B600 }, /* A and B */ + { 1200, DHU_LPR_B1200 }, /* A and B */ + { 1800, DHU_LPR_B1800 }, /* B */ + { 2000, DHU_LPR_B2000 }, /* B */ + { 2400, DHU_LPR_B2400 }, /* A and B */ + { 4800, DHU_LPR_B4800 }, /* A and B */ + { 7200, DHU_LPR_B7200 }, /* A */ + { 9600, DHU_LPR_B9600 }, /* A and B */ + { 19200, DHU_LPR_B19200 }, /* B */ + { 38400, DHU_LPR_B38400 }, /* A */ + { -1, -1 } +}; + +static int dhu_match __P((struct device *, void *, void *)); +static void dhu_attach __P((struct device *, struct device *, void *)); + +struct cfdriver dhu_cd = { + NULL, "dhu", DV_TTY +}; + +struct cfattach dhu_ca = { + sizeof(struct device), dhu_match, dhu_attach +}; + +static void dhurint __P((int)); +static void dhuxint __P((int)); +static void dhustart __P((struct tty *)); +static int dhuparam __P((struct tty *, struct termios *)); +static int dhuiflow __P((struct tty *, int)); + int dhustop __P((struct tty *, int)); +static unsigned dhumctl __P((int, int, int)); + int dhuopen __P((dev_t, int, int, struct proc *)); + int dhuclose __P((dev_t, int, int, struct proc *)); + int dhuread __P((dev_t, struct uio *, int)); + int dhuwrite __P((dev_t, struct uio *, int)); + int dhuioctl __P((dev_t, u_long, caddr_t, int, struct proc *)); +struct tty * dhutty __P((dev_t)); + + +/* Autoconfig handles: setup the controller to interrupt, */ +/* then complete the housecleaning for full operation */ + +static int +dhu_match (parent, match, aux) + struct device *parent; + void *match, *aux; +{ + struct uba_attach_args *ua = aux; + static int nunits = 0; + register dhuregs *dhuaddr; + register int n; + + if (nunits > NDHU) + return 0; + + dhuaddr = (dhuregs *) ua->ua_addr; + + /* Reset controller to initialize, enable TX/RX interrupts */ + /* to catch floating vector info elsewhere when completed */ + + dhuaddr->dhu_csr = (DHU_CSR_MASTER_RESET | DHU_CSR_RXIE | DHU_CSR_TXIE); + + /* Now wait up to 3 seconds for self-test to complete. */ + + for (n = 0; n < 300; n++) { + DELAY(10000); + if ((dhuaddr->dhu_csr & DHU_CSR_MASTER_RESET) == 0) + break; + } + + /* If the RESET did not clear after 3 seconds, */ + /* the controller must be broken. */ + + if (n >= 300) + return 0; + + /* Check whether diagnostic run has signalled a failure. */ + + if ((dhuaddr->dhu_csr & DHU_CSR_DIAG_FAIL) != 0) + return 0; + + /* Register the RX interrupt handler and pass unit # as arg */ + + ua->ua_ivec = dhurint; + + nunits++; + return 1; +} + +static void +dhu_attach (parent, self, aux) + struct device *parent, *self; + void *aux; +{ + register struct uba_attach_args *ua = aux; + register dhuregs *dhuaddr; + register unsigned c; + register int n, m; + + dhuaddr = (dhuregs *) ua->ua_addr; + + /* Process the 8 bytes of diagnostic info put into */ + /* the FIFO following the master reset operation. */ + + printf ("\ndhv%d:", self->dv_unit); + for (n = 0; n < 8; n++) { + c = dhuaddr->dhu_rbuf; + + if ((c&DHU_DIAG_CODE) == DHU_DIAG_CODE) { + if ((c&0200) == 0000) + printf (" rom(%d) version %d", + ((c>>1)&01), ((c>>2)&037)); + else if (((c>>2)&07) != 0) + printf (" diag-error(proc%d)=%x", + ((c>>1)&01), ((c>>2)&07)); + } + } + printf ("\n"); + + /* Initialize our static softc structure. */ + + c = dhuaddr->dhu_stat; /* get flag to distinguish DHU from DHV */ + + for (n = 0; n < ((c & DHU_STAT_DHU)? 16: 8); n++) { + m = ((self->dv_unit) << 4) + n; + dhu_softc[m].sc_addr = dhuaddr; + dhu_softc[m].sc_tty = ttymalloc(); + dhu_softc[m].sc_type = (c & DHU_STAT_DHU)? IS_DHU: IS_DHV; + dhu_softc[m].sc_state = STATE_IDLE; + + dhu_softc[m].sc_txaddr = uballoc (parent->dv_unit, + dhu_softc[m].sc_tty->t_outq.c_cs, + dhu_softc[m].sc_tty->t_outq.c_cn, + UBA_CANTWAIT); + } + + /* Now stuff TX interrupt handler in place */ + + ubasetvec (self, ua->ua_cvec+1, dhuxint); + return; +} + +/* Receiver Interrupt */ + +#if RX_DELAY > 0 + +static int RXtimeout = 0; + +static void +dhurint (cntlr) + int cntlr; +{ + static void dhuRXint __P((void *)); + if (RXtimeout == 0) { + RXtimeout = 1; + timeout (dhuRXint, (void *)cntlr, RX_DELAY); + } + return; +} + +static void +dhuRXint (arg) + void * arg; +{ + +#else + +static void +dhurint (cntlr) + int cntlr; +{ + +#endif + register dhuregs *dhuaddr; + register struct tty *tp; + register int cc, unit; + register unsigned c, delta; + int overrun = 0; +#if RX_DELAY > 0 + int cntlr = (int) arg; + int s; + + s = spltty(); +#endif + + dhuaddr = dhu_softc[cntlr].sc_addr; + + while ((c = dhuaddr->dhu_rbuf) & DHU_RBUF_DATA_VALID) + { + /* Ignore diagnostic FIFO entries. */ + + if ((c&DHU_DIAG_CODE) == DHU_DIAG_CODE) + continue; + + cc = c & 0xff; + unit = (cntlr<<4) | ((c>>8)&017); + tp = dhu_softc[unit].sc_tty; + + /* LINK.TYPE is set so we get modem control FIFO entries */ + + if ((c & DHU_DIAG_CODE) == DHU_MODEM_CODE) { + c = (c << 8); + /* Do MDMBUF flow control, wakeup sleeping opens */ + if (c & DHU_STAT_DCD) { + if (!(tp->t_state & TS_CARR_ON)) + (void)(*linesw[tp->t_line].l_modem)(tp, 1); + } + else if ((tp->t_state & TS_CARR_ON) && + (*linesw[tp->t_line].l_modem)(tp, 0) == 0) + (void) dhumctl (unit, 0, DMSET); + + /* Do CRTSCTS flow control */ + delta = c ^ dhu_softc[unit].sc_modem; + dhu_softc[unit].sc_modem = c; + if ((delta & DHU_STAT_CTS) && + (tp->t_state & TS_ISOPEN) && + (tp->t_cflag & CRTSCTS)) { + if (c & DHU_STAT_CTS) { + tp->t_state &= ~TS_TTSTOP; + ttstart (tp); + } else { + tp->t_state |= TS_TTSTOP; + dhustop (tp, 0); + } + } + continue; + } + + if ((c & DHU_RBUF_OVERRUN_ERR) && overrun == 0) { + log(LOG_WARNING, "dhv(%d,%d): silo overflow\n", + cntlr, (c >> 8) & 017); + overrun = 1; + } + /* A BREAK key will appear as a NULL with a framing error */ + if (c & DHU_RBUF_FRAMING_ERR) + cc |= TTY_FE; + if (c & DHU_RBUF_PARITY_ERR) + cc |= TTY_PE; + + (*linesw[tp->t_line].l_rint)(cc, tp); + } +#if RX_DELAY > 0 + RXtimeout = 0; + (void) splx(s); +#endif + return; +} + +/* Transmitter Interrupt */ + +static void +dhuxint (cntlr) + int cntlr; +{ + register dhuregs *dhuaddr; + register struct dhu_softc *sc; + register struct tty *tp; + register unsigned csr; + register int unit; + + dhuaddr = dhu_softc[cntlr].sc_addr; + + csr = (dhuaddr->dhu_csr_hi) << 8; + + unit = (cntlr<<4)|((csr>>8)&017); + + sc = &dhu_softc[unit]; + + tp = sc->sc_tty; + + tp->t_state &= ~TS_BUSY; + if (tp->t_state & TS_FLUSH) + tp->t_state &= ~TS_FLUSH; + else { + if (sc->sc_state == STATE_DMA_STOPPED) + sc->sc_cc -= dhuaddr->dhu_tbufcnt; + ndflush (&tp->t_outq, sc->sc_cc); + sc->sc_cc = 0; + } + + sc->sc_state = STATE_IDLE; + + if (tp->t_line) + (*linesw[tp->t_line].l_start)(tp); + else + dhustart (tp); + + return; +} + +int +dhuopen (dev, flag, mode, p) + dev_t dev; + int flag, mode; + struct proc *p; +{ + register struct tty *tp; + register int unit; + int s, error = 0; + + unit = minor(dev); + if (unit >= NDHULINE) + return (ENXIO); + tp = dhu_softc[unit].sc_tty; + if (tp == NULL) + tp = dhu_softc[unit].sc_tty = ttymalloc(); + tp->t_oproc = dhustart; + tp->t_param = dhuparam; + tp->t_hwiflow = dhuiflow; + tp->t_dev = dev; + if ((tp->t_state & TS_ISOPEN) == 0) { + tp->t_state |= TS_WOPEN; + ttychars(tp); + if (tp->t_ispeed == 0) { + tp->t_iflag = TTYDEF_IFLAG; + tp->t_oflag = TTYDEF_OFLAG; + tp->t_cflag = TTYDEF_CFLAG; + tp->t_lflag = TTYDEF_LFLAG; + tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; + } + (void) dhuparam(tp, &tp->t_termios); + ttsetwater(tp); + } else if ((tp->t_state & TS_XCLUDE) && curproc->p_ucred->cr_uid != 0) + return (EBUSY); + /* Use DMBIS and *not* DMSET or else we clobber incoming bits */ + if (dhumctl (unit, DML_DTR|DML_RTS, DMBIS) & DML_DCD) + tp->t_state |= TS_CARR_ON; + s = spltty(); + while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) && + !(tp->t_state & TS_CARR_ON)) { + tp->t_state |= TS_WOPEN; + error = ttysleep(tp, (caddr_t)&tp->t_rawq, + TTIPRI | PCATCH, ttopen, 0); + if (error) + break; + } + (void) splx(s); + if (error) + return (error); + return ((*linesw[tp->t_line].l_open)(dev, tp)); +} + +/*ARGSUSED*/ +int +dhuclose (dev, flag, mode, p) + dev_t dev; + int flag, mode; + struct proc *p; +{ + register struct tty *tp; + register int unit = minor(dev); + + tp = dhu_softc[unit].sc_tty; + + (*linesw[tp->t_line].l_close)(tp, flag); + + /* Make sure a BREAK state is not left enabled. */ + + (void) dhumctl (unit, DML_BRK, DMBIC); + + /* Do a hangup if so required. */ + + if ((tp->t_cflag & HUPCL) || (tp->t_state & TS_WOPEN) || + !(tp->t_state & TS_ISOPEN)) + (void) dhumctl (unit, 0, DMSET); + + return (ttyclose(tp)); +} + +int +dhuread (dev, uio, flag) + dev_t dev; + struct uio *uio; +{ + register struct tty *tp; + + tp = dhu_softc[minor(dev)].sc_tty; + return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); +} + +int +dhuwrite (dev, uio, flag) + dev_t dev; + struct uio *uio; +{ + register struct tty *tp; + + tp = dhu_softc[minor(dev)].sc_tty; + return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); +} + +/*ARGSUSED*/ +int +dhuioctl (dev, cmd, data, flag, p) + dev_t dev; + u_long cmd; + caddr_t data; + int flag; + struct proc *p; +{ + register struct tty *tp; + register int unit = minor(dev); + int error; + + tp = dhu_softc[unit].sc_tty; + error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); + if (error >= 0) + return (error); + error = ttioctl(tp, cmd, data, flag, p); + if (error >= 0) + return (error); + + switch (cmd) { + + case TIOCSBRK: + (void) dhumctl (unit, DML_BRK, DMBIS); + break; + + case TIOCCBRK: + (void) dhumctl (unit, DML_BRK, DMBIC); + break; + + case TIOCSDTR: + (void) dhumctl (unit, DML_DTR|DML_RTS, DMBIS); + break; + + case TIOCCDTR: + (void) dhumctl (unit, DML_DTR|DML_RTS, DMBIC); + break; + + case TIOCMSET: + (void) dhumctl (unit, *(int *)data, DMSET); + break; + + case TIOCMBIS: + (void) dhumctl (unit, *(int *)data, DMBIS); + break; + + case TIOCMBIC: + (void) dhumctl (unit, *(int *)data, DMBIC); + break; + + case TIOCMGET: + *(int *)data = (dhumctl (unit, 0, DMGET) & ~DML_BRK); + break; + + default: + return (ENOTTY); + } + return (0); +} + +struct tty * +dhutty (dev) + dev_t dev; +{ + struct tty *tp = dhu_softc[minor(dev)].sc_tty; + return (tp); +} + +/*ARGSUSED*/ +int +dhustop (tp, flag) + register struct tty *tp; +{ + register dhuregs *dhuaddr; + register struct dhu_softc *sc; + int unit = minor(tp->t_dev); + int s; + + s = spltty(); + + if (tp->t_state & TS_BUSY) + { + sc = &dhu_softc[unit]; + + if (sc->sc_state == STATE_DMA_RUNNING) + { + sc->sc_state = STATE_DMA_STOPPED; + + dhuaddr = sc->sc_addr; + dhuaddr->dhu_csr_lo = (DHU_CSR_RXIE | (unit & 017)); + dhuaddr->dhu_lnctrl |= DHU_LNCTRL_DMA_ABORT; + } + + if (!(tp->t_state & TS_TTSTOP)) + tp->t_state |= TS_FLUSH; + } + (void) splx(s); + return 0; +} + +static void +dhustart (tp) + register struct tty *tp; +{ + register struct dhu_softc *sc; + register dhuregs *dhuaddr; + register int unit = minor(tp->t_dev); + register unsigned addr; + register int cc; + int s; + + s = spltty(); + if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) + goto out; + if (tp->t_outq.c_cc <= tp->t_lowat) { + if (tp->t_state & TS_ASLEEP) { + tp->t_state &= ~TS_ASLEEP; + wakeup((caddr_t)&tp->t_outq); + } + selwakeup(&tp->t_wsel); + } + if (tp->t_outq.c_cc == 0) + goto out; + cc = ndqb(&tp->t_outq, 0); + if (cc == 0) + goto out; + + tp->t_state |= TS_BUSY; + + sc = &dhu_softc[unit]; + + dhuaddr = sc->sc_addr; + dhuaddr->dhu_csr_lo = (DHU_CSR_RXIE | (unit & 017)); + + sc->sc_cc = cc; + + if (cc == 1) + { + sc->sc_state = STATE_TX_ONE_CHAR; + dhuaddr->dhu_txchar = DHU_TXCHAR_DATA_VALID | *tp->t_outq.c_cf; + } + else + { + sc->sc_state = STATE_DMA_RUNNING; + + addr = UBAI_ADDR(sc->sc_txaddr) + + (tp->t_outq.c_cf - tp->t_outq.c_cs); + + dhuaddr->dhu_tbufcnt = cc; + dhuaddr->dhu_tbufad1 = (addr & 0xffff); + dhuaddr->dhu_tbufad2 = ((addr>>16) & 0x3f) | + DHU_TBUFAD2_TX_ENABLE; + + dhuaddr->dhu_lnctrl &= ~DHU_LNCTRL_DMA_ABORT; + dhuaddr->dhu_tbufad2 |= DHU_TBUFAD2_DMA_START; + } +out: + (void) splx(s); + return; +} + +static int +dhuparam (tp, t) + register struct tty *tp; + register struct termios *t; +{ + register dhuregs *dhuaddr; + register int cflag = t->c_cflag; + int unit = minor(tp->t_dev); + int ispeed = ttspeedtab(t->c_ispeed, dhuspeedtab); + int ospeed = ttspeedtab(t->c_ospeed, dhuspeedtab); + register unsigned lpr, lnctrl; + int s; + + /* check requested parameters */ + if (ospeed < 0 || ispeed < 0) + return (EINVAL); + + tp->t_ispeed = t->c_ispeed; + tp->t_ospeed = t->c_ospeed; + tp->t_cflag = cflag; + + if (ospeed == 0) { + (void) dhumctl (unit, 0, DMSET); /* hang up line */ + return (0); + } + + s = spltty(); + dhuaddr = dhu_softc[unit].sc_addr; + dhuaddr->dhu_csr_lo = (DHU_CSR_RXIE | (unit & 017)); + + lpr = ((ispeed&017)<<8) | ((ospeed&017)<<12) ; + + switch (cflag & CSIZE) + { + case CS5: + lpr |= DHU_LPR_5_BIT_CHAR; + break; + case CS6: + lpr |= DHU_LPR_6_BIT_CHAR; + break; + case CS7: + lpr |= DHU_LPR_7_BIT_CHAR; + break; + default: + lpr |= DHU_LPR_8_BIT_CHAR; + break; + } + if (cflag & PARENB) + lpr |= DHU_LPR_PARENB; + if (!(cflag & PARODD)) + lpr |= DHU_LPR_EPAR; + if (cflag & CSTOPB) + lpr |= DHU_LPR_2_STOP; + + dhuaddr->dhu_lpr = lpr; + + dhuaddr->dhu_tbufad2 |= DHU_TBUFAD2_TX_ENABLE; + + lnctrl = dhuaddr->dhu_lnctrl; + + /* Setting LINK.TYPE enables modem signal change interrupts. */ + + lnctrl |= (DHU_LNCTRL_RX_ENABLE | DHU_LNCTRL_LINK_TYPE); + + if (t->c_iflag & IXON) + lnctrl |= DHU_LNCTRL_OAUTO; + else + lnctrl &= ~DHU_LNCTRL_OAUTO; + + if (t->c_iflag & IXOFF) + lnctrl |= DHU_LNCTRL_IAUTO; + else + lnctrl &= ~DHU_LNCTRL_IAUTO; + + dhuaddr->dhu_lnctrl = lnctrl; + + dhu_softc[unit].sc_modem = dhuaddr->dhu_stat; + + (void) splx(s); + return (0); +} + +static int +dhuiflow (tp, flag) + struct tty *tp; + int flag; +{ + int unit = minor(tp->t_dev); + + if (tp->t_cflag & CRTSCTS) { + (void) dhumctl (unit, DML_RTS, ((flag)? DMBIC: DMBIS)); + return (1); + } + return (0); +} + +static unsigned +dhumctl (unit, bits, how) + int unit, bits, how; +{ + register dhuregs *dhuaddr; + register unsigned status; + register unsigned lnctrl; + register unsigned mbits; + int s; + + s = spltty(); + + dhuaddr = dhu_softc[unit].sc_addr; + dhuaddr->dhu_csr_lo = (DHU_CSR_RXIE | (unit & 017)); + + mbits = 0; + + /* external signals as seen from the port */ + + status = dhuaddr->dhu_stat; + + if (status & DHU_STAT_CTS) + mbits |= DML_CTS; + + if (status & DHU_STAT_DCD) + mbits |= DML_DCD; + + if (status & DHU_STAT_DSR) + mbits |= DML_DSR; + + if (status & DHU_STAT_RI) + mbits |= DML_RI; + + /* internal signals/state delivered to port */ + + lnctrl = dhuaddr->dhu_lnctrl; + + if (lnctrl & DHU_LNCTRL_RTS) + mbits |= DML_RTS; + + if (lnctrl & DHU_LNCTRL_DTR) + mbits |= DML_DTR; + + if (lnctrl & DHU_LNCTRL_BREAK) + mbits |= DML_BRK; + + switch (how) + { + case DMSET: + mbits = bits; + break; + + case DMBIS: + mbits |= bits; + break; + + case DMBIC: + mbits &= ~bits; + break; + + case DMGET: + (void) splx(s); + return (mbits); + } + + if (mbits & DML_RTS) + lnctrl |= DHU_LNCTRL_RTS; + else + lnctrl &= ~DHU_LNCTRL_RTS; + + if (mbits & DML_DTR) + lnctrl |= DHU_LNCTRL_DTR; + else + lnctrl &= ~DHU_LNCTRL_DTR; + + if (mbits & DML_BRK) + lnctrl |= DHU_LNCTRL_BREAK; + else + lnctrl &= ~DHU_LNCTRL_BREAK; + + dhuaddr->dhu_lnctrl = lnctrl; + + (void) splx(s); + return (mbits); +} + +#endif /* #if NDHU > 0 */ diff --git a/sys/arch/vax/uba/dhureg.h b/sys/arch/vax/uba/dhureg.h new file mode 100644 index 00000000000..2ecb20291dd --- /dev/null +++ b/sys/arch/vax/uba/dhureg.h @@ -0,0 +1,140 @@ +/* $NetBSD: dhureg.h,v 1.2 1996/03/17 22:51:50 ragge Exp $ */ +/* + * Copyright (c) 1996 Ken C. Wellsch. 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 the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. + */ + +union w_b +{ + u_short word; + struct { + u_char byte_lo; + u_char byte_hi; + } bytes; +}; + +struct DHUregs +{ + volatile union w_b u_csr; /* Control/Status Register (R/W) */ + volatile u_short dhu_rbuf; /* Receive Buffer (R only) */ +#define dhu_txchar dhu_rbuf /* Transmit Character (W only) */ + volatile u_short dhu_lpr; /* Line Parameter Register (R/W) */ + volatile u_short dhu_stat; /* Line Status (R only) */ + volatile u_short dhu_lnctrl; /* Line Control (R/W) */ + volatile u_short dhu_tbufad1; /* Transmit Buffer Address 1 (R/W) */ + volatile u_short dhu_tbufad2; /* Transmit Buffer Address 2 (R/W) */ + volatile u_short dhu_tbufcnt; /* Transmit Buffer Count (R/W) */ +}; + +#define dhu_csr u_csr.word +#define dhu_csr_lo u_csr.bytes.byte_lo +#define dhu_csr_hi u_csr.bytes.byte_hi + +typedef struct DHUregs dhuregs; + +/* CSR bits */ + +#define DHU_CSR_TX_ACTION 0100000 +#define DHU_CSR_TXIE 0040000 +#define DHU_CSR_DIAG_FAIL 0020000 +#define DHU_CSR_TX_DMA_ERROR 0010000 +#define DHU_CSR_TX_LINE_MASK 0007400 +#define DHU_CSR_RX_DATA_AVAIL 0000200 +#define DHU_CSR_RXIE 0000100 +#define DHU_CSR_MASTER_RESET 0000040 +#define DHU_CSR_UNUSED 0000020 +#define DHU_CSR_CHANNEL_MASK 0000017 + +/* RBUF bits */ + +#define DHU_RBUF_DATA_VALID 0100000 +#define DHU_RBUF_OVERRUN_ERR 0040000 +#define DHU_RBUF_FRAMING_ERR 0020000 +#define DHU_RBUF_PARITY_ERR 0010000 +#define DHU_RBUF_RX_LINE_MASK 0007400 + +#define DHU_DIAG_CODE 0070001 +#define DHU_MODEM_CODE 0070000 + +/* TXCHAR bits */ + +#define DHU_TXCHAR_DATA_VALID 0100000 + +/* LPR bits */ + +#define DHU_LPR_B50 0x0 +#define DHU_LPR_B75 0x1 +#define DHU_LPR_B110 0x2 +#define DHU_LPR_B134 0x3 +#define DHU_LPR_B150 0x4 +#define DHU_LPR_B300 0x5 +#define DHU_LPR_B600 0x6 +#define DHU_LPR_B1200 0x7 +#define DHU_LPR_B1800 0x8 +#define DHU_LPR_B2000 0x9 +#define DHU_LPR_B2400 0xA +#define DHU_LPR_B4800 0xB +#define DHU_LPR_B7200 0xC +#define DHU_LPR_B9600 0xD +#define DHU_LPR_B19200 0xE +#define DHU_LPR_B38400 0xF + +#define DHU_LPR_5_BIT_CHAR 0000000 +#define DHU_LPR_6_BIT_CHAR 0000010 +#define DHU_LPR_7_BIT_CHAR 0000020 +#define DHU_LPR_8_BIT_CHAR 0000030 +#define DHU_LPR_PARENB 0000040 +#define DHU_LPR_EPAR 0000100 +#define DHU_LPR_2_STOP 0000200 + +/* STAT bits */ + +#define DHU_STAT_DSR 0100000 +#define DHU_STAT_RI 0020000 +#define DHU_STAT_DCD 0010000 +#define DHU_STAT_CTS 0004000 +#define DHU_STAT_DHU 0000400 + +/* LNCTRL bits */ + +#define DHU_LNCTRL_DMA_ABORT 0000001 +#define DHU_LNCTRL_IAUTO 0000002 +#define DHU_LNCTRL_RX_ENABLE 0000004 +#define DHU_LNCTRL_BREAK 0000010 +#define DHU_LNCTRL_OAUTO 0000020 +#define DHU_LNCTRL_FORCE_XOFF 0000040 +#define DHU_LNCTRL_LINK_TYPE 0000400 +#define DHU_LNCTRL_DTR 0001000 +#define DHU_LNCTRL_RTS 0010000 + +/* TBUFAD2 bits */ + +#define DHU_TBUFAD2_DMA_START 0000200 +#define DHU_TBUFAD2_TX_ENABLE 0100000 diff --git a/sys/arch/vax/uba/dz.c b/sys/arch/vax/uba/dz.c new file mode 100644 index 00000000000..f1636b7f3ef --- /dev/null +++ b/sys/arch/vax/uba/dz.c @@ -0,0 +1,819 @@ +/* $NetBSD: dz.c,v 1.1 1996/04/08 17:22:20 ragge Exp $ */ +/* + * Copyright (c) 1996 Ken C. Wellsch. All rights reserved. + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Ralph Campbell and Rick Macklem. + * + * 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 the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/ioctl.h> +#include <sys/tty.h> +#include <sys/proc.h> +#include <sys/map.h> +#include <sys/buf.h> +#include <sys/conf.h> +#include <sys/file.h> +#include <sys/uio.h> +#include <sys/kernel.h> +#include <sys/syslog.h> +#include <sys/device.h> + +#include <machine/pte.h> +#include <machine/trap.h> + +#include <vax/uba/ubareg.h> +#include <vax/uba/ubavar.h> + +#include <vax/uba/dzreg.h> + +/* A DZ-11 has 8 ports while a DZV/DZQ-11 has only 4. We use 8 by default */ + +#define NDZLINE 8 + +#define DZ_C2I(c) ((c)<<3) /* convert controller # to index */ +#define DZ_I2C(c) ((c)>>3) /* convert minor to controller # */ +#define DZ_PORT(u) ((u)&07) /* extract the port # */ + +struct dz_softc { + struct device sc_dev; /* Autoconf blaha */ + dzregs * sc_addr; /* controller reg address */ + int sc_type; /* DZ11 or DZV11? */ + int sc_rxint; /* Receive interrupt count XXX */ + u_char sc_brk; /* Break asserted on some lines */ + struct { + struct tty * dz_tty; /* what we work on */ + caddr_t dz_mem; /* pointers to clist output */ + caddr_t dz_end; /* allowing pdma action */ + } sc_dz[NDZLINE]; +}; + +/* Flags used to monitor modem bits, make them understood outside driver */ + +#define DML_DTR TIOCM_DTR +#define DML_DCD TIOCM_CD +#define DML_RI TIOCM_RI +#define DML_BRK 0100000 /* no equivalent, we will mask */ + +static struct speedtab dzspeedtab[] = +{ + { 0, 0 }, + { 50, DZ_LPR_B50 }, + { 75, DZ_LPR_B75 }, + { 110, DZ_LPR_B110 }, + { 134, DZ_LPR_B134 }, + { 150, DZ_LPR_B150 }, + { 300, DZ_LPR_B300 }, + { 600, DZ_LPR_B600 }, + { 1200, DZ_LPR_B1200 }, + { 1800, DZ_LPR_B1800 }, + { 2000, DZ_LPR_B2000 }, + { 2400, DZ_LPR_B2400 }, + { 3600, DZ_LPR_B3600 }, + { 4800, DZ_LPR_B4800 }, + { 7200, DZ_LPR_B7200 }, + { 9600, DZ_LPR_B9600 }, + { -1, -1 } +}; + +static int dz_match __P((struct device *, void *, void *)); +static void dz_attach __P((struct device *, struct device *, void *)); +static void dzrint __P((int)); +static void dzxint __P((int)); +static void dzstart __P((struct tty *)); +static int dzparam __P((struct tty *, struct termios *)); +static unsigned dzmctl __P((struct dz_softc *, int, int, int)); +static void dzscan __P((void *)); +struct tty * dztty __P((dev_t)); + int dzopen __P((dev_t, int, int, struct proc *)); + int dzclose __P((dev_t, int, int, struct proc *)); + int dzread __P((dev_t, struct uio *, int)); + int dzwrite __P((dev_t, struct uio *, int)); + int dzioctl __P((dev_t, int, caddr_t, int, struct proc *)); + int dzstop __P((struct tty *, int)); + +struct cfdriver dz_cd = { + NULL, "dz", DV_TTY +}; + +struct cfattach dz_ca = { + sizeof(struct dz_softc), dz_match, dz_attach +}; + + +/* + * The DZ series doesn't interrupt on carrier transitions, + * so we have to use a timer to watch it. + */ +static int dz_timer = 0; /* true if timer started */ + +#define DZ_DZ 8 /* Unibus DZ-11 board linecount */ +#define DZ_DZV 4 /* Q-bus DZV-11 or DZQ-11 */ + +/* Autoconfig handles: setup the controller to interrupt, */ +/* then complete the housecleaning for full operation */ + +static int +dz_match (parent, match, aux) + struct device *parent; + void *match, *aux; +{ + struct uba_attach_args *ua = aux; + register dzregs *dzaddr; + register int n; + + dzaddr = (dzregs *) ua->ua_addr; + + /* Reset controller to initialize, enable TX interrupts */ + /* to catch floating vector info elsewhere when completed */ + + dzaddr->dz_csr = (DZ_CSR_MSE | DZ_CSR_TXIE); + dzaddr->dz_tcr = 1; /* Force a TX interrupt */ + + DELAY(100000); /* delay 1/10 second */ + + dzaddr->dz_csr = DZ_CSR_RESET; + + /* Now wait up to 3 seconds for reset/clear to complete. */ + + for (n = 0; n < 300; n++) { + DELAY(10000); + if ((dzaddr->dz_csr & DZ_CSR_RESET) == 0) + break; + } + + /* If the RESET did not clear after 3 seconds, */ + /* the controller must be broken. */ + + if (n >= 300) + return (0); + + /* Register the TX interrupt handler */ + + ua->ua_ivec = dzxint; + + return (1); +} + +static void +dz_attach (parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct uba_softc *uh = (void *)parent; + struct dz_softc *sc = (void *)self; + register struct uba_attach_args *ua = aux; + register dzregs *dzaddr; + register int n; + + dzaddr = (dzregs *) ua->ua_addr; + sc->sc_addr = dzaddr; + +#ifdef QBA + if (uh->uh_type == QBA) + sc->sc_type = DZ_DZV; + else +#endif + sc->sc_type = DZ_DZ; + + sc->sc_rxint = sc->sc_brk = 0; + + dzaddr->dz_csr = (DZ_CSR_MSE | DZ_CSR_RXIE | DZ_CSR_TXIE); + dzaddr->dz_dtr = 0; /* Make sure DTR bits are zero */ + dzaddr->dz_break = 0; /* Status of BREAK bits, all off */ + + /* Initialize our softc structure. Should be done in open? */ + + for (n = 0; n < sc->sc_type; n++) + sc->sc_dz[n].dz_tty = ttymalloc(); + + /* Now register the RX interrupt handler */ + ubasetvec(self, ua->ua_cvec-1, dzrint); + + /* Alas no interrupt on modem bit changes, so we manually scan */ + + if (dz_timer == 0) { + dz_timer = 1; + timeout(dzscan, (void *)0, hz); + } + + printf("\n"); + return; +} + +/* Receiver Interrupt */ + +static void +dzrint(cntlr) + int cntlr; +{ + struct dz_softc *sc = dz_cd.cd_devs[cntlr]; + volatile dzregs *dzaddr; + register struct tty *tp; + register int cc, line; + register unsigned c; + int overrun = 0; + + sc->sc_rxint++; + + dzaddr = sc->sc_addr; + + while ((c = dzaddr->dz_rbuf) & DZ_RBUF_DATA_VALID) { + cc = c & 0xFF; + line = DZ_PORT(c>>8); + tp = sc->sc_dz[line].dz_tty; + + if (!(tp->t_state & TS_ISOPEN)) { + wakeup((caddr_t)&tp->t_rawq); + continue; + } + + if ((c & DZ_RBUF_OVERRUN_ERR) && overrun == 0) { + log(LOG_WARNING, "%s: silo overflow, line %d\n", + sc->sc_dev.dv_xname, line); + overrun = 1; + } + /* A BREAK key will appear as a NULL with a framing error */ + if (c & DZ_RBUF_FRAMING_ERR) + cc |= TTY_FE; + if (c & DZ_RBUF_PARITY_ERR) + cc |= TTY_PE; + + (*linesw[tp->t_line].l_rint)(cc, tp); + } + return; +} + +/* Transmitter Interrupt */ + +static void +dzxint(cntlr) + int cntlr; +{ + volatile dzregs *dzaddr; + register struct dz_softc *sc = dz_cd.cd_devs[cntlr]; + register struct tty *tp; + register unsigned csr; + register int line; + + dzaddr = sc->sc_addr; + + /* + * Switch to POLLED mode. + * Some simple measurements indicated that even on + * one port, by freeing the scanner in the controller + * by either providing a character or turning off + * the port when output is complete, the transmitter + * was ready to accept more output when polled again. + * With just two ports running the game "worms," + * almost every interrupt serviced both transmitters! + * Each UART is double buffered, so if the scanner + * is quick enough and timing works out, we can even + * feed the same port twice. + */ + + dzaddr->dz_csr &= ~(DZ_CSR_TXIE); + + while (((csr = dzaddr->dz_csr) & DZ_CSR_TX_READY) != 0) { + + line = DZ_PORT(csr>>8); + + if (sc->sc_dz[line].dz_mem < sc->sc_dz[line].dz_end) { + dzaddr->dz_tbuf = *sc->sc_dz[line].dz_mem++; + continue; + } + + /* + * Turn off this TX port as all pending output + * has been completed - thus freeing the scanner + * on the controller to hopefully find another + * pending TX operation we can service now. + * (avoiding the overhead of another interrupt) + */ + + dzaddr->dz_tcr &= ~(1 << line); + + tp = sc->sc_dz[line].dz_tty; + + tp->t_state &= ~TS_BUSY; + + if (tp->t_state & TS_FLUSH) + tp->t_state &= ~TS_FLUSH; + else { + ndflush (&tp->t_outq, (sc->sc_dz[line].dz_mem - + (caddr_t)tp->t_outq.c_cf)); + sc->sc_dz[line].dz_end = sc->sc_dz[line].dz_mem = + tp->t_outq.c_cf; + } + + if (tp->t_line) + (*linesw[tp->t_line].l_start)(tp); + else + dzstart(tp); + } + + /* + * Re-enable TX interrupts. + */ + + dzaddr->dz_csr |= (DZ_CSR_TXIE); + return; +} + +int +dzopen(dev, flag, mode, p) + dev_t dev; + int flag, mode; + struct proc *p; +{ + register struct tty *tp; + register int unit, line; + struct dz_softc *sc; + int s, error = 0; + + unit = DZ_I2C(minor(dev)); + line = DZ_PORT(minor(dev)); + + if (unit >= dz_cd.cd_ndevs || dz_cd.cd_devs[unit] == NULL) + return (ENXIO); + + sc = dz_cd.cd_devs[unit]; + + if (line >= sc->sc_type) + return ENXIO; + + tp = sc->sc_dz[line].dz_tty; + if (tp == NULL) + return (ENODEV); + tp->t_oproc = dzstart; + tp->t_param = dzparam; + tp->t_dev = dev; + if ((tp->t_state & TS_ISOPEN) == 0) { + tp->t_state |= TS_WOPEN; + ttychars(tp); + if (tp->t_ispeed == 0) { + tp->t_iflag = TTYDEF_IFLAG; + tp->t_oflag = TTYDEF_OFLAG; + tp->t_cflag = TTYDEF_CFLAG; + tp->t_lflag = TTYDEF_LFLAG; + tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; + } + (void) dzparam(tp, &tp->t_termios); + ttsetwater(tp); + } else if ((tp->t_state & TS_XCLUDE) && p->p_ucred->cr_uid != 0) + return (EBUSY); + /* Use DMBIS and *not* DMSET or else we clobber incoming bits */ + if (dzmctl(sc, line, DML_DTR, DMBIS) & DML_DCD) + tp->t_state |= TS_CARR_ON; + s = spltty(); + while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) && + !(tp->t_state & TS_CARR_ON)) { + tp->t_state |= TS_WOPEN; + error = ttysleep(tp, (caddr_t)&tp->t_rawq, + TTIPRI | PCATCH, ttopen, 0); + if (error) + break; + } + (void) splx(s); + if (error) + return (error); + return ((*linesw[tp->t_line].l_open)(dev, tp)); +} + +/*ARGSUSED*/ +int +dzclose (dev, flag, mode, p) + dev_t dev; + int flag, mode; + struct proc *p; +{ + struct dz_softc *sc; + register struct tty *tp; + register int unit, line; + + + unit = DZ_I2C(minor(dev)); + line = DZ_PORT(minor(dev)); + sc = dz_cd.cd_devs[unit]; + + tp = sc->sc_dz[line].dz_tty; + + (*linesw[tp->t_line].l_close)(tp, flag); + + /* Make sure a BREAK state is not left enabled. */ + (void) dzmctl(sc, line, DML_BRK, DMBIC); + + /* Do a hangup if so required. */ + if ((tp->t_cflag & HUPCL) || (tp->t_state & TS_WOPEN) || + !(tp->t_state & TS_ISOPEN)) + (void) dzmctl(sc, line, 0, DMSET); + + return (ttyclose(tp)); +} + +int +dzread (dev, uio, flag) + dev_t dev; + struct uio *uio; +{ + register struct tty *tp; + struct dz_softc *sc; + + sc = dz_cd.cd_devs[DZ_I2C(minor(dev))]; + + tp = sc->sc_dz[DZ_PORT(minor(dev))].dz_tty; + return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); +} + +int +dzwrite (dev, uio, flag) + dev_t dev; + struct uio *uio; +{ + register struct tty *tp; + struct dz_softc *sc; + + sc = dz_cd.cd_devs[DZ_I2C(minor(dev))]; + + tp = sc->sc_dz[DZ_PORT(minor(dev))].dz_tty; + return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); +} + +/*ARGSUSED*/ +int +dzioctl (dev, cmd, data, flag, p) + dev_t dev; + int cmd; + caddr_t data; + int flag; + struct proc *p; +{ + struct dz_softc *sc; + register struct tty *tp; + register int unit, line; + int error; + + unit = DZ_I2C(minor(dev)); + line = DZ_PORT(minor(dev)); + sc = dz_cd.cd_devs[unit]; + tp = sc->sc_dz[line].dz_tty; + + error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); + if (error >= 0) + return (error); + error = ttioctl(tp, cmd, data, flag, p); + if (error >= 0) + return (error); + + switch (cmd) { + + case TIOCSBRK: + (void) dzmctl(sc, line, DML_BRK, DMBIS); + break; + + case TIOCCBRK: + (void) dzmctl(sc, line, DML_BRK, DMBIC); + break; + + case TIOCSDTR: + (void) dzmctl(sc, line, DML_DTR, DMBIS); + break; + + case TIOCCDTR: + (void) dzmctl(sc, line, DML_DTR, DMBIC); + break; + + case TIOCMSET: + (void) dzmctl(sc, line, *(int *)data, DMSET); + break; + + case TIOCMBIS: + (void) dzmctl(sc, line, *(int *)data, DMBIS); + break; + + case TIOCMBIC: + (void) dzmctl(sc, line, *(int *)data, DMBIC); + break; + + case TIOCMGET: + *(int *)data = (dzmctl(sc, line, 0, DMGET) & ~DML_BRK); + break; + + default: + return (ENOTTY); + } + return (0); +} + +struct tty * +dztty (dev) + dev_t dev; +{ + struct dz_softc *sc = dz_cd.cd_devs[DZ_I2C(minor(dev))]; + struct tty *tp = sc->sc_dz[DZ_PORT(minor(dev))].dz_tty; + + return (tp); +} + +/*ARGSUSED*/ +int +dzstop (tp, flag) + register struct tty *tp; +{ + register struct dz_softc *sc; + int unit, line, s; + + unit = DZ_I2C(minor(tp->t_dev)); + line = DZ_PORT(minor(tp->t_dev)); + sc = dz_cd.cd_devs[unit]; + + s = spltty(); + + if (tp->t_state & TS_BUSY) + { + sc->sc_dz[line].dz_end = sc->sc_dz[line].dz_mem; + if (!(tp->t_state & TS_TTSTOP)) + tp->t_state |= TS_FLUSH; + } + (void) splx(s); + return 0; +} + +static void +dzstart (tp) + register struct tty *tp; +{ + register struct dz_softc *sc; + register dzregs *dzaddr; + register int unit, line; + register int cc; + int s; + + unit = DZ_I2C(minor(tp->t_dev)); + line = DZ_PORT(minor(tp->t_dev)); + sc = dz_cd.cd_devs[unit]; + + s = spltty(); + if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) + goto out; + if (tp->t_outq.c_cc <= tp->t_lowat) { + if (tp->t_state & TS_ASLEEP) { + tp->t_state &= ~TS_ASLEEP; + wakeup((caddr_t)&tp->t_outq); + } + selwakeup(&tp->t_wsel); + } + if (tp->t_outq.c_cc == 0) + goto out; + cc = ndqb(&tp->t_outq, 0); + if (cc == 0) + goto out; + + tp->t_state |= TS_BUSY; + + dzaddr = sc->sc_addr; + + sc->sc_dz[line].dz_end = sc->sc_dz[line].dz_mem = tp->t_outq.c_cf; + sc->sc_dz[line].dz_end += cc; + dzaddr->dz_tcr |= (1 << line); /* Enable this TX port */ + +out: + (void) splx(s); + return; +} + +static int +dzparam(tp, t) + register struct tty *tp; + register struct termios *t; +{ + struct dz_softc *sc; + register dzregs *dzaddr; + register int cflag = t->c_cflag; + int unit, line; + int ispeed = ttspeedtab(t->c_ispeed, dzspeedtab); + int ospeed = ttspeedtab(t->c_ospeed, dzspeedtab); + register unsigned lpr; + int s; + + unit = DZ_I2C(minor(tp->t_dev)); + line = DZ_PORT(minor(tp->t_dev)); + sc = dz_cd.cd_devs[unit]; + + /* check requested parameters */ + if (ospeed < 0 || ispeed < 0 || ispeed != ospeed) + return (EINVAL); + + tp->t_ispeed = t->c_ispeed; + tp->t_ospeed = t->c_ospeed; + tp->t_cflag = cflag; + + if (ospeed == 0) { + (void) dzmctl(sc, line, 0, DMSET); /* hang up line */ + return (0); + } + + s = spltty(); + dzaddr = sc->sc_addr; + + lpr = DZ_LPR_RX_ENABLE | ((ispeed&0xF)<<8) | line; + + switch (cflag & CSIZE) + { + case CS5: + lpr |= DZ_LPR_5_BIT_CHAR; + break; + case CS6: + lpr |= DZ_LPR_6_BIT_CHAR; + break; + case CS7: + lpr |= DZ_LPR_7_BIT_CHAR; + break; + default: + lpr |= DZ_LPR_8_BIT_CHAR; + break; + } + if (cflag & PARENB) + lpr |= DZ_LPR_PARENB; + if (cflag & PARODD) + lpr |= DZ_LPR_OPAR; + if (cflag & CSTOPB) + lpr |= DZ_LPR_2_STOP; + + dzaddr->dz_lpr = lpr; + + (void) splx(s); + return (0); +} + +static unsigned +dzmctl(sc, line, bits, how) + register struct dz_softc *sc; + int line, bits, how; +{ + register dzregs *dzaddr; + register unsigned status; + register unsigned mbits; + register unsigned bit; + int s; + + s = spltty(); + + dzaddr = sc->sc_addr; + + mbits = 0; + + bit = (1 << line); + + /* external signals as seen from the port */ + + status = dzaddr->dz_dcd; + + if (status & bit) + mbits |= DML_DCD; + + status = dzaddr->dz_ring; + + if (status & bit) + mbits |= DML_RI; + + /* internal signals/state delivered to port */ + + status = dzaddr->dz_dtr; + + if (status & bit) + mbits |= DML_DTR; + + if (sc->sc_brk & bit) + mbits |= DML_BRK; + + switch (how) + { + case DMSET: + mbits = bits; + break; + + case DMBIS: + mbits |= bits; + break; + + case DMBIC: + mbits &= ~bits; + break; + + case DMGET: + (void) splx(s); + return (mbits); + } + + if (mbits & DML_DTR) + dzaddr->dz_dtr |= bit; + else + dzaddr->dz_dtr &= ~bit; + + if (mbits & DML_BRK) + dzaddr->dz_break = (sc->sc_brk |= bit); + else + dzaddr->dz_break = (sc->sc_brk &= ~bit); + + (void) splx(s); + return (mbits); +} + +/* + * This is called by timeout() periodically. + * Check to see if modem status bits have changed. + */ +static void +dzscan(arg) + void *arg; +{ + register dzregs *dzaddr; + register struct dz_softc *sc; + register struct tty *tp; + register int n, bit, port; + unsigned csr; + int s; + + s = spltty(); + + for (n = 0; n < dz_cd.cd_ndevs; n++) { + + if (dz_cd.cd_devs[n] == NULL) + continue; + + sc = dz_cd.cd_devs[n]; + + for (port = 0; port < sc->sc_type; port++) { + + dzaddr = sc->sc_addr; + tp = sc->sc_dz[port].dz_tty; + bit = (1 << port); + + if (dzaddr->dz_dcd & bit) { /* carrier present */ + + if (!(tp->t_state & TS_CARR_ON)) + (void)(*linesw[tp->t_line].l_modem) + (tp, 1); + } else if ((tp->t_state & TS_CARR_ON) && + (*linesw[tp->t_line].l_modem)(tp, 0) == 0) + dzaddr->dz_tcr &= ~bit; + } + + /* + * If the RX interrupt rate is this high, switch + * the controller to Silo Alarm - which means don't + * interrupt until the RX silo has 16 characters in + * it (the silo is 64 characters in all). + * Avoid oscillating SA on and off by not turning + * if off unless the rate is appropriately low. + */ + + dzaddr = sc->sc_addr; + + csr = dzaddr->dz_csr; + + if (sc->sc_rxint > (16*10)) { + if ((csr & DZ_CSR_SAE) == 0) + dzaddr->dz_csr = (csr | DZ_CSR_SAE); + } else if ((csr & DZ_CSR_SAE) != 0) + if (sc->sc_rxint < 10) + dzaddr->dz_csr = (csr & ~(DZ_CSR_SAE)); + + sc->sc_rxint = 0; + } + (void) splx(s); + timeout(dzscan, (void *)0, hz); + return; +} diff --git a/sys/arch/vax/uba/dzreg.h b/sys/arch/vax/uba/dzreg.h new file mode 100644 index 00000000000..c347cc6105d --- /dev/null +++ b/sys/arch/vax/uba/dzreg.h @@ -0,0 +1,116 @@ +/* $NetBSD: dzreg.h,v 1.1 1996/04/08 17:22:21 ragge Exp $ */ +/* + * Copyright (c) 1996 Ken C. Wellsch. 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 the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. + */ + +union w_b +{ + u_short word; + struct { + u_char byte_lo; + u_char byte_hi; + } bytes; +}; + +struct DZregs +{ + volatile u_short dz_csr; /* Control/Status Register (R/W) */ + volatile u_short dz_rbuf; /* Receive Buffer (R only) */ +#define dz_lpr dz_rbuf /* Line Parameter Register (W only) */ + volatile union w_b u_tcr; /* Transmit Control Register (R/W) */ + volatile union w_b u_msr; /* Modem Status Register (R only) */ +#define u_tdr u_msr /* Transmit Data Register (W only) */ +}; + +#define dz_tcr u_tcr.bytes.byte_lo /* tx enable bits */ +#define dz_dtr u_tcr.bytes.byte_hi /* DTR status bits */ +#define dz_ring u_msr.bytes.byte_lo /* RI status bits */ +#define dz_dcd u_msr.bytes.byte_hi /* DCD status bits */ +#define dz_tbuf u_tdr.bytes.byte_lo /* transmit character */ +#define dz_break u_tdr.bytes.byte_hi /* BREAK set/clr bits */ + +typedef struct DZregs dzregs; + +/* CSR bits */ + +#define DZ_CSR_TX_READY 0100000 /* Transmitter Ready */ +#define DZ_CSR_TXIE 0040000 /* Transmitter Interrupt Enable */ +#define DZ_CSR_SA 0020000 /* Silo Alarm */ +#define DZ_CSR_SAE 0010000 /* Silo Alarm Enable */ +#define DZ_CSR_TX_LINE_MASK 0007400 /* Which TX line */ + +#define DZ_CSR_RX_DONE 0000200 /* Receiver Done */ +#define DZ_CSR_RXIE 0000100 /* Receiver Interrupt Enable */ +#define DZ_CSR_MSE 0000040 /* Master Scan Enable */ +#define DZ_CSR_RESET 0000020 /* Clear (reset) Controller */ +#define DZ_CSR_MAINTENANCE 0000010 +#define DZ_CSR_UNUSED 0000007 + +/* RBUF bits */ + +#define DZ_RBUF_DATA_VALID 0100000 +#define DZ_RBUF_OVERRUN_ERR 0040000 +#define DZ_RBUF_FRAMING_ERR 0020000 +#define DZ_RBUF_PARITY_ERR 0010000 +#define DZ_RBUF_RX_LINE_MASK 0007400 + +/* LPR bits */ + +#define DZ_LPR_UNUSED 0160000 +#define DZ_LPR_RX_ENABLE 0010000 + +#define DZ_LPR_B50 0x0 +#define DZ_LPR_B75 0x1 +#define DZ_LPR_B110 0x2 +#define DZ_LPR_B134 0x3 +#define DZ_LPR_B150 0x4 +#define DZ_LPR_B300 0x5 +#define DZ_LPR_B600 0x6 +#define DZ_LPR_B1200 0x7 +#define DZ_LPR_B1800 0x8 +#define DZ_LPR_B2000 0x9 +#define DZ_LPR_B2400 0xA +#define DZ_LPR_B3600 0xB +#define DZ_LPR_B4800 0xC +#define DZ_LPR_B7200 0xD +#define DZ_LPR_B9600 0xE +#define DZ_LPR_ILLEGAL 0xF + +#define DZ_LPR_OPAR 0000200 +#define DZ_LPR_PARENB 0000100 +#define DZ_LPR_2_STOP 0000040 + +#define DZ_LPR_5_BIT_CHAR 0000000 +#define DZ_LPR_6_BIT_CHAR 0000010 +#define DZ_LPR_7_BIT_CHAR 0000020 +#define DZ_LPR_8_BIT_CHAR 0000030 + +#define DZ_LPR_CHANNEL_MASK 0000007 diff --git a/sys/arch/vax/uba/tmscp.c b/sys/arch/vax/uba/tmscp.c index e08cd17f2fa..ef490d93e3d 100644 --- a/sys/arch/vax/uba/tmscp.c +++ b/sys/arch/vax/uba/tmscp.c @@ -1,4 +1,4 @@ -/* $NetBSD: tmscp.c,v 1.7 1995/12/13 19:02:53 ragge Exp $ */ +/* $NetBSD: tmscp.c,v 1.12 1996/04/08 18:37:30 ragge Exp $ */ /*- * Copyright (c) 1991 The Regents of the University of California. @@ -158,27 +158,29 @@ #include "tmscp.h" #if NTMSCP > 0 -#include "sys/param.h" -#include "sys/systm.h" -#include "sys/buf.h" -#include "sys/conf.h" -#include "sys/errno.h" -#include "sys/file.h" -#include "sys/map.h" -#include "sys/ioctl.h" -#include "sys/syslog.h" -#include "sys/mtio.h" -/* #include "sys/cmap.h" */ -#include "sys/uio.h" -#include "sys/proc.h" -#include "sys/tprintf.h" - -#include "vax/include/pte.h" -#include "vax/include/cpu.h" -#include "vax/include/mtpr.h" -#include "vax/include/sid.h" -#include "vax/uba/ubareg.h" -#include "vax/uba/ubavar.h" +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/buf.h> +#include <sys/conf.h> +#include <sys/errno.h> +#include <sys/file.h> +#include <sys/map.h> +#include <sys/ioctl.h> +#include <sys/syslog.h> +#include <sys/mtio.h> +/* #include <sys/cmap.h> */ +#include <sys/uio.h> +#include <sys/proc.h> +#include <sys/tprintf.h> +#include <sys/proc.h> + +#include <machine/pte.h> +#include <machine/cpu.h> +#include <machine/mtpr.h> +#include <machine/sid.h> + +#include <vax/uba/ubareg.h> +#include <vax/uba/ubavar.h> #define TENSEC (1000) #define TMS_PRI LOG_INFO @@ -188,16 +190,20 @@ #define NRSP (1<<NRSPL2) #define NCMD (1<<NCMDL2) -#include "tmscpreg.h" -#include "vax/vax/tmscpinf.h" -#include "vax/vax/mscpvar.h" +#include <vax/uba/tmscpreg.h> +#include <vax/vax/tmscpinf.h> +#include <vax/vax/mscpvar.h> int tmscp_match __P((struct device *, void *, void *)); void tmscp_attach __P((struct device *, struct device *, void *)); void tmscpstrategy __P((struct buf *)); -struct cfdriver tmscpcd = { - NULL, "tmscp", tmscp_match, tmscp_attach, DV_DULL, sizeof(struct device) +struct cfdriver tmscp_cd = { + NULL, "tmscp", DV_DULL +}; + +struct cfattach tmscp_ca = { + sizeof(struct device), tmscp_match, tmscp_attach }; /* Software state per controller */ @@ -220,7 +226,27 @@ struct tmscp { struct mscp tmscp_cmd[NCMD]; /* command packets */ } tmscp[NTMSCP]; -void tmscpstrategy(struct buf *); +int tmscpprobe __P((caddr_t, int, struct uba_ctlr *, struct uba_softc *)); +int tmscpslave __P((struct uba_device *, caddr_t)); +int tmscpinit __P((int)); +void tmscpattach __P((struct uba_device *)); +void tmscpintr __P((int)); +void tmscprsp __P((struct uba_ctlr *, struct tmscp *, + struct tmscp_softc *, int)); +void tmscpstart __P((struct uba_ctlr *)); +void tmscpcommand __P((dev_t, int, int)); +struct mscp *tmscpgetcp __P((struct uba_ctlr *)); +void errinfo __P((int)); +int tmscpcmd __P((int, struct tmscp *, struct tmscpdevice *)); + +int tmscpopen __P((dev_t, int, int, struct proc *p)); +int tmscpclose __P((dev_t, int, int, struct proc *p)); +void tmscpstrategy __P((struct buf *)); +int tmscpread __P((dev_t, struct uio *)); +int tmscpwrite __P((dev_t, struct uio *)); +int tmscpdump __P((dev_t, daddr_t, caddr_t, size_t)); +int tmscpioctl __P((dev_t, u_long, caddr_t, int, struct proc *)); +void tmscpreset __P((int)); /* * Per drive-unit info @@ -241,6 +267,10 @@ struct tms_info { short tms_format; /* the unit's current format (density) */ tpr_t tms_tpr; /* tprintf handle */ } tms_info[NTMS]; + +void tmserror __P((struct uba_ctlr *, struct mslg *)); + + struct uba_ctlr *tmscpminfo[NTMSCP]; struct uba_device *tmsdinfo[NTMS]; /* @@ -293,7 +323,6 @@ short utoctlr[NTMS]; /* Slave unit to controller mapping */ int tmscperror = 0; /* causes hex dump of packets */ int tmscp_cp_wait = 0; /* Something to wait on for command */ /* packets and or credits. */ -void wakeup(); extern int hz; /* Should find the right include */ #ifdef DEBUG @@ -302,13 +331,10 @@ int tmscpdebug = 1; #define printd10 if(tmscpdebug >= 10) printf #endif -int tmscpprobe(), tmscpslave(), tmscpattach(), tmscpintr(); -struct mscp *tmscpgetcp(); - #define DRVNAME "tms" #define CTRLNAME "tmscp" -u_short tmscpstd[] = { 0174500, 0 }; +u_short tmscpstd[] = { 0174504, 0 }; struct uba_driver tmscpdriver = { tmscpprobe, tmscpslave, tmscpattach, 0, tmscpstd, DRVNAME, tmsdinfo, CTRLNAME , tmscpminfo, 0}; @@ -320,7 +346,7 @@ struct uba_driver tmscpdriver = /*************************************************************************/ #define DELAYTEN 1000 -extern struct cfdriver ubacd; +extern struct cfdriver uba_cd; /* * Unfortunately qbgetpri can't be used because the TK50 doesn't flip the @@ -328,10 +354,12 @@ extern struct cfdriver ubacd; * has been acknowledged by the cpu. If you are at spl6(), the TMSCP_STEP2 * flag never gets set and you return (0). */ -tmscpprobe(reg, ctlr, um) +int +tmscpprobe(reg, ctlr, um, uh) caddr_t reg; /* address of the IP register */ int ctlr; /* index of controller in the tmscp_softc array */ struct uba_ctlr *um; + struct uba_softc *uh; { /* register int br, cvec; MUST be 1st (r11 & r10): IPL and intr vec */ register struct tmscp_softc *sc = &tmscp_softc[ctlr]; @@ -353,7 +381,7 @@ tmscpprobe(reg, ctlr, um) * The device is not really initialized at this point, this is just to * find out if the device exists. */ - ubasc = ubacd.cd_devs[0]; /* XXX */ + ubasc = uba_cd.cd_devs[0]; /* XXX */ sc->sc_ivec = (ubasc->uh_lastiv -= 4); tmscpaddr->tmscpip = 0; @@ -391,13 +419,14 @@ tmscpprobe(reg, ctlr, um) * Try to find a slave (a drive) on the controller. * If the controller is not in the run state, call init to initialize it. */ +int tmscpslave (ui, reg) struct uba_device *ui; /* ptr to the uba device structure */ caddr_t reg; /* addr of the device controller */ { register struct uba_ctlr *um = tmscpminfo[ui->ui_ctlr]; - register struct tmscp_softc *sc = &tmscp_softc[ui->ui_ctlr]; - register struct tms_info *tms = &tms_info[ui->ui_unit]; + volatile struct tmscp_softc *sc = &tmscp_softc[ui->ui_ctlr]; + volatile struct tms_info *tms = &tms_info[ui->ui_unit]; volatile struct tmscpdevice *tmscpaddr; /* ptr to IP & SA */ volatile struct mscp *mp; volatile int i; /* Something to write into to start */ @@ -476,6 +505,7 @@ tmscpslave (ui, reg) * Unit to Controller mapping is set up here. * Open routine will issue the online command, later. */ +void tmscpattach (ui) register struct uba_device *ui; /* ptr to unibus dev struct */ { @@ -497,7 +527,9 @@ tmscpattach (ui) /* * TMSCP interrupt routine. */ +void tmscpintr(d) + int d; { volatile struct uba_ctlr *um = tmscpminfo[d]; volatile struct tmscpdevice *tmscpaddr = @@ -704,7 +736,8 @@ tmscpintr(d) i %= NRSP; if (tm->tmscp_ca.ca_rspdsc[i]&TMSCP_OWN) break; - tmscprsp(um, tm, sc, i); + tmscprsp((struct uba_ctlr *)um, tm, + (struct tmscp_softc *)sc, i); tm->tmscp_ca.ca_rspdsc[i] |= TMSCP_OWN; } sc->sc_lastrsp = i; @@ -722,7 +755,7 @@ tmscpintr(d) } if(tmscp_cp_wait) wakeup((caddr_t)&tmscp_cp_wait); - (void) tmscpstart(um); + (void) tmscpstart((struct uba_ctlr *)um); } @@ -732,9 +765,11 @@ tmscpintr(d) */ /* ARGSUSED */ -tmscpopen(dev, flag) +int +tmscpopen(dev, flag, type, p) dev_t dev; - int flag; + int flag, type; + struct proc *p; { register int unit; register struct uba_device *ui; @@ -854,9 +889,11 @@ tmscpopen(dev, flag) * command with the CSE modifier. * Make the tape available to others, by clearing openf flag. */ -tmscpclose(dev, flag) +int +tmscpclose(dev, flag, type, p) register dev_t dev; - register flag; + register flag, type; + struct proc *p; { register struct tms_info *tms; register struct uba_device *ui; @@ -868,7 +905,7 @@ tmscpclose(dev, flag) if(tmscpdebug)DELAY(10000); # endif tms = &tms_info[ui->ui_unit]; - if (flag == FWRITE || (flag&FWRITE) && tms->tms_lastiow) + if (flag == FWRITE || ((flag&FWRITE) && tms->tms_lastiow)) { /* device, command, count */ tmscpcommand (dev, TMS_WRITM, 1); @@ -903,7 +940,7 @@ tmscpclose(dev, flag) * with the command. The start routine is called by the strategy or the * interrupt routine. */ - +void tmscpcommand (dev, com, count) register dev_t dev; int com, count; @@ -1000,6 +1037,7 @@ tmscpgetcp(um) * initialize data structures, and start hardware * initialization sequence. */ +int tmscpinit (d) int d; /* index to the controller */ { @@ -1053,7 +1091,7 @@ tmscpinit (d) * Start I/O operation * This code is convoluted. The majority of it was copied from the uda driver. */ - +void tmscpstart(um) register struct uba_ctlr *um; { @@ -1349,7 +1387,7 @@ tmscpstart(um) i %= NRSP; if (tm->tmscp_ca.ca_rspdsc[i]&TMSCP_OWN) break; - tmscprsp(um, tm, sc, i); + tmscprsp(um, (struct tmscp *)tm, sc, i); tm->tmscp_ca.ca_rspdsc[i] |= TMSCP_OWN; } sc->sc_lastrsp = i; @@ -1359,9 +1397,10 @@ tmscpstart(um) /* * Process a response packet */ +void tmscprsp(um, tm, sc, i) register struct uba_ctlr *um; - register volatile struct tmscp *tm; + struct tmscp *tm; register struct tmscp_softc *sc; int i; { @@ -1459,7 +1498,7 @@ tmscprsp(um, tm, sc, i) } /* end if st == M_ST_SUCC */ else { - if (bp = dp->b_actf) + if ((bp = dp->b_actf)) tprintf(tms->tms_tpr, "tms%d: hard error bn%d: OFFLINE\n", minor(bp->b_dev)&03, bp->b_blkno); @@ -1467,7 +1506,7 @@ tmscprsp(um, tm, sc, i) tprintf(tms->tms_tpr, "tms%d: hard error: OFFLINE\n", ui->ui_unit); - while (bp = dp->b_actf) + while ((bp = dp->b_actf)) { dp->b_actf = bp->b_actf; bp->b_flags |= B_ERROR; @@ -1554,7 +1593,7 @@ tmscprsp(um, tm, sc, i) panic("tmscp: don't work2!"); dp->b_actf = bp->b_actf; # if defined(VAX750) - ubasc = ubacd.cd_devs[um->um_ubanum]; + ubasc = uba_cd.cd_devs[um->um_ubanum]; if (cpunumber == VAX_750) { if ((tmscpwtab[um->um_ctlr].b_actf == NULL) && (um->um_ubinfo != 0)) { @@ -1657,6 +1696,7 @@ tmscprsp(um, tm, sc, i) * Give a meaningful error when the mscp_status field returns an error code. */ +void errinfo(st) int st; /* the status code */ { @@ -1809,8 +1849,12 @@ tmscpwrite(dev, uio) struct tmscp tmscpd[NTMSCP]; -tmscpdump(dev) +int +tmscpdump(dev, blkno, va, size) dev_t dev; + daddr_t blkno; + caddr_t va; + size_t size; { #ifdef notyet volatile struct tmscpdevice *tmscpaddr; @@ -1900,10 +1944,11 @@ tmscpdump(dev) * Perform a standalone tmscp command. This routine is only used by tmscpdump. */ +int tmscpcmd(op, tmscpp, tmscpaddr) int op; - register volatile struct tmscp *tmscpp; - volatile struct tmscpdevice *tmscpaddr; + struct tmscp *tmscpp; + struct tmscpdevice *tmscpaddr; { volatile int i; @@ -1942,11 +1987,13 @@ tmscpcmd(op, tmscpp, tmscpaddr) */ /* ARGSUSED */ -tmscpioctl(dev, cmd, data, flag) +int +tmscpioctl(dev, cmd, data, flag, p) dev_t dev; - int cmd; + u_long cmd; caddr_t data; int flag; + struct proc *p; { register struct buf *bp = &ctmscpbuf[TMSCPCTLR(dev)]; register callcount; /* number of times to call cmd routine */ @@ -2025,7 +2072,7 @@ tmscpioctl(dev, cmd, data, flag) /* * Reset (for raw mode use only). */ - +void tmscpreset (uban) int uban; { @@ -2085,7 +2132,7 @@ tmscpreset (uban) * information is printed. Eventually should * send message to an error logger. */ - +void tmserror(um, mp) register struct uba_ctlr *um; register struct mslg *mp; @@ -2106,7 +2153,8 @@ tmserror(um, mp) break; case M_FM_BUSADDR: log(TMS_PRI, "host memory access error, event 0%o, addr 0%o\n", - mp->mslg_event, mp->mslg_unitid & 0xffffffff); + mp->mslg_event, + (unsigned int)(mp->mslg_unitid & 0xffffffff)); break; case M_FM_TAPETRN: log(TMS_PRI, "tape transfer error, unit %d, grp 0x%x, event 0%o\n", @@ -2140,11 +2188,12 @@ tmserror(um, mp) register long *p = (long *)mp; for (i = 0; i < mp->mslg_header.tmscp_msglen; i += sizeof(*p)) - printf("%x ", *p++); + printf("%x ", (unsigned int)*p++); printf("\n"); } } +int tmscp_match(parent, match, aux) struct device *parent; void *match, *aux; diff --git a/sys/arch/vax/uba/ts.c b/sys/arch/vax/uba/ts.c index 3f5ac796775..c2bb299e6a2 100644 --- a/sys/arch/vax/uba/ts.c +++ b/sys/arch/vax/uba/ts.c @@ -1,4 +1,4 @@ -/* $NetBSD: ts.c,v 1.1 1996/01/06 16:43:46 ragge Exp $ */ +/* $NetBSD: ts.c,v 1.6 1996/04/08 18:37:32 ragge Exp $ */ /*- * Copyright (c) 1991 The Regents of the University of California. @@ -61,7 +61,7 @@ * legends may be placed on the drivative work in addition * * to that set forth above. * * * - ************************************************************************ + ************************************************************************/ /* * TSV05/TS05 device driver, written by Bertram Barth. @@ -134,37 +134,41 @@ int tstrace = 1; #if NTS > 0 -#include "sys/param.h" -#include "sys/systm.h" -#include "sys/kernel.h" -#include "sys/buf.h" -#include "sys/conf.h" -#include "sys/errno.h" -#include "sys/file.h" -#include "sys/map.h" -#include "sys/syslog.h" -#include "sys/ioctl.h" -#include "sys/mtio.h" -#include "sys/uio.h" -#include "sys/proc.h" -#include "sys/tprintf.h" +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/buf.h> +#include <sys/conf.h> +#include <sys/errno.h> +#include <sys/file.h> +#include <sys/map.h> +#include <sys/syslog.h> +#include <sys/ioctl.h> +#include <sys/mtio.h> +#include <sys/uio.h> +#include <sys/proc.h> +#include <sys/tprintf.h> -#include "machine/pte.h" -#include "machine/sid.h" -#include "machine/cpu.h" -#include "machine/mtpr.h" +#include <machine/pte.h> +#include <machine/sid.h> +#include <machine/cpu.h> +#include <machine/mtpr.h> -#include "vax/uba/ubareg.h" -#include "vax/uba/ubavar.h" +#include <vax/uba/ubareg.h> +#include <vax/uba/ubavar.h> -#include "tsreg.h" +#include <vax/uba/tsreg.h> int ts_match __P((struct device *, void *, void *)); void ts_attach __P((struct device *, struct device *, void *)); void tsstrategy __P((struct buf *)); -struct cfdriver tscd = { - NULL, "ts", ts_match, ts_attach, DV_DULL, sizeof(struct device) +struct cfdriver ts_cd = { + NULL, "ts", DV_DULL +}; + +struct cfattach ts_ca = { + sizeof(struct device), ts_match, ts_attach }; /* @@ -201,6 +205,27 @@ struct ts_softc { tpr_t sc_tpr; /* tprintf handle */ } ts_softc[NTS]; +int tsprobe __P((caddr_t, int, struct uba_ctlr *, struct uba_softc *)); +int tsslave __P((struct uba_device *, caddr_t)); +void tsattach __P((struct uba_device *)); +void tsintr __P((int)); +int tsinit __P((int)); +void tscommand __P((dev_t, int, int)); +int tsstatus __P((int)); +int tsexec __P((int, int)); +int tsstart __P((struct uba_ctlr *, struct buf *)); +int tswchar __P((int)); +void tsreset __P((int)); +void tsxstatus __P((struct tsmsg *)); + +int tsopen __P((dev_t, int, int, struct proc *)); +int tsclose __P((dev_t, int, int, struct proc *)); +int tsioctl __P((dev_t, u_long, caddr_t, int, struct proc *)); +int tsread __P((dev_t, struct uio *)); +int tswrite __P((dev_t, struct uio *)); +int tsdump __P((dev_t, daddr_t, caddr_t, size_t)); + + #define ST_INVALID 0 /* uninitialized, before probe */ #define ST_PROBE 1 /* during tsprobe(), not used */ #define ST_SLAVE 2 /* in tsslave(), init almost complete */ @@ -226,8 +251,6 @@ struct ts_softc { struct uba_ctlr *zsinfo[NTS]; /* controller-info */ struct uba_device *tsinfo[NTS]; /* unit(tape)-info */ -int tsprobe(), tsslave(), tsattach(), tsdgo(), tsintr(); - u_short tsstd[] = { 0172520, 0172524, /* standart csr for ts */ 0172530, 0172534, 0 }; /* standart csr for ts */ @@ -303,7 +326,6 @@ tsexec (ctlr, cmd) volatile struct tsdevice *tsreg = ts[ctlr].reg; volatile char *dbx = ((char*)tsreg) + 3; volatile short sr; - char *cmdName; sc->sc_cmdf |= TS_CF_ACK | TS_CF_IE; tscmdp->cmdr = sc->sc_cmdf | cmd; @@ -375,7 +397,7 @@ tsexec (ctlr, cmd) * This routine sets up a buffer and calls the strategy routine which * issues the command to the controller. */ -int +void tscommand (dev, cmd, count) register dev_t dev; int cmd; @@ -445,7 +467,6 @@ tsstart (um, bp) volatile struct tsdevice *tsreg = ts[um->um_ctlr].reg; register struct tscmd *tscmdp = &ts[um->um_ctlr].cmd; register struct buf *dp; - register struct ts *tp; volatile int i, itmp; int unit; int ioctl; @@ -577,7 +598,7 @@ tsstart (um, bp) break; default: printf ("%s%d: bad ioctl %d\n", - CTLRNAME, unit, bp->b_resid); + CTLRNAME, unit, (int)bp->b_resid); /* Need a no-op. get status */ cmd = TS_CMD_STAT; } /* end switch (bp->b_resid) */ @@ -629,7 +650,6 @@ int tswchar (ctlr) int ctlr; { - register struct ts_softc *sc = &ts_softc[ctlr]; volatile struct tsdevice *tsregs = ts[ctlr].reg; volatile struct tscmd *tscmdp = &ts[ctlr].cmd; volatile struct tsmsg *tsmsgp = &ts[ctlr].msg; @@ -705,11 +725,10 @@ tswchar (ctlr) /* * */ -int -tsreset (ctlr) +void +tsreset(ctlr) int ctlr; { - register struct ts_softc *sc = &ts_softc[ctlr]; volatile struct tsdevice *tsreg = ts[ctlr].reg; volatile unsigned int sr, timeout; @@ -729,23 +748,24 @@ tsreset (ctlr) printf ("%s%d: timeout waiting for TS_SSR\n", CTLRNAME, ctlr); tsstatus (sr); - return (-1); + return; } } while ((sr & TS_SSR) == 0); /* wait until subsystem ready */ tsstatus (sr); - return (tswchar (ctlr)); + return; } -extern struct cfdriver ubacd; +extern struct cfdriver uba_cd; /* * probe for device. If found, try to raise an interrupt. */ int -tsprobe (reg, ctlr, um) +tsprobe (reg, ctlr, um, uh) caddr_t reg; /* address of TSDB register */ int ctlr; /* index of the controller */ struct uba_ctlr *um; /* controller-info */ + struct uba_softc *uh; { register struct ts_softc *sc; register struct tsdevice *tsregs = (struct tsdevice*) reg; @@ -768,7 +788,7 @@ tsprobe (reg, ctlr, um) * The device is not really initialized at this point, this is just to * find out if the device exists. */ - ubasc = ubacd.cd_devs[0]; /* XXX */ + ubasc = uba_cd.cd_devs[0]; /* XXX */ sc->sc_ivec = (ubasc->uh_lastiv -= 4); count = 0; @@ -851,37 +871,35 @@ tsslave (ui, reg) * Open routine will issue the online command, later. * Just reset the flags and do nothing ... */ -int +void tsattach (ui) - register struct uba_device *ui; + struct uba_device *ui; { trace (("\ntsattach (%x)", ui)); ui->ui_flags = 0; /* mark unit offline */ - return (0); } /* * TSV05/TS05 interrupt routine */ -int +void tsintr(ctlr) + int ctlr; { register struct ts_softc *sc = &ts_softc[ctlr]; register struct tsmsg *tsmsgp = &ts[ctlr].msg; register struct tscmd *tscmdp = &ts[ctlr].cmd; volatile struct tsdevice *tsreg = ts[ctlr].reg; - volatile struct uba_ctlr *um = zsinfo[ctlr]; + struct uba_ctlr *um = zsinfo[ctlr]; register struct buf *bp; unsigned short sr = tsreg->tssr; /* save TSSR */ unsigned short mh = tsmsgp->hdr; /* and msg-header */ /* clear the message header ??? */ - short cmode = tscmdp->cmdr & TS_CF_CMODE; short ccode = tscmdp->cmdr & TS_CF_CCODE; short cmask = tscmdp->cmdr & TS_CF_CMASK; - short error = 0; #ifdef DEBUG printf ("TSSR: %b, MSG: %x ", sr, TS_TSSR_BITS, mh); @@ -1165,9 +1183,10 @@ tsintr(ctlr) * in the run state, call init to initialize the ts controller first. */ int -tsopen (dev, flag) +tsopen (dev, flag, type, p) dev_t dev; - int flag; + int flag, type; + struct proc *p; { register struct uba_device *ui; register struct uba_ctlr *um; @@ -1226,15 +1245,16 @@ tsopen (dev, flag) * Make the tape available to others, by clearing openf flag. */ int -tsclose (dev, flag) +tsclose (dev, flag, type, p) dev_t dev; - int flag; + int flag, type; + struct proc *p; { register struct ts_softc *sc = &ts_softc[TS_UNIT(dev)]; trace (("tsclose (%x, %d)\n", dev, flag)); - if (flag == FWRITE || (flag & FWRITE) && sc->sc_liowf) { + if (flag == FWRITE || ((flag & FWRITE) && sc->sc_liowf)) { debug (("tsclose: writing eot\n")); /* * We are writing two tape marks (EOT), but place the tape @@ -1267,8 +1287,6 @@ tsstrategy (bp) { register struct uba_device *ui; register struct uba_ctlr *um; - register struct buf *dp; - register int ctlr = TS_CTLR(bp->b_dev); register int unit = TS_UNIT(bp->b_dev); int s; @@ -1319,14 +1337,14 @@ tsstrategy (bp) * Catch ioctl commands, and call the "command" routine to do them. */ int -tsioctl (dev, cmd, data, flag) +tsioctl (dev, cmd, data, flag, p) dev_t dev; - int cmd; + u_long cmd; caddr_t data; int flag; + struct proc *p; { register struct buf *bp = &ts_cbuf[TS_UNIT(dev)]; - register struct uba_device *ui; register struct ts_softc *sc; register struct mtop *mtop; /* mag tape cmd op to perform */ register struct mtget *mtget; /* mag tape struct to get info in */ @@ -1447,10 +1465,14 @@ tswrite (dev, uio) * */ int -tsdump (dev) +tsdump(dev, blkno, va, size) dev_t dev; + daddr_t blkno; + caddr_t va; + size_t size; { trace (("tsdump (%x)\n", dev)); + return 0; } /*----------------------------------------------------------------------*/ @@ -1489,7 +1511,7 @@ tsstatus (sr) return (0); } -int +void tsxstatus (mp) struct tsmsg *mp; { diff --git a/sys/arch/vax/uba/uba.c b/sys/arch/vax/uba/uba.c index 999fb900183..7444fc60d88 100644 --- a/sys/arch/vax/uba/uba.c +++ b/sys/arch/vax/uba/uba.c @@ -1,4 +1,4 @@ -/* $NetBSD: uba.c,v 1.12 1995/12/28 19:17:07 thorpej Exp $ */ +/* $NetBSD: uba.c,v 1.22 1996/04/08 18:37:34 ragge Exp $ */ /* * Copyright (c) 1982, 1986 The Regents of the University of California. @@ -37,34 +37,34 @@ * @(#)autoconf.c 7.20 (Berkeley) 5/9/91 */ -#include "sys/param.h" -#include "sys/types.h" -#include "sys/time.h" -#include "sys/systm.h" -#include "sys/map.h" -#include "sys/buf.h" -#include "sys/proc.h" -#include "sys/user.h" -#include "sys/conf.h" -#include "sys/dkstat.h" -#include "sys/kernel.h" -#include "sys/malloc.h" -#include "sys/device.h" - -#include "vm/vm.h" -#include "vm/vm_kern.h" - -#include "machine/pte.h" -#include "machine/cpu.h" -#include "machine/mtpr.h" -#include "machine/nexus.h" -#include "machine/sid.h" -#include "machine/scb.h" -#include "machine/trap.h" -#include "machine/frame.h" - -#include "ubareg.h" -#include "ubavar.h" +#include <sys/param.h> +#include <sys/types.h> +#include <sys/time.h> +#include <sys/systm.h> +#include <sys/map.h> +#include <sys/buf.h> +#include <sys/proc.h> +#include <sys/user.h> +#include <sys/conf.h> +#include <sys/dkstat.h> +#include <sys/kernel.h> +#include <sys/malloc.h> +#include <sys/device.h> + +#include <vm/vm.h> +#include <vm/vm_kern.h> + +#include <machine/pte.h> +#include <machine/cpu.h> +#include <machine/mtpr.h> +#include <machine/nexus.h> +#include <machine/sid.h> +#include <machine/scb.h> +#include <machine/trap.h> +#include <machine/frame.h> + +#include <vax/uba/ubareg.h> +#include <vax/uba/ubavar.h> extern int cold; @@ -74,60 +74,55 @@ int uba_match __P((struct device *, void *, void *)); void uba_attach __P((struct device *, struct device *, void *)); void ubascan __P((struct device *, void *)); int ubaprint __P((void *, char *)); - -struct cfdriver ubacd = { - NULL, "uba", uba_match, uba_attach, DV_DULL, - sizeof(struct uba_softc), 1 +void uba_dw780int __P((int)); +void ubaerror __P((int, struct uba_softc *, int *, int *, + struct uba_regs *)); +void ubainit __P((struct uba_softc *)); +void ubastray __P((int)); +void unifind __P((struct uba_softc *, caddr_t)); +void ubapurge __P((struct uba_ctlr *)); +void ubainitmaps __P((struct uba_softc *)); +int qbgetpri __P((void)); +int ubamem __P((int, int, int, int)); +void uba_dw780int __P((int)); + + +struct cfdriver uba_cd = { + NULL, "uba", DV_DULL, 1 }; +struct cfattach uba_ca = { + sizeof(struct uba_softc), uba_match, uba_attach +}; -#ifdef 0 -/* - * Mark addresses starting at "addr" and continuing - * "size" bytes as allocated in the map "ualloc". - * Warn if the new allocation overlaps a previous allocation. - */ -static -csralloc(ualloc, addr, size) - caddr_t ualloc; - u_short addr; - register int size; -{ - register caddr_t p; - int warned = 0; - - p = &ualloc[ubdevreg(addr+size)]; - while (--size >= 0) { - if (*--p && !warned) { - printf( - "WARNING: device registers overlap those for a previous device!\n"); - warned = 1; - } - *p = 1; - } -} -#endif /* - * Stray interrupt vector handler, used when nowhere else to - * go to. + * Stray interrupt vector handler, used when nowhere else to go to. */ void ubastray(arg) int arg; { struct callsframe *cf = FRAMEOFFSET(arg); - struct uba_softc *sc = ubacd.cd_devs[arg]; + struct uba_softc *sc = uba_cd.cd_devs[arg]; + struct uba_regs *ur = sc->uh_uba; int vektor; - vektor = (cf->ca_pc - (unsigned)&sc->uh_idsp[0]) >> 4; + rbr = mfpr(PR_IPL); +#ifdef DW780 + if (sc->uh_type == DW780) + vektor = ur->uba_brrvr[rbr - 0x14] >> 2; + else +#endif + vektor = (cf->ca_pc - (unsigned)&sc->uh_idsp[0]) >> 4; - if(cold){ - rbr = mfpr(PR_IPL); - rcvec = vektor; - } else { - printf("uba%d: unexpected interrupt, vector %o, level %d", - arg, vektor << 2, mfpr(PR_IPL)); - } + if (cold) { +#ifdef DW780 + if (sc->uh_type != DW780) +#endif + rcvec = vektor; + } else + printf("uba%d: unexpected interrupt, vector %o, br %d\n", + arg, vektor << 2, rbr - 20); } /* @@ -136,7 +131,7 @@ ubastray(arg) * and then fills in the tables, with help from a per-driver * slave initialization routine. */ - +void unifind(uhp0, pumem) struct uba_softc *uhp0; caddr_t pumem; @@ -144,75 +139,12 @@ unifind(uhp0, pumem) register struct uba_device *ui; register struct uba_ctlr *um; register struct uba_softc *uhp = uhp0; + volatile struct uba_regs *ubar = uhp->uh_uba; u_short *reg, *ap, addr; struct uba_driver *udp; int i; - caddr_t ualloc; - volatile extern int br, cvec; volatile extern int rbr, rcvec; -#if DW780 || DWBUA - struct uba_regs *vubp = uhp->uh_uba; -#endif -#if 0 - /* - * Initialize the UNIBUS, by freeing the map - * registers and the buffered data path registers - */ - uhp->uh_map = (struct map *) - malloc((u_long)(UAMSIZ * sizeof (struct map)), M_DEVBUF, - M_NOWAIT); - if (uhp->uh_map == 0) - panic("no mem for unibus map"); - bzero((caddr_t)uhp->uh_map, (unsigned)(UAMSIZ * sizeof (struct map))); - ubainitmaps(uhp); - /* - * Set last free interrupt vector for devices with - * programmable interrupt vectors. Use is to decrement - * this number and use result as interrupt vector. - */ - uhp->uh_lastiv = 0x200; - -#ifdef DWBUA - if (uhp->uh_type == DWBUA) - BUA(vubp)->bua_offset = (int)uhp->uh_vec - (int)&scb[0]; -#endif - -#ifdef DW780 - if (uhp->uh_type == DW780) { - vubp->uba_sr = vubp->uba_sr; - vubp->uba_cr = UBACR_IFS|UBACR_BRIE; - } -#endif - /* - * First configure devices that have unibus memory, - * allowing them to allocate the correct map registers. - */ - ubameminit(uhp->uh_dev.dv_unit); - /* - * Grab some memory to record the umem address space we allocate, - * so we can be sure not to place two devices at the same address. - * - * We could use just 1/8 of this (we only want a 1 bit flag) but - * we are going to give it back anyway, and that would make the - * code here bigger (which we can't give back), so ... - * - * One day, someone will make a unibus with something other than - * an 8K i/o address space, & screw this totally. - */ - ualloc = (caddr_t)malloc((u_long)(8 * 1024), M_TEMP, M_NOWAIT); - if (ualloc == (caddr_t)0) - panic("no mem for unifind"); - bzero(ualloc, 8*1024); - - /* - * Map the first page of UNIBUS i/o - * space to the first page of memory - * for devices which will need to dma - * output to produce an interrupt. - */ - *(int *)(&uhp->uh_mr[0]) = UBAMR_MRV; -#endif #define ubaddr(uhp, off) (u_short *)((int)(uhp)->uh_iopage + ubdevreg(off)) /* * Check each unibus mass storage controller. @@ -220,9 +152,9 @@ unifind(uhp0, pumem) * see if it is really there, and if it is record it and * then go looking for slaves. */ - for (um = ubminit; udp = um->um_driver; um++) { - if (um->um_ubanum != uhp->uh_dev.dv_unit && - um->um_ubanum != '?' || um->um_alive) + for (um = ubminit; (udp = um->um_driver); um++) { + if ((um->um_ubanum != uhp->uh_dev.dv_unit && + um->um_ubanum != '?') || um->um_alive) continue; addr = (u_short)(u_long)um->um_addr; /* @@ -232,26 +164,21 @@ unifind(uhp0, pumem) * in the driver til we find it */ for (ap = udp->ud_addr; addr || (addr = *ap++); addr = 0) { -#if 0 - if (ualloc[ubdevreg(addr)]) - continue; -#endif reg = ubaddr(uhp, addr); - if (badaddr((caddr_t)reg, 2)) continue; -#ifdef DW780 - if (uhp->uh_type == DW780 && vubp->uba_sr) { - vubp->uba_sr = vubp->uba_sr; +#if DW780 + if (uhp->uh_type == DW780 && ubar->uba_sr) { + ubar->uba_sr = ubar->uba_sr; continue; } #endif rcvec = 0x200; - i = (*udp->ud_probe)(reg, um->um_ctlr, um); -#ifdef DW780 - if (uhp->uh_type == DW780 && vubp->uba_sr) { - vubp->uba_sr = vubp->uba_sr; + i = (*udp->ud_probe)((caddr_t)reg, um->um_ctlr, um, uhp); +#if DW780 + if (uhp->uh_type == DW780 && ubar->uba_sr) { + ubar->uba_sr = ubar->uba_sr; continue; } #endif @@ -268,9 +195,6 @@ unifind(uhp0, pumem) continue; } printf("vec %o, ipl %x\n", rcvec << 2, rbr); -#if 0 - csralloc(ualloc, addr, i); -#endif um->um_alive = 1; um->um_ubanum = uhp->uh_dev.dv_unit; um->um_hd = uhp; @@ -282,13 +206,13 @@ unifind(uhp0, pumem) int t; if (ui->ui_driver != udp || ui->ui_alive || - ui->ui_ctlr != um->um_ctlr && ui->ui_ctlr != '?' || - ui->ui_ubanum != uhp->uh_dev.dv_unit && - ui->ui_ubanum != '?') + (ui->ui_ctlr != um->um_ctlr && ui->ui_ctlr != '?') || + (ui->ui_ubanum != uhp->uh_dev.dv_unit && + ui->ui_ubanum != '?')) continue; t = ui->ui_ctlr; ui->ui_ctlr = um->um_ctlr; - if ((*udp->ud_slave)(ui, reg) == 0) + if ((*udp->ud_slave)(ui, (caddr_t)reg) == 0) ui->ui_ctlr = t; else { ui->ui_alive = 1; @@ -313,9 +237,6 @@ unifind(uhp0, pumem) break; } } -#if 0 - free(ualloc, M_TEMP); -#endif } @@ -341,6 +262,7 @@ char ubasr_bits[] = UBASR_BITS; * to the controller, unless it is zero, indicating that the controller * does not now have a BDP. */ +int ubaqueue(ui, onq) register struct uba_device *ui; int onq; @@ -350,13 +272,13 @@ ubaqueue(ui, onq) register struct uba_driver *ud; register int s, unit; - uh = ubacd.cd_devs[um->um_ubanum]; + uh = uba_cd.cd_devs[um->um_ubanum]; ud = um->um_driver; s = spluba(); /* * Honor exclusive BDP use requests. */ - if (ud->ud_xclu && uh->uh_users > 0 || uh->uh_xclu) + if ((ud->ud_xclu && uh->uh_users > 0) || uh->uh_xclu) goto rwait; if (ud->ud_keepbdp) { /* @@ -405,10 +327,11 @@ rwait: return (0); } +void ubadone(um) struct uba_ctlr *um; { - struct uba_softc *uh = ubacd.cd_devs[um->um_ubanum]; + struct uba_softc *uh = uba_cd.cd_devs[um->um_ubanum]; if (um->um_driver->ud_xclu) uh->uh_xclu = 0; @@ -425,11 +348,12 @@ ubadone(um) * Return value encodes map register plus page offset, * bdp number and number of map registers. */ +int ubasetup(uban, bp, flags) struct buf *bp; int uban, flags; { - struct uba_softc *uh = ubacd.cd_devs[uban]; + struct uba_softc *uh = uba_cd.cd_devs[uban]; struct pte *pte, *io; int npf; int pfnum, temp; @@ -491,7 +415,8 @@ ubasetup(uban, bp, flags) if ((bp->b_flags & B_PHYS) == 0) pte = (struct pte *)kvtopte(bp->b_un.b_addr); else { - u_int *hej, i; + struct pte *hej; + int i; rp = bp->b_proc; v = btop((u_int)bp->b_un.b_addr&0x3fffffff); @@ -506,7 +431,7 @@ ubasetup(uban, bp, flags) else hej = rp->p_vmspace->vm_pmap.pm_pcb->P1BR; - pte = (struct pte *)&hej[v]; + pte = &hej[v]; for (i = 0; i < (npf - 1); i++) { if ((pte + i)->pg_pfn == 0) { int rv; @@ -534,6 +459,7 @@ ubasetup(uban, bp, flags) /* * Non buffer setup interface... set up a buffer and call ubasetup. */ +int uballoc(uban, addr, bcnt, flags) caddr_t addr; int uban, bcnt, flags; @@ -552,10 +478,11 @@ uballoc(uban, addr, bcnt, flags) * The map register parameter is by value since we need to block * against uba resets on 11/780's. */ +void ubarelse(uban, amr) int uban, *amr; { - register struct uba_softc *uh = ubacd.cd_devs[uban]; + register struct uba_softc *uh = uba_cd.cd_devs[uban]; register int bdp, reg, npf, s; int mr; @@ -583,7 +510,6 @@ ubarelse(uban, amr) break; #endif #ifdef DW780 -sdjhfgsadjkfhgasj case DW780: uh->uh_uba->uba_dpr[bdp] |= UBADPR_BNE; break; @@ -627,6 +553,7 @@ sdjhfgsadjkfhgasj ; } +void ubapurge(um) register struct uba_ctlr *um; { @@ -654,6 +581,7 @@ ubapurge(um) } } +void ubainitmaps(uhp) register struct uba_softc *uhp; { @@ -684,15 +612,15 @@ ubainitmaps(uhp) /* * Generate a reset on uba number uban. Then - * call each device in the character device table, + * call each device that asked to be called during attach, * giving it a chance to clean up so as to be able to continue. */ +void ubareset(uban) int uban; { - register struct cdevsw *cdp; - register struct uba_softc *uh = ubacd.cd_devs[uban]; - int s; + register struct uba_softc *uh = uba_cd.cd_devs[uban]; + int s, i; s = spluba(); uh->uh_users = 0; @@ -704,39 +632,26 @@ ubareset(uban) ubainitmaps(uh); wakeup((caddr_t)&uh->uh_bdpwant); wakeup((caddr_t)&uh->uh_mrwant); - printf("uba%d: reset", uban); + printf("%s: reset", uh->uh_dev.dv_xname); ubainit(uh); #ifdef notyet ubameminit(uban); #endif - /* XXX - ??? - * Intressant, vi m}ste l|sa det h{r med ubareset() p} n}t smart - * s{tt. En l{nkad lista som s{tts upp vid autoconfiggen? Kanske. - * N{r anv{nds dom? Jag vet faktiskt inte; det verkar vara en - * ren sm|rja den gamla koden. F}r peturba lite mer docs... - * 950428/Ragge - */ - udareset(0); /* XXX */ -/* for (cdp = cdevsw; cdp < cdevsw + nchrdev; cdp++) - (*cdp->d_reset)(uban); - ifubareset(uban); - */ + for (i = 0; i < uh->uh_resno; i++) + (*uh->uh_reset[i])(uh->uh_resarg[i]); printf("\n"); splx(s); } /* - * Init a uba. This is called with a pointer - * rather than a virtual address since it is called - * by code which runs with memory mapping disabled. - * In these cases we really don't need the interrupts - * enabled, but since we run with ipl high, we don't care - * if they are, they will never happen anyways. + * Init a uba. */ void ubainit(uhp) struct uba_softc *uhp; { + volatile struct uba_regs *ur = uhp->uh_uba; + switch (uhp->uh_type) { #ifdef DWBUA case DWBUA: @@ -745,11 +660,11 @@ ubainit(uhp) DELAY(500000); break; #endif -#ifdef DW780 +#if DW780 case DW780: - uba->uba_cr = UBACR_ADINIT; - uba->uba_cr = UBACR_IFS|UBACR_BRIE|UBACR_USEFIE|UBACR_SUEFIE; - while ((uba->uba_cnfgr & UBACNFGR_UBIC) == 0) + ur->uba_cr = UBACR_ADINIT; + ur->uba_cr = UBACR_IFS|UBACR_BRIE|UBACR_USEFIE|UBACR_SUEFIE; + while ((ur->uba_cnfgr & UBACNFGR_UBIC) == 0) ; break; #endif @@ -791,13 +706,14 @@ ubainit(uhp) * delaying as necessary, then call this routine * before resetting the device. */ +int qbgetpri() { +#ifdef notyet int pri; extern int cvec; panic("qbgetpri"); -#if 0 for (pri = 0x17; pri > 0x14; ) { if (cvec && cvec != 0x200) /* interrupted at pri */ break; @@ -806,6 +722,8 @@ qbgetpri() } (void) spl0(); return (pri); +#else + return 0x17; #endif } #endif @@ -823,15 +741,16 @@ int zvcnt_max = 5000; /* in 8 sec */ * It must not be declared register. */ /*ARGSUSED*/ +void ubaerror(uban, uh, ipl, uvec, uba) register int uban; register struct uba_softc *uh; - int ipl, uvec; + int *ipl, *uvec; register struct uba_regs *uba; { register sr, s; - if (uvec == 0) { + if (*uvec == 0) { /* * Declare dt as unsigned so that negative values * are handled as >8 below, in case time was set back. @@ -845,9 +764,9 @@ ubaerror(uban, uh, ipl, uvec, uba) } if (++uh->uh_zvcnt > zvcnt_max) { printf("uba%d: too many zero vectors (%d in <%d sec)\n", - uban, uh->uh_zvcnt, dt + 1); + uban, uh->uh_zvcnt, (int)dt + 1); printf("\tIPL 0x%x\n\tcnfgr: %b Adapter Code: 0x%x\n", - ipl, uba->uba_cnfgr&(~0xff), UBACNFGR_BITS, + *ipl, uba->uba_cnfgr&(~0xff), UBACNFGR_BITS, uba->uba_cnfgr&0xff); printf("\tsr: %b\n\tdcr: %x (MIC %sOK)\n", uba->uba_sr, ubasr_bits, uba->uba_dcr, @@ -861,7 +780,7 @@ ubaerror(uban, uh, ipl, uvec, uba) uban, uba->uba_sr, ubasr_bits, uba->uba_cnfgr, NEXFLT_BITS); ubareset(uban); - uvec = 0; + *uvec = 0; return; } sr = uba->uba_sr; @@ -870,13 +789,13 @@ ubaerror(uban, uh, ipl, uvec, uba) uban, uba->uba_sr, ubasr_bits, uba->uba_fmer, 4*uba->uba_fubar); splx(s); uba->uba_sr = sr; - uvec &= UBABRRVR_DIV; + *uvec &= UBABRRVR_DIV; if (++uh->uh_errcnt % ubawedgecnt == 0) { if (uh->uh_errcnt > ubacrazy) panic("uba crazy"); printf("ERROR LIMIT "); ubareset(uban); - uvec = 0; + *uvec = 0; return; } return; @@ -894,7 +813,7 @@ ubaerror(uban, uh, ipl, uvec, uba) ubameminit(uban) { register struct uba_device *ui; - register struct uba_softc *uh = ubacd.cd_devs[uban]; + register struct uba_softc *uh = uba_cd.cd_devs[uban]; caddr_t umembase, addr; #define ubaoff(off) ((int)(off) & 0x1fff) @@ -938,11 +857,6 @@ jdhfgsjdkfhgsdjkfghak } #endif -rmget(){ - showstate(curproc); - panic("rmget() not implemented. (in uba.c)"); -} - /* * Allocate UNIBUS memory. Allocates and initializes * sufficient mapping registers for access. On a 780, @@ -954,17 +868,19 @@ rmget(){ * the last unibus memory would free unusable map registers. * Doalloc is 1 to allocate, 0 to deallocate. */ +int ubamem(uban, addr, npg, doalloc) int uban, addr, npg, doalloc; { - register struct uba_softc *uh = ubacd.cd_devs[uban]; + register struct uba_softc *uh = uba_cd.cd_devs[uban]; register int a; int s; a = (addr >> 9) + 1; s = spluba(); if (doalloc) - a = rmget(uh->uh_map, npg, a); + panic("uba: rmget"); +/* a = rmget(uh->uh_map, npg, a); */ else rmfree(uh->uh_map, (long)npg, (long)a); splx(s); @@ -1020,12 +936,36 @@ unmaptouser(vaddress) } #endif -resuba() +#ifdef DW780 +void +uba_dw780int(uba) + int uba; { - showstate(curproc); - panic("resuba"); + int br, svec, vec, arg; + struct uba_softc *sc = uba_cd.cd_devs[uba]; + struct uba_regs *ur = sc->uh_uba; + void (*func) __P((int)); + + br = mfpr(PR_IPL); + svec = ur->uba_brrvr[br - 0x14]; + if (svec < 0) { + ubaerror(uba, sc, &br, &svec, ur); + if (svec == 0) + return; + } + vec = svec >> 2; + if (cold) + rcvec = vec; + func = sc->uh_idsp[vec].hoppaddr; + arg = sc->uh_idsp[vec].pushlarg; + (*func)(arg); } +#endif +/* + * The match routine checks which UBA adapter number it is, to + * be sure to use correct interrupt vectors. + */ int uba_match(parent, vcf, aux) struct device *parent; @@ -1057,6 +997,12 @@ uba_match(parent, vcf, aux) return 1; } +/* + * The attach routines: + * Allocates interrupt vectors. + * Puts correct (cpu-specific) addresses in uba_softc. + * Calls the scan routine to search for uba devices. + */ void uba_attach(parent, self, aux) struct device *parent, *self; @@ -1066,10 +1012,7 @@ uba_attach(parent, self, aux) struct uba_regs *ubar = (struct uba_regs *)sa->nexaddr; struct uba_softc *sc = (struct uba_softc *)self; vm_offset_t min, max, ubaphys, ubaiophys; -#if DW780 || DWBUA - struct uba_regs *vubp = sc->uh_uba; -#endif - void ubascan(); + extern struct ivec_dsp idsptch; printf("\n"); /* @@ -1084,13 +1027,13 @@ uba_attach(parent, self, aux) sc->uh_memsize = UBAPAGES; sc->uh_iopage = (void *)min + (sc->uh_memsize * NBPG); sc->uh_iarea = (void *)scb + NBPG + sa->nexinfo * NBPG; + sc->uh_resno = 0; /* * Create interrupt dispatchers for this uba. */ #define NO_IVEC 128 { vm_offset_t iarea; - extern struct ivec_dsp idsptch; int i; iarea = kmem_alloc(kernel_map, @@ -1100,13 +1043,34 @@ uba_attach(parent, self, aux) for (i = 0; i < NO_IVEC; i++) { bcopy(&idsptch, &sc->uh_idsp[i], sizeof(struct ivec_dsp)); - sc->uh_idsp[i].pushlarg = sa->nexinfo; + sc->uh_idsp[i].pushlarg = sc->uh_dev.dv_unit; sc->uh_idsp[i].hoppaddr = ubastray; sc->uh_iarea[i] = (unsigned int)&sc->uh_idsp[i]; } } switch (cpunumber) { +#if VAX780 || VAX8600 + case VAX_780: + case VAX_8600: + sc->uh_mr = (void *)ubar->uba_map; + sc->uh_type = DW780; + sc->uh_physuba = (struct uba_regs *)kvtophys(sa->nexaddr); + if (parent->dv_unit == 0) { + ubaphys = UMEMA8600(sa->nexinfo); + ubaiophys = UMEMA8600(sa->nexinfo) + (UBAPAGES * NBPG); + } else { + ubaphys = UMEMB8600(sa->nexinfo); + ubaiophys = UMEMB8600(sa->nexinfo) + (UBAPAGES * NBPG); + } + bcopy(&idsptch, &sc->uh_dw780, sizeof(struct ivec_dsp)); + sc->uh_dw780.pushlarg = sc->uh_dev.dv_unit; + sc->uh_dw780.hoppaddr = uba_dw780int; + scb->scb_nexvec[0][sa->nexnum] = scb->scb_nexvec[1][sa->nexnum] + = scb->scb_nexvec[2][sa->nexnum] + = scb->scb_nexvec[3][sa->nexnum] = &sc->uh_dw780; + break; +#endif #if VAX750 case VAX_750: sc->uh_mr = (void *)ubar->uba_map; @@ -1128,6 +1092,9 @@ uba_attach(parent, self, aux) ubaiophys = QIOPAGE630; break; #endif + default: + ubaphys = QMEM630; + ubaiophys = QIOPAGE630; }; break; #endif @@ -1140,6 +1107,9 @@ uba_attach(parent, self, aux) ubaiophys = QIOPAGE630; /* XXX */ break; #endif + default: + printf("Bad luck, this cputype does not support UBA's\n"); + return; }; /* * Map uba space in kernel virtual; especially i/o space. @@ -1170,14 +1140,14 @@ uba_attach(parent, self, aux) sc->uh_lastiv = 0x200; #ifdef DWBUA - if (uhp->uh_type == DWBUA) - BUA(vubp)->bua_offset = (int)uhp->uh_vec - (int)&scb[0]; + if (sc->uh_type == DWBUA) + BUA(ubar)->bua_offset = (int)sc->uh_vec - (int)&scb[0]; #endif #ifdef DW780 - if (uhp->uh_type == DW780) { - vubp->uba_sr = vubp->uba_sr; - vubp->uba_cr = UBACR_IFS|UBACR_BRIE; + if (sc->uh_type == DW780) { + ubar->uba_sr = ubar->uba_sr; + ubar->uba_cr = UBACR_IFS|UBACR_BRIE; } #endif #ifdef notyet @@ -1197,14 +1167,14 @@ uba_attach(parent, self, aux) /* * Now start searching for devices. */ - unifind(sc, ubaiophys); /* Some devices are not yet converted */ + unifind(sc, (caddr_t)ubaiophys);/* Some devices are not yet converted */ config_scan(ubascan,self); #ifdef DW780 - if (uhp->uh_type == DW780) - uhp->uh_uba->uba_cr = UBACR_IFS | UBACR_BRIE | + if (sc->uh_type == DW780) + ubar->uba_cr = UBACR_IFS | UBACR_BRIE | UBACR_USEFIE | UBACR_SUEFIE | - (uhp->uh_uba->uba_cr & 0x7c000000); + (ubar->uba_cr & 0x7c000000); #endif } @@ -1217,27 +1187,29 @@ ubascan(parent, match) struct device *dev = match; struct cfdata *cf = dev->dv_cfdata; struct uba_softc *sc = (struct uba_softc *)parent; + volatile struct uba_regs *ubar = sc->uh_uba; struct uba_attach_args ua; int i; ua.ua_addr = (caddr_t)ubaddr(sc, cf->cf_loc[0]); + ua.ua_reset = NULL; if (badaddr(ua.ua_addr, 2)) goto forgetit; #ifdef DW780 - if (uhp->uh_type == DW780 && vubp->uba_sr) { - vubp->uba_sr = vubp->uba_sr; - continue; + if (sc->uh_type == DW780 && ubar->uba_sr) { + ubar->uba_sr = ubar->uba_sr; + goto forgetit; } #endif rcvec = 0x200; - i = (*cf->cf_driver->cd_match) (parent, dev, &ua); + i = (*cf->cf_attach->ca_match) (parent, dev, &ua); #ifdef DW780 - if (uhp->uh_type == DW780 && vubp->uba_sr) { - vubp->uba_sr = vubp->uba_sr; - continue; + if (sc->uh_type == DW780 && ubar->uba_sr) { + ubar->uba_sr = ubar->uba_sr; + goto forgetit; } #endif if (i == 0) @@ -1247,7 +1219,15 @@ ubascan(parent, match) goto fail; sc->uh_idsp[rcvec].hoppaddr = ua.ua_ivec; - sc->uh_idsp[rcvec].pushlarg = ua.ua_iarg; + sc->uh_idsp[rcvec].pushlarg = dev->dv_unit; + if (ua.ua_reset) { /* device wants ubaeset */ + if (sc->uh_resno == 0) { + sc->uh_reset = malloc(1024, M_DEVBUF, M_NOWAIT); + sc->uh_resarg = malloc(256, M_DEVBUF, M_NOWAIT); + } + sc->uh_resarg[sc->uh_resno] = dev->dv_unit; + sc->uh_reset[sc->uh_resno++] = ua.ua_reset; + } ua.ua_br = rbr; ua.ua_cvec = rcvec; ua.ua_iaddr = dev->dv_cfdata->cf_loc[0]; @@ -1257,13 +1237,33 @@ ubascan(parent, match) fail: printf("%s at %s csr %o %s\n", dev->dv_cfdata->cf_driver->cd_name, - parent->dv_xname, dev->dv_cfdata->cf_loc[0] << 2, + parent->dv_xname, dev->dv_cfdata->cf_loc[0], rcvec ? "didn't interrupt\n" : "zero vector\n"); forgetit: free(dev, M_DEVBUF); } +/* + * Called when a device needs more than one interrupt vector. + * (Like DHU11, DMF32). Argument is the device's softc, vector + * number and a function pointer to the interrupt catcher. + */ +void +ubasetvec(dev, vec, func) + struct device *dev; + int vec; + void (*func) __P((int)); +{ + struct uba_softc *sc = (void *)dev->dv_parent; + + sc->uh_idsp[vec].hoppaddr = func; + sc->uh_idsp[vec].pushlarg = dev->dv_unit; +} + +/* + * Print out some interesting info common to all unibus devices. + */ int ubaprint(aux, uba) void *aux; diff --git a/sys/arch/vax/uba/ubareg.h b/sys/arch/vax/uba/ubareg.h index f654615f127..be7dd1ab475 100644 --- a/sys/arch/vax/uba/ubareg.h +++ b/sys/arch/vax/uba/ubareg.h @@ -223,7 +223,7 @@ struct uba_regs { #define UBADPR_BS 0x007f0000 /* buffer state field */ #define UBADPR_BUBA 0x0000ffff /* buffered UNIBUS address */ #define UBA_PURGE780(uba, bdp) \ - ((uba)->uba_dpr[bdp] |= UBADPR_BNE) + ((uba)->uba_dpr[(int)bdp] |= UBADPR_BNE) #else #define UBA_PURGE780(uba, bdp) #endif @@ -234,8 +234,8 @@ struct uba_regs { #define UBADPR_PURGE 0x00000001 /* purge bdp */ /* the DELAY is for a hardware problem */ #define UBA_PURGE750(uba, bdp) { \ - ((uba)->uba_dpr[bdp] |= (UBADPR_PURGE|UBADPR_NXM|UBADPR_UCE)); \ - {int N=8;while(N--);} \ + ((uba)->uba_dpr[(int)bdp] |= (UBADPR_PURGE|UBADPR_NXM|UBADPR_UCE)); \ + {volatile int N=8;while(N--);} \ } #else #define UBA_PURGE750(uba, bdp) @@ -317,7 +317,7 @@ struct uba_regs { #define UMEM8200(i) (0x20400000+(i)*0x40000) #endif -#if VAX8600 +#if VAX8600 || VAX780 #define UMEMA8600(i) (0x20100000+(i)*0x40000) #define UMEMB8600(i) (0x22100000+(i)*0x40000) #endif diff --git a/sys/arch/vax/uba/ubavar.h b/sys/arch/vax/uba/ubavar.h index 23d190ebcc6..1cc8ea8ce9e 100644 --- a/sys/arch/vax/uba/ubavar.h +++ b/sys/arch/vax/uba/ubavar.h @@ -1,4 +1,4 @@ -/* $NetBSD: ubavar.h,v 1.8 1995/12/01 19:23:01 ragge Exp $ */ +/* $NetBSD: ubavar.h,v 1.15 1996/04/08 18:37:36 ragge Exp $ */ /* * Copyright (c) 1982, 1986 Regents of the University of California. @@ -44,8 +44,10 @@ * Each unibus device has a uba_device structure. */ -#include "sys/buf.h" -#include "sys/device.h" +#include <sys/buf.h> +#include <sys/device.h> + +#include <machine/trap.h> /* For struct ivec_dsp */ /* * Per-uba structure. * @@ -76,7 +78,9 @@ struct uba_softc { int uh_memsize; /* size of uba memory, pages */ caddr_t uh_mem; /* start of uba memory address space */ caddr_t uh_iopage; /* start of uba io page */ - void (**Nuh_vec)(); /* interrupt vector */ + void (**uh_reset) __P((int));/* UBA reset function array */ + int *uh_resarg; /* array of ubareset args */ + int uh_resno; /* Number of devices to reset */ struct ivec_dsp *uh_idsp; /* Interrupt dispatch area */ u_int *uh_iarea; /* Interrupt vector array */ struct uba_device *uh_actf; /* head of queue to transfer */ @@ -95,6 +99,7 @@ struct uba_softc { int uh_lastmem; /* limit of any unibus memory */ #define UAMSIZ 100 struct map *uh_map; /* register free map */ + struct ivec_dsp uh_dw780; /* Interrupt handles for DW780 */ }; /* given a pointer to uba_regs, find DWBUA registers */ @@ -117,7 +122,7 @@ struct uba_ctlr { short um_ctlr; /* controller index in driver */ short um_ubanum; /* the uba it is on */ short um_alive; /* controller exists */ - void (*um_intr)(); /* interrupt handler(s) */ + void (*um_intr) __P((int)); /* interrupt handler(s) XXX */ caddr_t um_addr; /* address of device in i/o space */ struct uba_softc *um_hd; /* the driver saves the prototype command here for use in its go routine */ @@ -149,7 +154,7 @@ struct uba_device { short ui_ctlr; /* mass ctlr number; -1 if none */ short ui_ubanum; /* the uba it is on */ short ui_slave; /* slave on controller */ - void (*ui_intr)(); /* interrupt handler(s) */ + void (*ui_intr) __P((int)); /* interrupt handler(s) XXX */ caddr_t ui_addr; /* address of device in i/o space */ short ui_dk; /* if init 1 set to number for iostat */ int ui_flags; /* parameter from system specification */ @@ -171,10 +176,15 @@ struct uba_device { * These are used at boot time by the configuration program. */ struct uba_driver { - int (*ud_probe)(); /* see if a driver is really there */ - int (*ud_slave)(); /* see if a slave is there */ - int (*ud_attach)(); /* setup driver for a slave */ - int (*ud_dgo)(); /* fill csr/ba to start transfer */ + /* see if a driver is really there XXX*/ + int (*ud_probe) __P((caddr_t, int, struct uba_ctlr *, + struct uba_softc *)); + /* see if a slave is there XXX */ + int (*ud_slave) __P((struct uba_device *, caddr_t)); + /* setup driver for a slave XXX */ + void (*ud_attach) __P((struct uba_device *)); + /* fill csr/ba to start transfer XXX */ + void (*ud_dgo) __P((struct uba_ctlr *)); u_short *ud_addr; /* device csr addresses */ char *ud_dname; /* name of a device */ struct uba_device **ud_dinfo; /* backpointers to ubdinit structs */ @@ -182,7 +192,8 @@ struct uba_driver { struct uba_ctlr **ud_minfo; /* backpointers to ubminit structs */ short ud_xclu; /* want exclusive use of bdp's */ short ud_keepbdp; /* hang on to bdp's once allocated */ - int (*ud_ubamem)(); /* see if dedicated memory is present */ + int (*ud_ubamem) __P((struct uba_device *, int)); + /* see if dedicated memory is present */ }; /* @@ -191,8 +202,10 @@ struct uba_driver { */ struct uba_attach_args { caddr_t ua_addr; - void (*ua_ivec)(); - int ua_iarg; + /* Pointer to int routine, filled in by probe*/ + void (*ua_ivec) __P((int)); + /* UBA reset routine, filled in by probe */ + void (*ua_reset) __P((int)); int ua_iaddr; int ua_br; int ua_cvec; @@ -242,9 +255,16 @@ struct ubinfo { extern struct uba_ctlr ubminit[]; extern struct uba_device ubdinit[]; -extern struct cfdriver ubacd; +extern struct cfdriver uba_cd; void ubainit __P((struct uba_softc *)); +void ubasetvec __P((struct device *, int, void (*) __P((int)))); +int uballoc __P((int, caddr_t, int, int)); +void ubarelse __P((int, int *)); +int ubaqueue __P((struct uba_device *, int)); +void ubadone __P((struct uba_ctlr *)); +void ubareset __P((int)); +int ubasetup __P((int, struct buf *, int)); #endif /* _KERNEL */ #endif !LOCORE diff --git a/sys/arch/vax/uba/uda.c b/sys/arch/vax/uba/uda.c index 11ea94f68f7..cb541c4bcb9 100644 --- a/sys/arch/vax/uba/uda.c +++ b/sys/arch/vax/uba/uda.c @@ -1,4 +1,4 @@ -/* $NetBSD: uda.c,v 1.10 1995/12/13 19:02:47 ragge Exp $ */ +/* $NetBSD: uda.c,v 1.15 1996/03/17 22:56:50 ragge Exp $ */ /* * Copyright (c) 1988 Regents of the University of California. * All rights reserved. @@ -85,35 +85,35 @@ #define STEP3MASK ALLSTEPS #define STEP3GOOD UDA_STEP4 -#include "sys/param.h" -#include "sys/systm.h" -#include "sys/buf.h" -#include "sys/conf.h" -#include "sys/file.h" -#include "sys/ioctl.h" -#include "sys/proc.h" -#include "sys/user.h" -#include "sys/map.h" -#include "sys/device.h" -#include "sys/dkstat.h" -#include "sys/disklabel.h" -#include "sys/syslog.h" -#include "sys/stat.h" - -#include "machine/pte.h" -#include "machine/sid.h" -#include "machine/cpu.h" - -#include "vax/uba/ubareg.h" -#include "vax/uba/ubavar.h" +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/buf.h> +#include <sys/conf.h> +#include <sys/file.h> +#include <sys/ioctl.h> +#include <sys/proc.h> +#include <sys/user.h> +#include <sys/map.h> +#include <sys/device.h> +#include <sys/dkstat.h> +#include <sys/disklabel.h> +#include <sys/syslog.h> +#include <sys/stat.h> + +#include <machine/pte.h> +#include <machine/sid.h> +#include <machine/cpu.h> + +#include <vax/uba/ubareg.h> +#include <vax/uba/ubavar.h> #define NRSP (1 << NRSPL2) #define NCMD (1 << NCMDL2) -#include "vax/uba/udareg.h" -#include "vax/vax/mscp.h" -#include "vax/vax/mscpvar.h" -#include "machine/mtpr.h" +#include <vax/uba/udareg.h> +#include <vax/vax/mscp.h> +#include <vax/vax/mscpvar.h> +#include <machine/mtpr.h> extern int cold; @@ -128,7 +128,7 @@ extern int cold; if ((udaddr->udasa & mask) != result) { \ volatile int count = 0; \ while ((udaddr->udasa & mask) != result) { \ - DELAY(1000); \ + DELAY(10000); \ count += 1; \ if (count > DELAYTEN) \ break; \ @@ -177,8 +177,12 @@ struct udastats { int udamatch __P((struct device *, void *, void *)); void uda_attach __P((struct device *, struct device *, void *)); -struct cfdriver udacd = { - NULL, "uda", udamatch, uda_attach, DV_DULL, sizeof(struct device) +struct cfdriver uda_cd = { + NULL, "uda", DV_DULL +}; + +struct cfattach uda_ca = { + sizeof(struct device), udamatch, uda_attach }; /* @@ -298,7 +302,6 @@ void udawatch(); /* watchdog timer */ * Externals */ int hz; -extern struct cfdriver ubacd; /* * Poke at a supposed UDA50 to see if it is there. @@ -321,10 +324,11 @@ uda_attach(parent, self, aux) { } -udaprobe(reg, ctlr, um) +udaprobe(reg, ctlr, um, uhp) caddr_t reg; int ctlr; struct uba_ctlr *um; + struct uba_softc *uhp; { struct uda_softc *sc; volatile struct udadevice *udaddr; @@ -347,7 +351,6 @@ udaprobe(reg, ctlr, um) if (MACHID(cpu_type) == VAX_750) udadriver.ud_keepbdp = 1; #endif -/* printf("udaprobe\n"); */ probeum = um; /* remember for udaslave() */ /* * Set up the controller-specific generic MSCP driver info. @@ -366,12 +369,7 @@ udaprobe(reg, ctlr, um) mi->mi_rsp.mri_size = NRSP; mi->mi_rsp.mri_desc = sc->sc_uda.uda_ca.ca_rspdsc; mi->mi_rsp.mri_ring = sc->sc_uda.uda_rsp; -#ifdef ragge - mi->mi_wtab.b_actf = NULL; -#else mi->mi_wtab.b_actf = &mi->mi_wtab; -#endif -/* Was: mi->mi_wtab.av_forw = mi->mi_wtab.av_back = &mi->mi_wtab; */ /* * More controller specific variables. Again, this should @@ -386,7 +384,7 @@ udaprobe(reg, ctlr, um) * problem; but it would be easily fixed if we had a controller * attach routine. Sigh. */ - ubasc = ubacd.cd_devs[0]; /* XXX */ + ubasc = uhp; sc->sc_ivec = ubasc->uh_lastiv -= 4; udaddr = (struct udadevice *) reg; @@ -488,7 +486,7 @@ again: return (0); timeout = 1000; while (timeout-- > 0) { - DELAY(3000); + DELAY(10000); if (sc->sc_state == ST_RUN) goto findunit; } @@ -677,7 +675,7 @@ udainit(ctlr) int ctlr; { register struct uda_softc *sc; - register struct udadevice *udaddr; + volatile struct udadevice *udaddr; struct uba_ctlr *um; int timo, ubinfo, count, i, wait_status; unsigned short hej; @@ -927,7 +925,7 @@ uda_rainit(ui, flags) if (cold) { i = 1000; while ((ui->ui_flags & UNIT_ONLINE) == 0) { - DELAY(1000); + DELAY(10000); if (i-- < 0) break; } @@ -2098,7 +2096,7 @@ udadump(dev) * comes on, or ten seconds pass without response, return true (error). */ udadumpwait(udaddr, bits) - register struct udadevice *udaddr; + volatile struct udadevice *udaddr; register int bits; { register int timo = todr() + 1000; |