summaryrefslogtreecommitdiff
path: root/sys/arch/vax/uba
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/vax/uba')
-rw-r--r--sys/arch/vax/uba/dhu.c858
-rw-r--r--sys/arch/vax/uba/dhureg.h140
-rw-r--r--sys/arch/vax/uba/dz.c819
-rw-r--r--sys/arch/vax/uba/dzreg.h116
-rw-r--r--sys/arch/vax/uba/tmscp.c171
-rw-r--r--sys/arch/vax/uba/ts.c140
-rw-r--r--sys/arch/vax/uba/uba.c476
-rw-r--r--sys/arch/vax/uba/ubareg.h8
-rw-r--r--sys/arch/vax/uba/ubavar.h48
-rw-r--r--sys/arch/vax/uba/uda.c82
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;